diff options
Diffstat (limited to 'arch/sh/kernel')
-rw-r--r-- | arch/sh/kernel/Makefile | 1 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh2/entry.S | 16 | ||||
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 2 | ||||
-rw-r--r-- | arch/sh/kernel/entry-common.S | 64 | ||||
-rw-r--r-- | arch/sh/kernel/stacktrace.c | 43 |
5 files changed, 124 insertions, 2 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile index 50d54c24d76a..99c7e5249f7a 100644 --- a/arch/sh/kernel/Makefile +++ b/arch/sh/kernel/Makefile | |||
@@ -21,3 +21,4 @@ obj-$(CONFIG_EARLY_PRINTK) += early_printk.o | |||
21 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o | 21 | obj-$(CONFIG_KEXEC) += machine_kexec.o relocate_kernel.o |
22 | obj-$(CONFIG_APM) += apm.o | 22 | obj-$(CONFIG_APM) += apm.o |
23 | obj-$(CONFIG_PM) += pm.o | 23 | obj-$(CONFIG_PM) += pm.o |
24 | obj-$(CONFIG_STACKTRACE) += stacktrace.o | ||
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S index 298d9191909d..34d51b3745ea 100644 --- a/arch/sh/kernel/cpu/sh2/entry.S +++ b/arch/sh/kernel/cpu/sh2/entry.S | |||
@@ -184,6 +184,11 @@ trap_entry: | |||
184 | add r15,r8 | 184 | add r15,r8 |
185 | mov.l r9,@r8 | 185 | mov.l r9,@r8 |
186 | mov r9,r8 | 186 | mov r9,r8 |
187 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
188 | mov.l 5f, r9 | ||
189 | jsr @r9 | ||
190 | nop | ||
191 | #endif | ||
187 | sti | 192 | sti |
188 | bra system_call | 193 | bra system_call |
189 | nop | 194 | nop |
@@ -193,6 +198,9 @@ trap_entry: | |||
193 | 2: .long break_point_trap_software | 198 | 2: .long break_point_trap_software |
194 | 3: .long NR_syscalls | 199 | 3: .long NR_syscalls |
195 | 4: .long sys_call_table | 200 | 4: .long sys_call_table |
201 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
202 | 5: .long trace_hardirqs_on | ||
203 | #endif | ||
196 | 204 | ||
197 | #if defined(CONFIG_SH_STANDARD_BIOS) | 205 | #if defined(CONFIG_SH_STANDARD_BIOS) |
198 | /* Unwind the stack and jmp to the debug entry */ | 206 | /* Unwind the stack and jmp to the debug entry */ |
@@ -255,6 +263,11 @@ ENTRY(address_error_handler) | |||
255 | 263 | ||
256 | restore_all: | 264 | restore_all: |
257 | cli | 265 | cli |
266 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
267 | mov.l 3f, r0 | ||
268 | jsr @r0 | ||
269 | nop | ||
270 | #endif | ||
258 | mov r15,r0 | 271 | mov r15,r0 |
259 | mov.l $cpu_mode,r2 | 272 | mov.l $cpu_mode,r2 |
260 | mov #OFF_SR,r3 | 273 | mov #OFF_SR,r3 |
@@ -307,6 +320,9 @@ $current_thread_info: | |||
307 | .long __current_thread_info | 320 | .long __current_thread_info |
308 | $cpu_mode: | 321 | $cpu_mode: |
309 | .long __cpu_mode | 322 | .long __cpu_mode |
323 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
324 | 3: .long trace_hardirqs_off | ||
325 | #endif | ||
310 | 326 | ||
311 | ! common exception handler | 327 | ! common exception handler |
312 | #include "../../entry-common.S" | 328 | #include "../../entry-common.S" |
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 7ba3dcbe7504..8c0dc2700c69 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -140,7 +140,7 @@ call_dpf: | |||
140 | mov.l 1f, r0 | 140 | mov.l 1f, r0 |
141 | mov.l @r0, r6 ! address | 141 | mov.l @r0, r6 ! address |
142 | mov.l 3f, r0 | 142 | mov.l 3f, r0 |
143 | sti | 143 | |
144 | jmp @r0 | 144 | jmp @r0 |
145 | mov r15, r4 ! regs | 145 | mov r15, r4 ! regs |
146 | 146 | ||
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S index 8f96d21fcb1c..29136a35d7c7 100644 --- a/arch/sh/kernel/entry-common.S +++ b/arch/sh/kernel/entry-common.S | |||
@@ -100,6 +100,11 @@ debug_trap: | |||
100 | .align 2 | 100 | .align 2 |
101 | ENTRY(exception_error) | 101 | ENTRY(exception_error) |
102 | ! | 102 | ! |
103 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
104 | mov.l 3f, r0 | ||
105 | jsr @r0 | ||
106 | nop | ||
107 | #endif | ||
103 | sti | 108 | sti |
104 | mov.l 2f, r0 | 109 | mov.l 2f, r0 |
105 | jmp @r0 | 110 | jmp @r0 |
@@ -109,10 +114,18 @@ ENTRY(exception_error) | |||
109 | .align 2 | 114 | .align 2 |
110 | 1: .long break_point_trap_software | 115 | 1: .long break_point_trap_software |
111 | 2: .long do_exception_error | 116 | 2: .long do_exception_error |
117 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
118 | 3: .long trace_hardirqs_on | ||
119 | #endif | ||
112 | 120 | ||
113 | .align 2 | 121 | .align 2 |
114 | ret_from_exception: | 122 | ret_from_exception: |
115 | preempt_stop() | 123 | preempt_stop() |
124 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
125 | mov.l 4f, r0 | ||
126 | jsr @r0 | ||
127 | nop | ||
128 | #endif | ||
116 | ENTRY(ret_from_irq) | 129 | ENTRY(ret_from_irq) |
117 | ! | 130 | ! |
118 | mov #OFF_SR, r0 | 131 | mov #OFF_SR, r0 |
@@ -143,6 +156,11 @@ need_resched: | |||
143 | mov.l 1f, r0 | 156 | mov.l 1f, r0 |
144 | mov.l r0, @(TI_PRE_COUNT,r8) | 157 | mov.l r0, @(TI_PRE_COUNT,r8) |
145 | 158 | ||
159 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
160 | mov.l 3f, r0 | ||
161 | jsr @r0 | ||
162 | nop | ||
163 | #endif | ||
146 | sti | 164 | sti |
147 | mov.l 2f, r0 | 165 | mov.l 2f, r0 |
148 | jsr @r0 | 166 | jsr @r0 |
@@ -150,9 +168,15 @@ need_resched: | |||
150 | mov #0, r0 | 168 | mov #0, r0 |
151 | mov.l r0, @(TI_PRE_COUNT,r8) | 169 | mov.l r0, @(TI_PRE_COUNT,r8) |
152 | cli | 170 | cli |
171 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
172 | mov.l 4f, r0 | ||
173 | jsr @r0 | ||
174 | nop | ||
175 | #endif | ||
153 | 176 | ||
154 | bra need_resched | 177 | bra need_resched |
155 | nop | 178 | nop |
179 | |||
156 | noresched: | 180 | noresched: |
157 | bra __restore_all | 181 | bra __restore_all |
158 | nop | 182 | nop |
@@ -160,11 +184,20 @@ noresched: | |||
160 | .align 2 | 184 | .align 2 |
161 | 1: .long PREEMPT_ACTIVE | 185 | 1: .long PREEMPT_ACTIVE |
162 | 2: .long schedule | 186 | 2: .long schedule |
187 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
188 | 3: .long trace_hardirqs_on | ||
189 | 4: .long trace_hardirqs_off | ||
190 | #endif | ||
163 | #endif | 191 | #endif |
164 | 192 | ||
165 | ENTRY(resume_userspace) | 193 | ENTRY(resume_userspace) |
166 | ! r8: current_thread_info | 194 | ! r8: current_thread_info |
167 | cli | 195 | cli |
196 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
197 | mov.l 5f, r0 | ||
198 | jsr @r0 | ||
199 | nop | ||
200 | #endif | ||
168 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 201 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
169 | tst #_TIF_WORK_MASK, r0 | 202 | tst #_TIF_WORK_MASK, r0 |
170 | bt/s __restore_all | 203 | bt/s __restore_all |
@@ -210,6 +243,11 @@ work_resched: | |||
210 | jsr @r1 ! schedule | 243 | jsr @r1 ! schedule |
211 | nop | 244 | nop |
212 | cli | 245 | cli |
246 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
247 | mov.l 5f, r0 | ||
248 | jsr @r0 | ||
249 | nop | ||
250 | #endif | ||
213 | ! | 251 | ! |
214 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 252 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
215 | tst #_TIF_WORK_MASK, r0 | 253 | tst #_TIF_WORK_MASK, r0 |
@@ -221,6 +259,10 @@ work_resched: | |||
221 | 1: .long schedule | 259 | 1: .long schedule |
222 | 2: .long do_notify_resume | 260 | 2: .long do_notify_resume |
223 | 3: .long restore_all | 261 | 3: .long restore_all |
262 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
263 | 4: .long trace_hardirqs_on | ||
264 | 5: .long trace_hardirqs_off | ||
265 | #endif | ||
224 | 266 | ||
225 | .align 2 | 267 | .align 2 |
226 | syscall_exit_work: | 268 | syscall_exit_work: |
@@ -229,6 +271,11 @@ syscall_exit_work: | |||
229 | tst #_TIF_SYSCALL_TRACE, r0 | 271 | tst #_TIF_SYSCALL_TRACE, r0 |
230 | bt/s work_pending | 272 | bt/s work_pending |
231 | tst #_TIF_NEED_RESCHED, r0 | 273 | tst #_TIF_NEED_RESCHED, r0 |
274 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
275 | mov.l 5f, r0 | ||
276 | jsr @r0 | ||
277 | nop | ||
278 | #endif | ||
232 | sti | 279 | sti |
233 | ! XXX setup arguments... | 280 | ! XXX setup arguments... |
234 | mov.l 4f, r0 ! do_syscall_trace | 281 | mov.l 4f, r0 ! do_syscall_trace |
@@ -265,7 +312,7 @@ syscall_trace_entry: | |||
265 | mov.l r0, @(OFF_R0,r15) ! Return value | 312 | mov.l r0, @(OFF_R0,r15) ! Return value |
266 | 313 | ||
267 | __restore_all: | 314 | __restore_all: |
268 | mov.l 1f,r0 | 315 | mov.l 1f, r0 |
269 | jmp @r0 | 316 | jmp @r0 |
270 | nop | 317 | nop |
271 | 318 | ||
@@ -331,7 +378,13 @@ ENTRY(system_call) | |||
331 | mov #OFF_TRA, r9 | 378 | mov #OFF_TRA, r9 |
332 | add r15, r9 | 379 | add r15, r9 |
333 | mov.l r8, @r9 ! set TRA value to tra | 380 | mov.l r8, @r9 ! set TRA value to tra |
381 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
382 | mov.l 5f, r10 | ||
383 | jsr @r10 | ||
384 | nop | ||
385 | #endif | ||
334 | sti | 386 | sti |
387 | |||
335 | ! | 388 | ! |
336 | get_current_thread_info r8, r10 | 389 | get_current_thread_info r8, r10 |
337 | mov.l @(TI_FLAGS,r8), r8 | 390 | mov.l @(TI_FLAGS,r8), r8 |
@@ -355,6 +408,11 @@ syscall_call: | |||
355 | ! | 408 | ! |
356 | syscall_exit: | 409 | syscall_exit: |
357 | cli | 410 | cli |
411 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
412 | mov.l 6f, r0 | ||
413 | jsr @r0 | ||
414 | nop | ||
415 | #endif | ||
358 | ! | 416 | ! |
359 | get_current_thread_info r8, r0 | 417 | get_current_thread_info r8, r0 |
360 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags | 418 | mov.l @(TI_FLAGS,r8), r0 ! current_thread_info->flags |
@@ -369,3 +427,7 @@ syscall_exit: | |||
369 | 2: .long NR_syscalls | 427 | 2: .long NR_syscalls |
370 | 3: .long sys_call_table | 428 | 3: .long sys_call_table |
371 | 4: .long do_syscall_trace | 429 | 4: .long do_syscall_trace |
430 | #ifdef CONFIG_TRACE_IRQFLAGS | ||
431 | 5: .long trace_hardirqs_on | ||
432 | 6: .long trace_hardirqs_off | ||
433 | #endif | ||
diff --git a/arch/sh/kernel/stacktrace.c b/arch/sh/kernel/stacktrace.c new file mode 100644 index 000000000000..0d5268afe80f --- /dev/null +++ b/arch/sh/kernel/stacktrace.c | |||
@@ -0,0 +1,43 @@ | |||
1 | /* | ||
2 | * arch/sh/kernel/stacktrace.c | ||
3 | * | ||
4 | * Stack trace management functions | ||
5 | * | ||
6 | * Copyright (C) 2006 Paul Mundt | ||
7 | * | ||
8 | * This file is subject to the terms and conditions of the GNU General Public | ||
9 | * License. See the file "COPYING" in the main directory of this archive | ||
10 | * for more details. | ||
11 | */ | ||
12 | #include <linux/sched.h> | ||
13 | #include <linux/stacktrace.h> | ||
14 | #include <linux/thread_info.h> | ||
15 | #include <asm/ptrace.h> | ||
16 | |||
17 | /* | ||
18 | * Save stack-backtrace addresses into a stack_trace buffer. | ||
19 | */ | ||
20 | void save_stack_trace(struct stack_trace *trace, struct task_struct *task) | ||
21 | { | ||
22 | unsigned long *sp; | ||
23 | |||
24 | if (!task) | ||
25 | task = current; | ||
26 | if (task == current) | ||
27 | sp = (unsigned long *)current_stack_pointer; | ||
28 | else | ||
29 | sp = (unsigned long *)task->thread.sp; | ||
30 | |||
31 | while (!kstack_end(sp)) { | ||
32 | unsigned long addr = *sp++; | ||
33 | |||
34 | if (__kernel_text_address(addr)) { | ||
35 | if (trace->skip > 0) | ||
36 | trace->skip--; | ||
37 | else | ||
38 | trace->entries[trace->nr_entries++] = addr; | ||
39 | if (trace->nr_entries >= trace->max_entries) | ||
40 | break; | ||
41 | } | ||
42 | } | ||
43 | } | ||