Commit ce3266c0 authored by Steven J. Magnani's avatar Steven J. Magnani Committed by Michal Simek
Browse files

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

Signed-off-by: default avatarSteven J. Magnani <steve@digidescorp.com>
parent ba9c4f88
Loading
Loading
Loading
Loading
+5 −0
Original line number Diff line number Diff line
@@ -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 */
+0 −1
Original line number Diff line number Diff line
@@ -45,7 +45,6 @@ extern struct task_struct *_switch_to(struct thread_info *prev,
#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,
+29 −0
Original line number Diff line number Diff line
/*
 * 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 */
+1 −1
Original line number Diff line number Diff line
@@ -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/

+28 −0
Original line number Diff line number Diff line
@@ -588,3 +588,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
Loading