microblaze: add stack unwinder
PATCH v2 1/1 microblaze: add stack unwinder
Implement intelligent backtracing by searching for stack frame creation, and emitting only return addresses. Use print_hex_dump() to display the entire binary kernel stack.
Limitation: MMU kernels are not currently able to trace beyond a system trap (interrupt, syscall, etc.). It is the intent of this patch to provide infrastructure that can be extended to add this capability later.
Changes from V1:
* Removed checks in find_frame_creation() that prevented location of the frame creation instruction in heavily optimized code
* Various formatting/commenting/file location tweaks per review comments
* Dropped Kconfig option to enable STACKTRACE as something logically separate
---
arch/microblaze/include/asm/exceptions.h +5 -0
@@ -14,6 +14,11 @@#define _ASM_MICROBLAZE_EXCEPTIONS_H#ifdef __KERNEL__ + +#ifndef CONFIG_MMU +#define EX_HANDLER_STACK_SIZ (4*19) +#endif +#ifndef __ASSEMBLY__/* Macros to enable and disable HW exceptions in the MSR */
arch/microblaze/include/asm/system.h +0 -1
@@ -44,7 +44,6 @@ extern struct task_struct *_switch_to(st#define smp_rmb () rmb()#define smp_wmb () wmb() -void show_trace (struct task_struct *task,unsigned long *stack);void __bad_xchg (volatile void *ptr,int size); static inline unsigned long __xchg(unsigned long x, volatile void *ptr,
arch/microblaze/include/asm/unwind.h +29 -0
@@ -0,0 +1,29 @@ +/* +* Backtrace support for Microblaze +* +* Copyright (C) 2010 Digital Design Corporation +* +* This file is subject to the terms and conditions of the GNU General Public +* License. See the file "COPYING" in the main directory of this archive +* for more details. +*/ + +#ifndef __MICROBLAZE_UNWIND_H +#define __MICROBLAZE_UNWIND_H + +struct stack_trace ; + +struct trap_handler_info { +unsigned long start_addr; +unsigned long end_addr; +const char *trap_name; +}; +extern struct trap_handler_info microblaze_trap_handlers; + +extern const char _hw_exception_handler; +extern const char ex_handler_unhandled; + +void microblaze_unwind (struct task_struct *task,struct stack_trace *trace); + +#endif /* __MICROBLAZE_UNWIND_H */ +
arch/microblaze/kernel/entry-nommu.S +28 -0
@@ -586,3 +586,31 @@ sys_rt_sigsuspend_wrapper: #include "syscall_table.S" syscall_table_size=(.-sys_call_table) + +type_SYSCALL: + .ascii "SYSCALL\0" +type_IRQ: + .ascii "IRQ\0" +type_IRQ_PREEMPT: + .ascii "IRQ (PREEMPTED)\0" +type_SYSCALL_PREEMPT: + .ascii " SYSCALL (PREEMPTED)\0" + + /* + * Trap decoding for stack unwinder + * Tuples are (start addr, end addr, string) + * If return address lies on [start addr, end addr], + * unwinder displays 'string' + */ + + .align 4 +.global microblaze_trap_handlers +microblaze_trap_handlers: + /* Exact matches come first */ + .word ret_to_user ; .word ret_to_user ; .word type_SYSCALL + .word ret_from_intr; .word ret_from_intr ; .word type_IRQ + /* Fuzzy matches go here */ + .word ret_from_intr; .word no_intr_resched; .word type_IRQ_PREEMPT + .word work_pending ; .word no_work_pending; .word type_SYSCALL_PREEMPT + /* End of table */ + .word 0 ; .word 0 ; .word 0
arch/microblaze/kernel/entry.S +27 -0
@@ -1127,3 +1127,30 @@ ENTRY(_break) syscall_table_size=(.-sys_call_table) +type_SYSCALL: + .ascii "SYSCALL\0" +type_IRQ: + .ascii "IRQ\0" +type_IRQ_PREEMPT: + .ascii "IRQ (PREEMPTED)\0" +type_SYSCALL_PREEMPT: + .ascii " SYSCALL (PREEMPTED)\0" + + /* + * Trap decoding for stack unwinder + * Tuples are (start addr, end addr, string) + * If return address lies on [start addr, end addr], + * unwinder displays 'string' + */ + + .align 4 +.global microblaze_trap_handlers +microblaze_trap_handlers: + /* Exact matches come first */ + .word ret_from_trap; .word ret_from_trap ; .word type_SYSCALL + .word ret_from_irq ; .word ret_from_irq ; .word type_IRQ + /* Fuzzy matches go here */ + .word ret_from_irq ; .word no_intr_resched ; .word type_IRQ_PREEMPT + .word ret_from_trap; .word TRAP_return ; .word type_SYSCALL_PREEMPT + /* End of table */ + .word 0 ; .word 0 ; .word 0
arch/microblaze/kernel/hw_exception_handler.S +1 -3
@@ -78,9 +78,6 @@ #include <asm/asm-offsets.h> /* Helpful Macros */ -#ifndef CONFIG_MMU -#define EX_HANDLER_STACK_SIZ (4*19) -#endif #define NUM_TO_REG(num) r ## num #ifdef CONFIG_MMU
@@ -988,6 +985,7 @@ ex_unaligned_fixup: .end _unaligned_data_exception #endif /* CONFIG_MMU */ +.global ex_handler_unhandled ex_handler_unhandled: /* FIXME add handle function for unhandled exception - dump register */ bri 0
arch/microblaze/kernel/Makefile +1 -1
@@ -17,7 +17,7 @@ extra-y := head.o vmlinux.lds obj-y += dma.o exceptions.o \ hw_exception_handler.o init_task.o intc.o irq.o of_device.o \ of_platform.o process.o prom.o prom_parse.o ptrace.o \ - setup.o signal.o sys_microblaze.o timer.o traps.o reset.o + reset.o setup.o signal.o sys_microblaze.o timer.o traps.o unwind.o obj-y += cpu/
arch/microblaze/kernel/stacktrace.c +5 -39
57 lines not on this page · raw message
arch/microblaze/kernel/traps.c +39 -50
117 lines not on this page · raw message
arch/microblaze/kernel/unwind.c +318 -0
318 lines not on this page · raw message