sh: stacktrace/lockdep/irqflags tracing support.
Wire up all of the essentials for lockdep..
Signed-off-by: Paul Mundt <lethal@linux-sh.org>
diff --git a/arch/sh/Kconfig b/arch/sh/Kconfig
index aa1ebc5..0137320 100644
--- a/arch/sh/Kconfig
+++ b/arch/sh/Kconfig
@@ -51,6 +51,14 @@
config ARCH_MAY_HAVE_PC_FDC
bool
+config STACKTRACE_SUPPORT
+ bool
+ default y
+
+config LOCKDEP_SUPPORT
+ bool
+ default y
+
source "init/Kconfig"
menu "System type"
diff --git a/arch/sh/Kconfig.debug b/arch/sh/Kconfig.debug
index dcceec9..66a25ef4 100644
--- a/arch/sh/Kconfig.debug
+++ b/arch/sh/Kconfig.debug
@@ -1,5 +1,9 @@
menu "Kernel hacking"
+config TRACE_IRQFLAGS_SUPPORT
+ bool
+ default y
+
source "lib/Kconfig.debug"
config SH_STANDARD_BIOS
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 50d54c2..99c7e52 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -21,3 +21,4 @@
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 298d919..34d51b3 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -184,6 +184,11 @@
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 @@
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 @@
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 @@
.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 7ba3dcb..8c0dc27 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -140,7 +140,7 @@
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 8f96d21..29136a3 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -100,6 +100,11 @@
.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 @@
.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 @@
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 @@
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 @@
.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 @@
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 @@
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 @@
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 @@
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 @@
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_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 @@
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 0000000..0d5268a
--- /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;
+ }
+ }
+}
diff --git a/arch/sh/mm/fault.c b/arch/sh/mm/fault.c
index cfeefc1..716ebf5 100644
--- a/arch/sh/mm/fault.c
+++ b/arch/sh/mm/fault.c
@@ -37,6 +37,9 @@
int si_code;
siginfo_t info;
+ trace_hardirqs_on();
+ local_irq_enable();
+
#ifdef CONFIG_SH_KGDB
if (kgdb_nofault && kgdb_bus_err_hook)
kgdb_bus_err_hook();