Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 204639
b: refs/heads/master
c: ce3266c
h: refs/heads/master
i:
  204637: 04460e3
  204635: d2540ae
  204631: db2ad9c
  204623: c6a4c2e
  204607: 8e65657
v: v3
  • Loading branch information
Steven J. Magnani authored and Michal Simek committed Aug 4, 2010
1 parent 8e90c5a commit 81d17d6
Show file tree
Hide file tree
Showing 11 changed files with 455 additions and 96 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: ba9c4f88d747836bf35c3eee36aa18d2e164f493
refs/heads/master: ce3266c047389443d5f433d605c769e878cbe46e
5 changes: 5 additions & 0 deletions trunk/arch/microblaze/include/asm/exceptions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
1 change: 0 additions & 1 deletion trunk/arch/microblaze/include/asm/system.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
29 changes: 29 additions & 0 deletions trunk/arch/microblaze/include/asm/unwind.h
Original file line number Diff line number Diff line change
@@ -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 */

2 changes: 1 addition & 1 deletion trunk/arch/microblaze/kernel/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -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/

Expand Down
28 changes: 28 additions & 0 deletions trunk/arch/microblaze/kernel/entry-nommu.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
27 changes: 27 additions & 0 deletions trunk/arch/microblaze/kernel/entry.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 1 addition & 3 deletions trunk/arch/microblaze/kernel/hw_exception_handler.S
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
44 changes: 5 additions & 39 deletions trunk/arch/microblaze/kernel/stacktrace.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,18 @@
#include <linux/thread_info.h>
#include <linux/ptrace.h>
#include <linux/module.h>
#include <asm/unwind.h>

/* FIXME initial support */
void save_stack_trace(struct stack_trace *trace)
{
unsigned long *sp;
unsigned long addr;
asm("addik %0, r1, 0" : "=r" (sp));

while (!kstack_end(sp)) {
addr = *sp++;
if (__kernel_text_address(addr)) {
if (trace->skip > 0)
trace->skip--;
else
trace->entries[trace->nr_entries++] = addr;

if (trace->nr_entries >= trace->max_entries)
break;
}
}
/* Exclude our helper functions from the trace*/
trace->skip += 2;
microblaze_unwind(NULL, trace);
}
EXPORT_SYMBOL_GPL(save_stack_trace);

void save_stack_trace_tsk(struct task_struct *tsk, struct stack_trace *trace)
{
unsigned int *sp;
unsigned long addr;

struct thread_info *ti = task_thread_info(tsk);

if (tsk == current)
asm("addik %0, r1, 0" : "=r" (sp));
else
sp = (unsigned int *)ti->cpu_context.r1;

while (!kstack_end(sp)) {
addr = *sp++;
if (__kernel_text_address(addr)) {
if (trace->skip > 0)
trace->skip--;
else
trace->entries[trace->nr_entries++] = addr;

if (trace->nr_entries >= trace->max_entries)
break;
}
}
microblaze_unwind(tsk, trace);
}
EXPORT_SYMBOL_GPL(save_stack_trace_tsk);
91 changes: 40 additions & 51 deletions trunk/arch/microblaze/kernel/traps.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,80 +16,69 @@

#include <asm/exceptions.h>
#include <asm/system.h>
#include <asm/unwind.h>

void trap_init(void)
{
__enable_hw_exceptions();
}

static unsigned long kstack_depth_to_print = 24;
static unsigned long kstack_depth_to_print; /* 0 == entire stack */

static int __init kstack_setup(char *s)
{
return !strict_strtoul(s, 0, &kstack_depth_to_print);
}
__setup("kstack=", kstack_setup);

void show_trace(struct task_struct *task, unsigned long *stack)
void show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long addr;

if (!stack)
stack = (unsigned long *)&stack;
unsigned long words_to_show;
u32 fp = (u32) sp;

if (fp == 0) {
if (task) {
fp = ((struct thread_info *)
(task->stack))->cpu_context.r1;
} else {
/* Pick up caller of dump_stack() */
fp = (u32)&sp - 8;
}
}

printk(KERN_NOTICE "Call Trace: ");
#ifdef CONFIG_KALLSYMS
printk(KERN_NOTICE "\n");
#endif
while (!kstack_end(stack)) {
addr = *stack++;
/*
* If the address is either in the text segment of the
* kernel, or in the region which contains vmalloc'ed
* memory, it *may* be the address of a calling
* routine; if so, print it so that someone tracing
* down the cause of the crash will be able to figure
* out the call path that was taken.
*/
if (kernel_text_address(addr))
print_ip_sym(addr);
words_to_show = (THREAD_SIZE - (fp & (THREAD_SIZE - 1))) >> 2;
if (kstack_depth_to_print && (words_to_show > kstack_depth_to_print))
words_to_show = kstack_depth_to_print;

pr_info("Kernel Stack:\n");

/*
* Make the first line an 'odd' size if necessary to get
* remaining lines to start at an address multiple of 0x10
*/
if (fp & 0xF) {
unsigned long line1_words = (0x10 - (fp & 0xF)) >> 2;
if (line1_words < words_to_show) {
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32,
4, (void *)fp, line1_words << 2, 0);
fp += line1_words << 2;
words_to_show -= line1_words;
}
}
printk(KERN_NOTICE "\n");
print_hex_dump(KERN_INFO, "", DUMP_PREFIX_ADDRESS, 32, 4, (void *)fp,
words_to_show << 2, 0);
printk(KERN_INFO "\n\n");

pr_info("Call Trace:\n");
microblaze_unwind(task, NULL);
pr_info("\n");

if (!task)
task = current;

debug_show_held_locks(task);
}

void show_stack(struct task_struct *task, unsigned long *sp)
{
unsigned long *stack;
int i;

if (sp == NULL) {
if (task)
sp = (unsigned long *) ((struct thread_info *)
(task->stack))->cpu_context.r1;
else
sp = (unsigned long *)&sp;
}

stack = sp;

printk(KERN_INFO "\nStack:\n ");

for (i = 0; i < kstack_depth_to_print; i++) {
if (kstack_end(sp))
break;
if (i && ((i % 8) == 0))
printk("\n ");
printk("%08lx ", *sp++);
}
printk("\n");
show_trace(task, stack);
}

void dump_stack(void)
{
show_stack(NULL, NULL);
Expand Down
Loading

0 comments on commit 81d17d6

Please sign in to comment.