aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/sh/kernel/Makefile3
-rw-r--r--arch/sh/kernel/cpu/sh2/entry.S2
-rw-r--r--arch/sh/kernel/cpu/sh3/entry.S2
-rw-r--r--arch/sh/kernel/debugtraps.S41
-rw-r--r--arch/sh/kernel/entry-common.S119
-rw-r--r--arch/sh/kernel/kgdb_stub.c7
-rw-r--r--arch/sh/kernel/process.c24
-rw-r--r--include/asm-sh/kgdb.h8
8 files changed, 117 insertions, 89 deletions
diff --git a/arch/sh/kernel/Makefile b/arch/sh/kernel/Makefile
index 2f6d2bcb1c93..ff30d7f58043 100644
--- a/arch/sh/kernel/Makefile
+++ b/arch/sh/kernel/Makefile
@@ -6,7 +6,8 @@ extra-y := head.o init_task.o vmlinux.lds
6 6
7obj-y := process.o signal.o traps.o irq.o \ 7obj-y := process.o signal.o traps.o irq.o \
8 ptrace.o setup.o time.o sys_sh.o semaphore.o \ 8 ptrace.o setup.o time.o sys_sh.o semaphore.o \
9 io.o io_generic.o sh_ksyms.o syscalls.o 9 io.o io_generic.o sh_ksyms.o syscalls.o \
10 debugtraps.o
10 11
11obj-y += cpu/ timers/ 12obj-y += cpu/ timers/
12obj-$(CONFIG_VSYSCALL) += vsyscall/ 13obj-$(CONFIG_VSYSCALL) += vsyscall/
diff --git a/arch/sh/kernel/cpu/sh2/entry.S b/arch/sh/kernel/cpu/sh2/entry.S
index d51fa5e9904a..8de48102ac85 100644
--- a/arch/sh/kernel/cpu/sh2/entry.S
+++ b/arch/sh/kernel/cpu/sh2/entry.S
@@ -206,7 +206,7 @@ trap_entry:
206 206
207#if defined(CONFIG_SH_STANDARD_BIOS) 207#if defined(CONFIG_SH_STANDARD_BIOS)
208 /* Unwind the stack and jmp to the debug entry */ 208 /* Unwind the stack and jmp to the debug entry */
209debug_kernel_fw: 209ENTRY(sh_bios_handler)
210 mov r15,r0 210 mov r15,r0
211 add #(22-4)*4-4,r0 211 add #(22-4)*4-4,r0
212 ldc.l @r0+,gbr 212 ldc.l @r0+,gbr
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S
index 8c0dc2700c69..014ac37ca16a 100644
--- a/arch/sh/kernel/cpu/sh3/entry.S
+++ b/arch/sh/kernel/cpu/sh3/entry.S
@@ -173,7 +173,7 @@ call_dae:
173 173
174#if defined(CONFIG_SH_STANDARD_BIOS) 174#if defined(CONFIG_SH_STANDARD_BIOS)
175 /* Unwind the stack and jmp to the debug entry */ 175 /* Unwind the stack and jmp to the debug entry */
176debug_kernel_fw: 176ENTRY(sh_bios_handler)
177 mov.l @r15+, r0 177 mov.l @r15+, r0
178 mov.l @r15+, r1 178 mov.l @r15+, r1
179 mov.l @r15+, r2 179 mov.l @r15+, r2
diff --git a/arch/sh/kernel/debugtraps.S b/arch/sh/kernel/debugtraps.S
new file mode 100644
index 000000000000..13b66746410a
--- /dev/null
+++ b/arch/sh/kernel/debugtraps.S
@@ -0,0 +1,41 @@
1/*
2 * arch/sh/kernel/debugtraps.S
3 *
4 * Debug trap jump tables for SuperH
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/sys.h>
13#include <linux/linkage.h>
14
15#if !defined(CONFIG_SH_KGDB)
16#define kgdb_handle_exception debug_trap_handler
17#endif
18
19#if !defined(CONFIG_SH_STANDARD_BIOS)
20#define sh_bios_handler debug_trap_handler
21#endif
22
23 .data
24
25ENTRY(debug_trap_table)
26 .long debug_trap_handler /* 0x30 */
27 .long debug_trap_handler /* 0x31 */
28 .long debug_trap_handler /* 0x32 */
29 .long debug_trap_handler /* 0x33 */
30 .long debug_trap_handler /* 0x34 */
31 .long debug_trap_handler /* 0x35 */
32 .long debug_trap_handler /* 0x36 */
33 .long debug_trap_handler /* 0x37 */
34 .long debug_trap_handler /* 0x38 */
35 .long debug_trap_handler /* 0x39 */
36 .long debug_trap_handler /* 0x3a */
37 .long debug_trap_handler /* 0x3b */
38 .long kgdb_handle_exception /* 0x3c */
39 .long debug_trap_handler /* 0x3d */
40 .long bug_trap_handler /* 0x3e */
41 .long sh_bios_handler /* 0x3f */
diff --git a/arch/sh/kernel/entry-common.S b/arch/sh/kernel/entry-common.S
index fc279aeb73ab..ab4ebb856c2a 100644
--- a/arch/sh/kernel/entry-common.S
+++ b/arch/sh/kernel/entry-common.S
@@ -54,79 +54,24 @@
54# define resume_kernel __restore_all 54# define resume_kernel __restore_all
55#endif 55#endif
56 56
57#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
58! Handle kernel debug if either kgdb (SW) or gdb-stub (FW) is present.
59! If both are configured, handle the debug traps (breakpoints) in SW,
60! but still allow BIOS traps to FW.
61
62 .align 2
63debug_kernel:
64#if defined(CONFIG_SH_STANDARD_BIOS) && defined(CONFIG_SH_KGDB)
65 /* Force BIOS call to FW (debug_trap put TRA in r8) */
66 mov r8,r0
67 shlr2 r0
68 cmp/eq #0x3f,r0
69 bt debug_kernel_fw
70#endif /* CONFIG_SH_STANDARD_BIOS && CONFIG_SH_KGDB */
71
72debug_enter:
73#if defined(CONFIG_SH_KGDB)
74 /* Jump to kgdb, pass stacked regs as arg */
75debug_kernel_sw:
76 mov.l 3f, r0
77 jmp @r0
78 mov r15, r4
79 .align 2
803: .long kgdb_handle_exception
81#endif /* CONFIG_SH_KGDB */
82#ifdef CONFIG_SH_STANDARD_BIOS
83 bra debug_kernel_fw
84 nop
85#endif
86#endif /* CONFIG_SH_STANDARD_BIOS || CONFIG_SH_KGDB */
87
88 .align 2
89debug_trap:
90#if defined(CONFIG_SH_STANDARD_BIOS) || defined(CONFIG_SH_KGDB)
91 mov r8, r0
92 shlr2 r0
93 cmp/eq #0x3f, r0 ! sh_bios() trap
94 bf 1f
95#ifdef CONFIG_SH_KGDB
96 cmp/eq #0xff, r0 ! XXX: KGDB trap, fix for SH-2.
97 bf 1f
98#endif
99 mov #OFF_SR, r0
100 mov.l @(r0,r15), r0 ! get status register
101 shll r0
102 shll r0 ! kernel space?
103 bt/s debug_kernel
1041:
105#endif
106 mov.l @r15, r0 ! Restore R0 value
107 mov.l 1f, r8
108 jmp @r8
109 nop
110 57
111 .align 2 58 .align 2
112ENTRY(exception_error) 59ENTRY(exception_error)
113 ! 60 !
114#ifdef CONFIG_TRACE_IRQFLAGS 61#ifdef CONFIG_TRACE_IRQFLAGS
115 mov.l 3f, r0 62 mov.l 2f, r0
116 jsr @r0 63 jsr @r0
117 nop 64 nop
118#endif 65#endif
119 sti 66 sti
120 mov.l 2f, r0 67 mov.l 1f, r0
121 jmp @r0 68 jmp @r0
122 nop 69 nop
123 70
124!
125 .align 2 71 .align 2
1261: .long break_point_trap_software 721: .long do_exception_error
1272: .long do_exception_error
128#ifdef CONFIG_TRACE_IRQFLAGS 73#ifdef CONFIG_TRACE_IRQFLAGS
1293: .long trace_hardirqs_on 742: .long trace_hardirqs_on
130#endif 75#endif
131 76
132 .align 2 77 .align 2
@@ -331,16 +276,31 @@ __restore_all:
3311: .long restore_all 2761: .long restore_all
332 277
333 .align 2 278 .align 2
334not_syscall_tra:
335 bra debug_trap
336 nop
337
338 .align 2
339syscall_badsys: ! Bad syscall number 279syscall_badsys: ! Bad syscall number
340 mov #-ENOSYS, r0 280 mov #-ENOSYS, r0
341 bra resume_userspace 281 bra resume_userspace
342 mov.l r0, @(OFF_R0,r15) ! Return value 282 mov.l r0, @(OFF_R0,r15) ! Return value
343 283
284/*
285 * The main debug trap handler.
286 *
287 * r8=TRA (not the trap number!)
288 *
289 * Note: This assumes that the trapa value is left in its original
290 * form (without the shlr2 shift) so the calculation for the jump
291 * call table offset remains a simple in place mask.
292 */
293debug_trap:
294 mov r8, r0
295 and #(0xf << 2), r0
296 mov.l 1f, r8
297 add r0, r8
298 mov.l @r8, r8
299 jmp @r8
300 nop
301
302 .align 2
3031: .long debug_trap_table
344 304
345/* 305/*
346 * Syscall interface: 306 * Syscall interface:
@@ -348,17 +308,19 @@ syscall_badsys: ! Bad syscall number
348 * Syscall #: R3 308 * Syscall #: R3
349 * Arguments #0 to #3: R4--R7 309 * Arguments #0 to #3: R4--R7
350 * Arguments #4 to #6: R0, R1, R2 310 * Arguments #4 to #6: R0, R1, R2
351 * TRA: (number of arguments + 0x10) x 4 311 * TRA: (number of arguments + ABI revision) x 4
352 * 312 *
353 * This code also handles delegating other traps to the BIOS/gdb stub 313 * This code also handles delegating other traps to the BIOS/gdb stub
354 * according to: 314 * according to:
355 * 315 *
356 * Trap number 316 * Trap number
357 * (TRA>>2) Purpose 317 * (TRA>>2) Purpose
358 * -------- ------- 318 * -------- -------
359 * 0x0-0xf old syscall ABI 319 * 0x00-0x0f original SH-3/4 syscall ABI (not in general use).
360 * 0x10-0x1f new syscall ABI 320 * 0x10-0x1f general SH-3/4 syscall ABI.
361 * 0x20-0xff delegated through debug_trap to BIOS/gdb stub. 321 * 0x20-0x2f syscall ABI for SH-2 parts.
322 * 0x30-0x3f debug traps used by the kernel.
323 * 0x40-0xff Not supported by all parts, so left unhandled.
362 * 324 *
363 * Note: When we're first called, the TRA value must be shifted 325 * Note: When we're first called, the TRA value must be shifted
364 * right 2 bits in order to get the value that was used as the "trapa" 326 * right 2 bits in order to get the value that was used as the "trapa"
@@ -375,17 +337,22 @@ ret_from_fork:
375 nop 337 nop
376 .align 2 338 .align 2
3771: .long schedule_tail 3391: .long schedule_tail
378 ! 340
341/*
342 * The poorly named main trapa decode and dispatch routine, for
343 * system calls and debug traps through their respective jump tables.
344 */
379ENTRY(system_call) 345ENTRY(system_call)
380#if !defined(CONFIG_CPU_SH2) 346#if !defined(CONFIG_CPU_SH2)
381 mov.l 1f, r9 347 mov.l 1f, r9
382 mov.l @r9, r8 ! Read from TRA (Trap Address) Register 348 mov.l @r9, r8 ! Read from TRA (Trap Address) Register
383#endif 349#endif
384 ! 350 /*
385 ! Is the trap argument >= 0x20? (TRA will be >= 0x80) 351 * Check the trap type
386 mov #0x7f, r9 352 */
353 mov #((0x20 << 2) - 1), r9
387 cmp/hi r9, r8 354 cmp/hi r9, r8
388 bt/s not_syscall_tra 355 bt/s debug_trap ! it's a debug trap..
389 mov #OFF_TRA, r9 356 mov #OFF_TRA, r9
390 add r15, r9 357 add r15, r9
391 mov.l r8, @r9 ! set TRA value to tra 358 mov.l r8, @r9 ! set TRA value to tra
diff --git a/arch/sh/kernel/kgdb_stub.c b/arch/sh/kernel/kgdb_stub.c
index 9c6315f0335d..d8927d85492e 100644
--- a/arch/sh/kernel/kgdb_stub.c
+++ b/arch/sh/kernel/kgdb_stub.c
@@ -1323,8 +1323,11 @@ static void kgdb_command_loop(const int excep_code, const int trapa_value)
1323} 1323}
1324 1324
1325/* There has been an exception, most likely a breakpoint. */ 1325/* There has been an exception, most likely a breakpoint. */
1326void kgdb_handle_exception(struct pt_regs *regs) 1326asmlinkage void kgdb_handle_exception(unsigned long r4, unsigned long r5,
1327 unsigned long r6, unsigned long r7,
1328 struct pt_regs __regs)
1327{ 1329{
1330 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
1328 int excep_code, vbr_val; 1331 int excep_code, vbr_val;
1329 int count; 1332 int count;
1330 int trapa_value = ctrl_inl(TRA); 1333 int trapa_value = ctrl_inl(TRA);
@@ -1368,8 +1371,6 @@ void kgdb_handle_exception(struct pt_regs *regs)
1368 1371
1369 vbr_val = trap_registers.vbr; 1372 vbr_val = trap_registers.vbr;
1370 asm("ldc %0, vbr": :"r"(vbr_val)); 1373 asm("ldc %0, vbr": :"r"(vbr_val));
1371
1372 return;
1373} 1374}
1374 1375
1375/* Trigger a breakpoint by function */ 1376/* Trigger a breakpoint by function */
diff --git a/arch/sh/kernel/process.c b/arch/sh/kernel/process.c
index 486c06e18033..cc8f306fd682 100644
--- a/arch/sh/kernel/process.c
+++ b/arch/sh/kernel/process.c
@@ -493,9 +493,27 @@ asmlinkage void break_point_trap(void)
493 force_sig(SIGTRAP, current); 493 force_sig(SIGTRAP, current);
494} 494}
495 495
496asmlinkage void break_point_trap_software(unsigned long r4, unsigned long r5, 496/*
497 unsigned long r6, unsigned long r7, 497 * Generic trap handler.
498 struct pt_regs __regs) 498 */
499asmlinkage void debug_trap_handler(unsigned long r4, unsigned long r5,
500 unsigned long r6, unsigned long r7,
501 struct pt_regs __regs)
502{
503 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
504
505 /* Rewind */
506 regs->pc -= 2;
507
508 force_sig(SIGTRAP, current);
509}
510
511/*
512 * Special handler for BUG() traps.
513 */
514asmlinkage void bug_trap_handler(unsigned long r4, unsigned long r5,
515 unsigned long r6, unsigned long r7,
516 struct pt_regs __regs)
499{ 517{
500 struct pt_regs *regs = RELOC_HIDE(&__regs, 0); 518 struct pt_regs *regs = RELOC_HIDE(&__regs, 0);
501 519
diff --git a/include/asm-sh/kgdb.h b/include/asm-sh/kgdb.h
index 7b26f53fe343..0095c665d272 100644
--- a/include/asm-sh/kgdb.h
+++ b/include/asm-sh/kgdb.h
@@ -85,10 +85,10 @@ extern int setjmp(jmp_buf __jmpb);
85#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__) 85#define KGDB_PRINTK(...) printk("KGDB: " __VA_ARGS__)
86 86
87/* Forced breakpoint */ 87/* Forced breakpoint */
88#define BREAKPOINT() do { \ 88#define BREAKPOINT() \
89 if (kgdb_enabled) { \ 89do { \
90 asm volatile("trapa #0xff"); \ 90 if (kgdb_enabled) \
91 } \ 91 __asm__ __volatile__("trapa #0x3c"); \
92} while (0) 92} while (0)
93 93
94/* KGDB should be able to flush all kernel text space */ 94/* KGDB should be able to flush all kernel text space */