aboutsummaryrefslogtreecommitdiff
path: root/arch/sh/kernel
diff options
context:
space:
mode:
authorPaul Mundt <lethal@linux-sh.org>2006-12-04 18:17:28 +0900
committerPaul Mundt <lethal@linux-sh.org>2006-12-06 10:45:40 +0900
commitafbfb52e47273a440df33274452c603e8c332de2 (patch)
tree041dc70061a67e787b362959298e093830b4b4d7 /arch/sh/kernel
parentc03c69610bfa728805deceeb624ee4268c722a5a (diff)
sh: stacktrace/lockdep/irqflags tracing support.
Wire up all of the essentials for lockdep.. Signed-off-by: Paul Mundt <lethal@linux-sh.org>
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r--arch/sh/kernel/Makefile1
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S16
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S2
-rw-r--r--arch/sh/kernel/entry-common.S64
-rw-r--r--arch/sh/kernel/stacktrace.c43
5 files changed, 124 insertions, 2 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 50d54c24d76..99c7e5249f7 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o
obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o
obj-$(CONFIG_APM) += apm.o
obj-$(CONFIG_PM) += pm.o
+obj-$(CONFIG_STACKTRACE) += stacktrace.o
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index 298d9191909..34d51b3745e 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -184,6 +184,11 @@ trap_entry:
add r15,r8
mov.l r9,@r8
mov r9,r8
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r9
+ jsr @r9
+ nop
+#endif
sti
bra system_call
nop
@@ -193,6 +198,9 @@ trap_entry:
2: .long break_point_trap_software
3: .long NR_syscalls
4: .long sys_call_table
+#ifdef CONFIG_TRACE_IRQFLAGS
+5: .long trace_hardirqs_on
+#endif
#if defined(CONFIG_SH_STANDARD_BIOS)
/* Unwind the stack and jmp to the debug entry */
@@ -255,6 +263,11 @@ ENTRY(address_error_handler)
restore_all:
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
mov r15,r0
mov.l $cpu_mode,r2
mov #OFF_SR,r3
@@ -307,6 +320,9 @@ $current_thread_info:
.long __current_thread_info
$cpu_mode:
.long __cpu_mode
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .long trace_hardirqs_off
+#endif
! common exception handler
#include "../../entry-common.S"
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 7ba3dcbe750..8c0dc2700c6 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -140,7 +140,7 @@ call_dpf:
mov.l 1f, r0
mov.l @r0, r6 ! address
mov.l 3f, r0
- sti
+
jmp @r0
mov r15, r4 ! regs
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index 8f96d21fcb1..29136a35d7c 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -100,6 +100,11 @@ debug_trap:
.align 2
ENTRY(exception_error)
!
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
sti
mov.l 2f, r0
jmp @r0
@@ -109,10 +114,18 @@ ENTRY(exception_error)
.align 2
1: .long break_point_trap_software
2: .long do_exception_error
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .long trace_hardirqs_on
+#endif
.align 2
ret_from_exception:
preempt_stop()
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 4f, r0
+ jsr @r0
+ nop
+#endif
ENTRY(ret_from_irq)
!
mov #OFF_SR, r0
@@ -143,6 +156,11 @@ need_resched:
mov.l 1f, r0
mov.l r0, @(TI_PRE_COUNT,r8)
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 3f, r0
+ jsr @r0
+ nop
+#endif
sti
mov.l 2f, r0
jsr @r0
@@ -150,9 +168,15 @@ need_resched:
mov #0, r0
mov.l r0, @(TI_PRE_COUNT,r8)
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 4f, r0
+ jsr @r0
+ nop
+#endif
bra need_resched
nop
+
noresched:
bra __restore_all
nop
@@ -160,11 +184,20 @@ noresched:
.align 2
1: .long PREEMPT_ACTIVE
2: .long schedule
+#ifdef CONFIG_TRACE_IRQFLAGS
+3: .long trace_hardirqs_on
+4: .long trace_hardirqs_off
+#endif
#endif
ENTRY(resume_userspace)
! r8: current_thread_info
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
bt/s __restore_all
@@ -210,6 +243,11 @@ work_resched:
jsr @r1 ! schedule
nop
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
!
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
tst #_TIF_WORK_MASK, r0
@@ -221,6 +259,10 @@ work_resched:
1: .long schedule
2: .long do_notify_resume
3: .long restore_all
+#ifdef CONFIG_TRACE_IRQFLAGS
+4: .long trace_hardirqs_on
+5: .long trace_hardirqs_off
+#endif
.align 2
syscall_exit_work:
@@ -229,6 +271,11 @@ syscall_exit_work:
tst #_TIF_SYSCALL_TRACE, r0
bt/s work_pending
tst #_TIF_NEED_RESCHED, r0
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r0
+ jsr @r0
+ nop
+#endif
sti
! XXX setup arguments...
mov.l 4f, r0 ! do_syscall_trace
@@ -265,7 +312,7 @@ syscall_trace_entry:
mov.l r0, @(OFF_R0,r15) ! Return value
__restore_all:
- mov.l 1f,r0
+ mov.l 1f, r0
jmp @r0
nop
@@ -331,7 +378,13 @@ ENTRY(system_call)
mov #OFF_TRA, r9
add r15, r9
mov.l r8, @r9 ! set TRA value to tra
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 5f, r10
+ jsr @r10
+ nop
+#endif
sti
+
!
get_current_thread_info r8, r10
mov.l @(TI_FLAGS,r8), r8
@@ -355,6 +408,11 @@ syscall_call:
!
syscall_exit:
cli
+#ifdef CONFIG_TRACE_IRQFLAGS
+ mov.l 6f, r0
+ jsr @r0
+ nop
+#endif
!
get_current_thread_info r8, r0
mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags
@@ -369,3 +427,7 @@ syscall_exit:
2: .long NR_syscalls
3: .long sys_call_table
4: .long do_syscall_trace
+#ifdef CONFIG_TRACE_IRQFLAGS
+5: .long trace_hardirqs_on
+6: .long trace_hardirqs_off
+#endif
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c
new file mode 100644
index 00000000000..0d5268afe80
--- /dev/null
+++ b/arch/sh/kernel/stacktrace.c
@@ -0,0 +1,43 @@
+/*
+ * arch/sh/kernel/stacktrace.c
+ *
+ * Stack trace management functions
+ *
+ * Copyright (C) 2006 Paul Mundt
+ *
+ * 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.
+ */
+#include <linux/sched.h>
+#include <linux/stacktrace.h>
+#include <linux/thread_info.h>
+#include <asm/ptrace.h>
+
+/*
+ * Save stack-backtrace addresses into a stack_trace buffer.
+ */
+void save_stack_trace(struct stack_trace *trace, struct task_struct *task)
+{
+ unsigned long *sp;
+
+ if (!task)
+ task = current;
+ if (task == current)
+ sp = (unsigned long *)current_stack_pointer;
+ else
+ sp = (unsigned long *)task->thread.sp;
+
+ while (!kstack_end(sp)) {
+ unsigned long 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;
+ }
+ }
+}