direct-io.hg

changeset 11374:20c988c92bee

[XEN][POWERPC] add show_backtrace()

Total rip off of xmon_show_stack() from Linux:arch/powerpc/xmon/xmon.c.
This will allow a numeric only stack traceback of Xen exectution.
Currently only triggered by BUG() et.al.

Signed-off-by: Jimi Xenidis <jimix@watson.ibm.com>
Signed-off-by: Hollis Blanchard <hollisb@us.ibm.com>
author Jimi Xenidis <jimix@watson.ibm.com>
date Wed Aug 23 04:59:10 2006 -0400 (2006-08-23)
parents 980ff1125446
children 3a195d95c615
files xen/arch/powerpc/Makefile xen/arch/powerpc/backtrace.c xen/arch/powerpc/exceptions.c xen/arch/powerpc/memory.c xen/arch/powerpc/setup.c xen/include/asm-powerpc/processor.h
line diff
     1.1 --- a/xen/arch/powerpc/Makefile	Tue Aug 22 17:20:58 2006 -0400
     1.2 +++ b/xen/arch/powerpc/Makefile	Wed Aug 23 04:59:10 2006 -0400
     1.3 @@ -6,6 +6,7 @@ subdir-$(HAS_PPC64) += powerpc64
     1.4  subdir-y += papr
     1.5  
     1.6  obj-y += audit.o
     1.7 +obj-y += backtrace.o
     1.8  obj-y += bitops.o
     1.9  obj-y += boot_of.o
    1.10  obj-y += dart.o
     2.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     2.2 +++ b/xen/arch/powerpc/backtrace.c	Wed Aug 23 04:59:10 2006 -0400
     2.3 @@ -0,0 +1,194 @@
     2.4 +/*
     2.5 + * Routines providing a simple monitor for use on the PowerMac.
     2.6 + *
     2.7 + * Copyright (C) 1996-2005 Paul Mackerras.
     2.8 + *
     2.9 + *      This program is free software; you can redistribute it and/or
    2.10 + *      modify it under the terms of the GNU General Public License
    2.11 + *      as published by the Free Software Foundation; either version
    2.12 + *      2 of the License, or (at your option) any later version.
    2.13 + */
    2.14 +
    2.15 +#include <xen/config.h>
    2.16 +#include <xen/lib.h>
    2.17 +#include <xen/console.h>
    2.18 +#include <xen/sched.h>
    2.19 +
    2.20 +/* Shamelessly lifted from Linux Xmon try to keep pristene */
    2.21 +#ifdef __powerpc64__
    2.22 +#define LRSAVE_OFFSET		0x10
    2.23 +#define REG_FRAME_MARKER	0x7265677368657265ul	/* "regshere" */
    2.24 +#define MARKER_OFFSET		0x60
    2.25 +#define REGS_OFFSET		0x70
    2.26 +#define REG "%016lX"
    2.27 +#else
    2.28 +#define LRSAVE_OFFSET		4
    2.29 +#define REG_FRAME_MARKER	0x72656773
    2.30 +#define MARKER_OFFSET		8
    2.31 +#define REGS_OFFSET		16
    2.32 +#define REG "%08lX"
    2.33 +#endif
    2.34 +
    2.35 +#define TRAP(regs) ((regs)->entry_vector & ~0xF)
    2.36 +static int xmon_depth_to_print = 64;
    2.37 +
    2.38 +/* Very cheap human name for vector lookup. */
    2.39 +static
    2.40 +const char *getvecname(unsigned long vec)
    2.41 +{
    2.42 +	char *ret;
    2.43 +
    2.44 +	switch (vec) {
    2.45 +	case 0x100:	ret = "(System Reset)"; break;
    2.46 +	case 0x200:	ret = "(Machine Check)"; break;
    2.47 +	case 0x300:	ret = "(Data Access)"; break;
    2.48 +	case 0x380:	ret = "(Data SLB Access)"; break;
    2.49 +	case 0x400:	ret = "(Instruction Access)"; break;
    2.50 +	case 0x480:	ret = "(Instruction SLB Access)"; break;
    2.51 +	case 0x500:	ret = "(Hardware Interrupt)"; break;
    2.52 +	case 0x600:	ret = "(Alignment)"; break;
    2.53 +	case 0x700:	ret = "(Program Check)"; break;
    2.54 +	case 0x800:	ret = "(FPU Unavailable)"; break;
    2.55 +	case 0x900:	ret = "(Decrementer)"; break;
    2.56 +	case 0xc00:	ret = "(System Call)"; break;
    2.57 +	case 0xd00:	ret = "(Single Step)"; break;
    2.58 +	case 0xf00:	ret = "(Performance Monitor)"; break;
    2.59 +	case 0xf20:	ret = "(Altivec Unavailable)"; break;
    2.60 +	case 0x1300:	ret = "(Instruction Breakpoint)"; break;
    2.61 +	default: ret = "";
    2.62 +	}
    2.63 +	return ret;
    2.64 +}
    2.65 +
    2.66 +static int mread(unsigned long adrs, void *buf, int size)
    2.67 +{
    2.68 +    memcpy(buf, (void *)adrs, size);
    2.69 +    return size;
    2.70 +}
    2.71 +
    2.72 +static void get_function_bounds(unsigned long pc, unsigned long *startp,
    2.73 +				unsigned long *endp)
    2.74 +{
    2.75 +    *startp = pc;
    2.76 +    *endp = pc;
    2.77 +}
    2.78 +    
    2.79 +/* Print an address in numeric and symbolic form (if possible) */
    2.80 +static void xmon_print_symbol(unsigned long address, const char *mid,
    2.81 +                              const char *after)
    2.82 +{
    2.83 +	char *modname;
    2.84 +	const char *name = NULL;
    2.85 +	unsigned long offset, size;
    2.86 +
    2.87 +	printf(REG, address);
    2.88 +#if 0
    2.89 +	if (setjmp(bus_error_jmp) == 0) {
    2.90 +		catch_memory_errors = 1;
    2.91 +		sync();
    2.92 +		name = kallsyms_lookup(address, &size, &offset, &modname,
    2.93 +				       tmpstr);
    2.94 +		sync();
    2.95 +		/* wait a little while to see if we get a machine check */
    2.96 +		__delay(200);
    2.97 +	}
    2.98 +
    2.99 +	catch_memory_errors = 0;
   2.100 +#endif
   2.101 +	if (name) {
   2.102 +		printf("%s%s+%#lx/%#lx", mid, name, offset, size);
   2.103 +		if (modname)
   2.104 +			printf(" [%s]", modname);
   2.105 +	}
   2.106 +	printf("%s", after);
   2.107 +}
   2.108 +
   2.109 +static void backtrace(
   2.110 +    unsigned long sp, unsigned long lr, unsigned long pc)
   2.111 +{
   2.112 +	unsigned long ip;
   2.113 +	unsigned long newsp;
   2.114 +	unsigned long marker;
   2.115 +	int count = 0;
   2.116 +	struct cpu_user_regs regs;
   2.117 +
   2.118 +	do {
   2.119 +		if (sp > xenheap_phys_end) {
   2.120 +			if (sp != 0)
   2.121 +				printf("SP (%lx) is not in xen space\n", sp);
   2.122 +			break;
   2.123 +		}
   2.124 +
   2.125 +		if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
   2.126 +		    || !mread(sp, &newsp, sizeof(unsigned long))) {
   2.127 +			printf("Couldn't read stack frame at %lx\n", sp);
   2.128 +			break;
   2.129 +		}
   2.130 +
   2.131 +		/*
   2.132 +		 * For the first stack frame, try to work out if
   2.133 +		 * LR and/or the saved LR value in the bottommost
   2.134 +		 * stack frame are valid.
   2.135 +		 */
   2.136 +		if ((pc | lr) != 0) {
   2.137 +			unsigned long fnstart, fnend;
   2.138 +			unsigned long nextip;
   2.139 +			int printip = 1;
   2.140 +
   2.141 +			get_function_bounds(pc, &fnstart, &fnend);
   2.142 +			nextip = 0;
   2.143 +			if (newsp > sp)
   2.144 +				mread(newsp + LRSAVE_OFFSET, &nextip,
   2.145 +				      sizeof(unsigned long));
   2.146 +			if (lr == ip) {
   2.147 +				if (lr >= xenheap_phys_end
   2.148 +				    || (fnstart <= lr && lr < fnend))
   2.149 +					printip = 0;
   2.150 +			} else if (lr == nextip) {
   2.151 +				printip = 0;
   2.152 +			} else if (lr < xenheap_phys_end
   2.153 +                       && !(fnstart <= lr && lr < fnend)) {
   2.154 +				printf("[link register   ] ");
   2.155 +				xmon_print_symbol(lr, " ", "\n");
   2.156 +			}
   2.157 +			if (printip) {
   2.158 +				printf("["REG"] ", sp);
   2.159 +				xmon_print_symbol(ip, " ", " (unreliable)\n");
   2.160 +			}
   2.161 +			pc = lr = 0;
   2.162 +
   2.163 +		} else {
   2.164 +			printf("["REG"] ", sp);
   2.165 +			xmon_print_symbol(ip, " ", "\n");
   2.166 +		}
   2.167 +
   2.168 +		/* Look for "regshere" marker to see if this is
   2.169 +		   an exception frame. */
   2.170 +		if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
   2.171 +		    && marker == REG_FRAME_MARKER) {
   2.172 +			if (mread(sp + REGS_OFFSET, &regs, sizeof(regs))
   2.173 +			    != sizeof(regs)) {
   2.174 +				printf("Couldn't read registers at %lx\n",
   2.175 +				       sp + REGS_OFFSET);
   2.176 +				break;
   2.177 +			}
   2.178 +            printf("--- Exception: %x %s at ", regs.entry_vector,
   2.179 +			       getvecname(TRAP(&regs)));
   2.180 +			pc = regs.pc;
   2.181 +			lr = regs.lr;
   2.182 +			xmon_print_symbol(pc, " ", "\n");
   2.183 +		}
   2.184 +
   2.185 +		if (newsp == 0)
   2.186 +			break;
   2.187 +        
   2.188 +		sp = newsp;
   2.189 +	} while (count++ < xmon_depth_to_print);
   2.190 +}
   2.191 +
   2.192 +void show_backtrace(ulong sp, ulong lr, ulong pc)
   2.193 +{
   2.194 +    console_start_sync();
   2.195 +    backtrace(sp, lr, pc);
   2.196 +    console_end_sync();
   2.197 +}
     3.1 --- a/xen/arch/powerpc/exceptions.c	Tue Aug 22 17:20:58 2006 -0400
     3.2 +++ b/xen/arch/powerpc/exceptions.c	Wed Aug 23 04:59:10 2006 -0400
     3.3 @@ -82,6 +82,8 @@ void program_exception(struct cpu_user_r
     3.4      show_registers(regs);
     3.5      printk("dar 0x%016lx, dsisr 0x%08x\n", mfdar(), mfdsisr());
     3.6      printk("hid4 0x%016lx\n", regs->hid4);
     3.7 +    printk("---[ backtrace ]---\n");
     3.8 +    show_backtrace(regs->gprs[1], regs->lr, regs->pc);
     3.9      panic("%s: 0x%lx\n", __func__, cookie);
    3.10  #endif /* CRASH_DEBUG */
    3.11  }
     4.1 --- a/xen/arch/powerpc/memory.c	Tue Aug 22 17:20:58 2006 -0400
     4.2 +++ b/xen/arch/powerpc/memory.c	Wed Aug 23 04:59:10 2006 -0400
     4.3 @@ -176,9 +176,6 @@ void memory_init(module_t *mod, int mcou
     4.4                "for heap (0x%lx)\n", _start, heap_start);
     4.5      }
     4.6  
     4.7 -    /* we give the first RMA to the hypervisor */
     4.8 -    xenheap_phys_end = rma_size(cpu_rma_order());
     4.9 -
    4.10      /* allow everything else to be allocated */
    4.11      total_pages = 0;
    4.12      ofd_walk_mem((void *)oftree, heap_init);
     5.1 --- a/xen/arch/powerpc/setup.c	Tue Aug 22 17:20:58 2006 -0400
     5.2 +++ b/xen/arch/powerpc/setup.c	Wed Aug 23 04:59:10 2006 -0400
     5.3 @@ -295,6 +295,9 @@ static void __init __start_xen(multiboot
     5.4      console_start_sync();
     5.5  #endif
     5.6  
     5.7 +    /* we give the first RMA to the hypervisor */
     5.8 +    xenheap_phys_end = rma_size(cpu_rma_order());
     5.9 +
    5.10      /* Check that we have at least one Multiboot module. */
    5.11      if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
    5.12          panic("FATAL ERROR: Require at least one Multiboot module.\n");
     6.1 --- a/xen/include/asm-powerpc/processor.h	Tue Aug 22 17:20:58 2006 -0400
     6.2 +++ b/xen/include/asm-powerpc/processor.h	Wed Aug 23 04:59:10 2006 -0400
     6.3 @@ -39,6 +39,7 @@ struct vcpu;
     6.4  struct cpu_user_regs;
     6.5  extern void show_registers(struct cpu_user_regs *);
     6.6  extern void show_execution_state(struct cpu_user_regs *);
     6.7 +extern void show_backtrace(ulong sp, ulong lr, ulong pc);
     6.8  extern unsigned int cpu_rma_order(void);
     6.9  extern void cpu_initialize(int cpuid);
    6.10  extern void cpu_init_vcpu(struct vcpu *);