# HG changeset patch
# User Jimi Xenidis <jimix@xxxxxxxxxxxxxx>
# Node ID 877560e56eabbc7f05f650fba912fd0611b930f6
# Parent e06e2cca9f39d56344ec96b90ad4a2405b247996
[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@xxxxxxxxxxxxxx>
---
xen/arch/powerpc/Makefile | 1
xen/arch/powerpc/backtrace.c | 194 ++++++++++++++++++++++++++++++++++++
xen/arch/powerpc/exceptions.c | 2
xen/arch/powerpc/memory.c | 3
xen/arch/powerpc/setup.c | 3
xen/include/asm-powerpc/processor.h | 1
6 files changed, 201 insertions(+), 3 deletions(-)
diff -r e06e2cca9f39 -r 877560e56eab xen/arch/powerpc/Makefile
--- a/xen/arch/powerpc/Makefile Tue Aug 22 17:26:36 2006 -0400
+++ b/xen/arch/powerpc/Makefile Wed Aug 23 04:59:10 2006 -0400
@@ -6,6 +6,7 @@ subdir-y += papr
subdir-y += papr
obj-y += audit.o
+obj-y += backtrace.o
obj-y += bitops.o
obj-y += boot_of.o
obj-y += dart.o
diff -r e06e2cca9f39 -r 877560e56eab xen/arch/powerpc/exceptions.c
--- a/xen/arch/powerpc/exceptions.c Tue Aug 22 17:26:36 2006 -0400
+++ b/xen/arch/powerpc/exceptions.c Wed Aug 23 04:59:10 2006 -0400
@@ -82,6 +82,8 @@ void program_exception(struct cpu_user_r
show_registers(regs);
printk("dar 0x%016lx, dsisr 0x%08x\n", mfdar(), mfdsisr());
printk("hid4 0x%016lx\n", regs->hid4);
+ printk("---[ backtrace ]---\n");
+ show_backtrace(regs->gprs[1], regs->lr, regs->pc);
panic("%s: 0x%lx\n", __func__, cookie);
#endif /* CRASH_DEBUG */
}
diff -r e06e2cca9f39 -r 877560e56eab xen/arch/powerpc/memory.c
--- a/xen/arch/powerpc/memory.c Tue Aug 22 17:26:36 2006 -0400
+++ b/xen/arch/powerpc/memory.c Wed Aug 23 04:59:10 2006 -0400
@@ -176,9 +176,6 @@ void memory_init(module_t *mod, int mcou
"for heap (0x%lx)\n", _start, heap_start);
}
- /* we give the first RMA to the hypervisor */
- xenheap_phys_end = rma_size(cpu_rma_order());
-
/* allow everything else to be allocated */
total_pages = 0;
ofd_walk_mem((void *)oftree, heap_init);
diff -r e06e2cca9f39 -r 877560e56eab xen/arch/powerpc/setup.c
--- a/xen/arch/powerpc/setup.c Tue Aug 22 17:26:36 2006 -0400
+++ b/xen/arch/powerpc/setup.c Wed Aug 23 04:59:10 2006 -0400
@@ -296,6 +296,9 @@ static void __init __start_xen(multiboot
console_start_sync();
#endif
+ /* we give the first RMA to the hypervisor */
+ xenheap_phys_end = rma_size(cpu_rma_order());
+
/* Check that we have at least one Multiboot module. */
if (!(mbi->flags & MBI_MODULES) || (mbi->mods_count == 0)) {
panic("FATAL ERROR: Require at least one Multiboot module.\n");
diff -r e06e2cca9f39 -r 877560e56eab xen/include/asm-powerpc/processor.h
--- a/xen/include/asm-powerpc/processor.h Tue Aug 22 17:26:36 2006 -0400
+++ b/xen/include/asm-powerpc/processor.h Wed Aug 23 04:59:10 2006 -0400
@@ -39,6 +39,7 @@ struct cpu_user_regs;
struct cpu_user_regs;
extern void show_registers(struct cpu_user_regs *);
extern void show_execution_state(struct cpu_user_regs *);
+extern void show_backtrace(ulong sp, ulong lr, ulong pc);
extern unsigned int cpu_rma_order(void);
extern void cpu_initialize(int cpuid);
extern void cpu_init_vcpu(struct vcpu *);
diff -r e06e2cca9f39 -r 877560e56eab xen/arch/powerpc/backtrace.c
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/xen/arch/powerpc/backtrace.c Wed Aug 23 04:59:10 2006 -0400
@@ -0,0 +1,194 @@
+/*
+ * Routines providing a simple monitor for use on the PowerMac.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <xen/config.h>
+#include <xen/lib.h>
+#include <xen/console.h>
+#include <xen/sched.h>
+
+/* Shamelessly lifted from Linux Xmon try to keep pristene */
+#ifdef __powerpc64__
+#define LRSAVE_OFFSET 0x10
+#define REG_FRAME_MARKER 0x7265677368657265ul /* "regshere" */
+#define MARKER_OFFSET 0x60
+#define REGS_OFFSET 0x70
+#define REG "%016lX"
+#else
+#define LRSAVE_OFFSET 4
+#define REG_FRAME_MARKER 0x72656773
+#define MARKER_OFFSET 8
+#define REGS_OFFSET 16
+#define REG "%08lX"
+#endif
+
+#define TRAP(regs) ((regs)->entry_vector & ~0xF)
+static int xmon_depth_to_print = 64;
+
+/* Very cheap human name for vector lookup. */
+static
+const char *getvecname(unsigned long vec)
+{
+ char *ret;
+
+ switch (vec) {
+ case 0x100: ret = "(System Reset)"; break;
+ case 0x200: ret = "(Machine Check)"; break;
+ case 0x300: ret = "(Data Access)"; break;
+ case 0x380: ret = "(Data SLB Access)"; break;
+ case 0x400: ret = "(Instruction Access)"; break;
+ case 0x480: ret = "(Instruction SLB Access)"; break;
+ case 0x500: ret = "(Hardware Interrupt)"; break;
+ case 0x600: ret = "(Alignment)"; break;
+ case 0x700: ret = "(Program Check)"; break;
+ case 0x800: ret = "(FPU Unavailable)"; break;
+ case 0x900: ret = "(Decrementer)"; break;
+ case 0xc00: ret = "(System Call)"; break;
+ case 0xd00: ret = "(Single Step)"; break;
+ case 0xf00: ret = "(Performance Monitor)"; break;
+ case 0xf20: ret = "(Altivec Unavailable)"; break;
+ case 0x1300: ret = "(Instruction Breakpoint)"; break;
+ default: ret = "";
+ }
+ return ret;
+}
+
+static int mread(unsigned long adrs, void *buf, int size)
+{
+ memcpy(buf, (void *)adrs, size);
+ return size;
+}
+
+static void get_function_bounds(unsigned long pc, unsigned long *startp,
+ unsigned long *endp)
+{
+ *startp = pc;
+ *endp = pc;
+}
+
+/* Print an address in numeric and symbolic form (if possible) */
+static void xmon_print_symbol(unsigned long address, const char *mid,
+ const char *after)
+{
+ char *modname;
+ const char *name = NULL;
+ unsigned long offset, size;
+
+ printf(REG, address);
+#if 0
+ if (setjmp(bus_error_jmp) == 0) {
+ catch_memory_errors = 1;
+ sync();
+ name = kallsyms_lookup(address, &size, &offset, &modname,
+ tmpstr);
+ sync();
+ /* wait a little while to see if we get a machine check */
+ __delay(200);
+ }
+
+ catch_memory_errors = 0;
+#endif
+ if (name) {
+ printf("%s%s+%#lx/%#lx", mid, name, offset, size);
+ if (modname)
+ printf(" [%s]", modname);
+ }
+ printf("%s", after);
+}
+
+static void backtrace(
+ unsigned long sp, unsigned long lr, unsigned long pc)
+{
+ unsigned long ip;
+ unsigned long newsp;
+ unsigned long marker;
+ int count = 0;
+ struct cpu_user_regs regs;
+
+ do {
+ if (sp > xenheap_phys_end) {
+ if (sp != 0)
+ printf("SP (%lx) is not in xen space\n", sp);
+ break;
+ }
+
+ if (!mread(sp + LRSAVE_OFFSET, &ip, sizeof(unsigned long))
+ || !mread(sp, &newsp, sizeof(unsigned long))) {
+ printf("Couldn't read stack frame at %lx\n", sp);
+ break;
+ }
+
+ /*
+ * For the first stack frame, try to work out if
+ * LR and/or the saved LR value in the bottommost
+ * stack frame are valid.
+ */
+ if ((pc | lr) != 0) {
+ unsigned long fnstart, fnend;
+ unsigned long nextip;
+ int printip = 1;
+
+ get_function_bounds(pc, &fnstart, &fnend);
+ nextip = 0;
+ if (newsp > sp)
+ mread(newsp + LRSAVE_OFFSET, &nextip,
+ sizeof(unsigned long));
+ if (lr == ip) {
+ if (lr >= xenheap_phys_end
+ || (fnstart <= lr && lr < fnend))
+ printip = 0;
+ } else if (lr == nextip) {
+ printip = 0;
+ } else if (lr < xenheap_phys_end
+ && !(fnstart <= lr && lr < fnend)) {
+ printf("[link register ] ");
+ xmon_print_symbol(lr, " ", "\n");
+ }
+ if (printip) {
+ printf("["REG"] ", sp);
+ xmon_print_symbol(ip, " ", " (unreliable)\n");
+ }
+ pc = lr = 0;
+
+ } else {
+ printf("["REG"] ", sp);
+ xmon_print_symbol(ip, " ", "\n");
+ }
+
+ /* Look for "regshere" marker to see if this is
+ an exception frame. */
+ if (mread(sp + MARKER_OFFSET, &marker, sizeof(unsigned long))
+ && marker == REG_FRAME_MARKER) {
+ if (mread(sp + REGS_OFFSET, ®s, sizeof(regs))
+ != sizeof(regs)) {
+ printf("Couldn't read registers at %lx\n",
+ sp + REGS_OFFSET);
+ break;
+ }
+ printf("--- Exception: %x %s at ", regs.entry_vector,
+ getvecname(TRAP(®s)));
+ pc = regs.pc;
+ lr = regs.lr;
+ xmon_print_symbol(pc, " ", "\n");
+ }
+
+ if (newsp == 0)
+ break;
+
+ sp = newsp;
+ } while (count++ < xmon_depth_to_print);
+}
+
+void show_backtrace(ulong sp, ulong lr, ulong pc)
+{
+ console_start_sync();
+ backtrace(sp, lr, pc);
+ console_end_sync();
+}
_______________________________________________
Xen-ppc-devel mailing list
Xen-ppc-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-ppc-devel
|