[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH ARM v6 14/14] mini-os: arm: show registers, stack and exception vector on fault
Signed-off-by: Thomas Leonard <talex5@xxxxxxxxx> --- Exit with SHUTDOWN_crash on BUG or fault (suggested by Ian Campbell). --- extras/mini-os/ARM-TODO.txt | 1 - extras/mini-os/arch/arm/arm32.S | 75 ++++++++++++++++++++++++++++--- extras/mini-os/arch/arm/panic.c | 98 +++++++++++++++++++++++++++++++++++++++++ 3 files changed, 166 insertions(+), 8 deletions(-) create mode 100644 extras/mini-os/arch/arm/panic.c diff --git a/extras/mini-os/ARM-TODO.txt b/extras/mini-os/ARM-TODO.txt index c85ee5b..27507cd 100644 --- a/extras/mini-os/ARM-TODO.txt +++ b/extras/mini-os/ARM-TODO.txt @@ -1,4 +1,3 @@ -* support abort exception handling ( and others ) * gic request_irq implementation, currently all IRQs all hardcoded in gic irq handler. * bind_* * add multiple cpu support (?) diff --git a/extras/mini-os/arch/arm/arm32.S b/extras/mini-os/arch/arm/arm32.S index 56429b1..fab9f9f 100644 --- a/extras/mini-os/arch/arm/arm32.S +++ b/extras/mini-os/arch/arm/arm32.S @@ -166,8 +166,69 @@ irqstack: .fill (1024), 4, 0x0 irqstack_end: +fault_dump: + .fill 18, 4, 0x0 @ On fault, we save the registers + CPSR + handler address + .popsection +fault: + cpsid aif @ Disable interrupts + + ldr r13, =fault_dump + stmia r13, {r0-r12} @ Dump the non-banked registers directly (well, unless from FIQ mode) + str r14, [r13, #15 << 2] @ Our r14 is the faulting r15 + mov r0, r13 + + @ Save the caller's CPSR (our SPSR) too. + mrs r1, SPSR + str r1, [r13, #16 << 2] + + @ Switch to the mode we came from to get r13 and r14. + @ If coming from user mode, use System mode instead so we're still + @ privileged. + and r1, r1, #0x1f @ r1 = SPSR mode + cmp r1, #0x10 @ If from User mode + moveq r1, #0x1f @ Then use System mode instead + + mrs r3, CPSR @ r3 = our CPSR + bic r2, r3, #0x1f + orr r2, r2, r1 + msr CPSR, r2 @ Change to mode r1 + + @ Save old mode's r13, r14 + str r13, [r0, #13 << 2] + str r14, [r0, #14 << 2] + + msr CPSR, r3 @ Back to fault mode + + ldr r1, [r0, #17 << 2] + sub r1, r1, #12 @ Fix to point at start of handler + str r1, [r0, #17 << 2] + + @ Call C code to format the register dump. + @ Clobbers the stack, but we're not going to return anyway. + ldr sp, =_boot_stack_end + bl dump_registers + b do_exit + +@ We want to store a unique value to identify this handler, without corrupting +@ any of the registers. So, we store r15 (which will point just after the branch). +@ Later, we subtract 12 so the user gets pointed at the start of the exception +@ handler. +#define FAULT(name) \ +.globl fault_##name; \ +fault_##name: \ + ldr r13, =fault_dump; \ + str r15, [r13, #17 << 2]; \ + b fault + +FAULT(reset) +FAULT(undefined_instruction) +FAULT(svc) +FAULT(prefetch_call) +FAULT(prefetch_abort) +FAULT(data_abort) + @ exception base address .align 5 .globl exception_vector_table @@ -177,13 +238,13 @@ irqstack_end: @ instruction to clear an existing tag is required on context switches." @ -- ARM Cortex-A Series Programmerâs Guide (Version: 4.0) exception_vector_table: - b . @ reset - b . @ undefined instruction - b . @ supervisor call - b . @ prefetch call - b . @ prefetch abort - b . @ data abort - b irq_handler @ irq + b fault_reset + b fault_undefined_instruction + b fault_svc + b fault_prefetch_call + b fault_prefetch_abort + b fault_data_abort + b irq_handler @ IRQ .word 0xe7f000f0 @ abort on FIQ irq_handler: diff --git a/extras/mini-os/arch/arm/panic.c b/extras/mini-os/arch/arm/panic.c new file mode 100644 index 0000000..d0547b0 --- /dev/null +++ b/extras/mini-os/arch/arm/panic.c @@ -0,0 +1,98 @@ +/****************************************************************************** + * panic.c + * + * Displays a register dump and stack trace for debugging. + * + * Copyright (c) 2014, Thomas Leonard + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to + * deal in the Software without restriction, including without limitation the + * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or + * sell copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include <mini-os/os.h> +#include <mini-os/console.h> +#include <arch_mm.h> + +extern int irqstack[]; +extern int irqstack_end[]; + +typedef void handler(void); + +extern handler fault_reset; +extern handler fault_undefined_instruction; +extern handler fault_svc; +extern handler fault_prefetch_call; +extern handler fault_prefetch_abort; +extern handler fault_data_abort; + +void dump_registers(int *saved_registers) { + static int in_dump = 0; + int *sp, *stack_top, *x; + char *fault_name; + void *fault_handler; + int i; + + if (in_dump) + { + printk("Crash while in dump_registers! Not generating a second report.\n"); + return; + } + + in_dump = 1; + + fault_handler = (handler *) saved_registers[17]; + if (fault_handler == fault_reset) + fault_name = "reset"; + else if (fault_handler == fault_undefined_instruction) + fault_name = "undefined_instruction"; + else if (fault_handler == fault_svc) + fault_name = "svc"; + else if (fault_handler == fault_prefetch_call) + fault_name = "prefetch_call"; + else if (fault_handler == fault_prefetch_abort) + fault_name = "prefetch_abort"; + else if (fault_handler == fault_data_abort) + fault_name = "data_abort"; + else + fault_name = "unknown fault type!"; + + printk("Fault handler at %x called (%s)\n", fault_handler, fault_name); + + for (i = 0; i < 16; i++) { + printk("r%d = %x\n", i, saved_registers[i]); + } + printk("CPSR = %x\n", saved_registers[16]); + + printk("Stack dump (innermost last)\n"); + sp = (int *) saved_registers[13]; + + if (sp >= _boot_stack && sp <= _boot_stack_end) + stack_top = _boot_stack_end; /* The boot stack */ + else if (sp >= irqstack && sp <= irqstack_end) + stack_top = irqstack_end; /* The IRQ stack */ + else + stack_top = (int *) ((((unsigned long) sp) | (__STACK_SIZE-1)) + 1); /* A normal thread stack */ + + for (x = stack_top - 1; x >= sp; x--) + { + printk(" [%8p] %8x\n", x, *x); + } + printk("End of stack\n"); + + in_dump = 0; +} -- 2.0.1 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |