diff options
Diffstat (limited to 'arch/sh/kernel/entry-common.S')
-rw-r--r-- | arch/sh/kernel/entry-common.S | 119 |
1 files changed, 43 insertions, 76 deletions
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 | ||
63 | debug_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 | |||
72 | debug_enter: | ||
73 | #if defined(CONFIG_SH_KGDB) | ||
74 | /* Jump to kgdb, pass stacked regs as arg */ | ||
75 | debug_kernel_sw: | ||
76 | mov.l 3f, r0 | ||
77 | jmp @r0 | ||
78 | mov r15, r4 | ||
79 | .align 2 | ||
80 | 3: .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 | ||
89 | debug_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 | ||
104 | 1: | ||
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 |
112 | ENTRY(exception_error) | 59 | ENTRY(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 |
126 | 1: .long break_point_trap_software | 72 | 1: .long do_exception_error |
127 | 2: .long do_exception_error | ||
128 | #ifdef CONFIG_TRACE_IRQFLAGS | 73 | #ifdef CONFIG_TRACE_IRQFLAGS |
129 | 3: .long trace_hardirqs_on | 74 | 2: .long trace_hardirqs_on |
130 | #endif | 75 | #endif |
131 | 76 | ||
132 | .align 2 | 77 | .align 2 |
@@ -331,16 +276,31 @@ __restore_all: | |||
331 | 1: .long restore_all | 276 | 1: .long restore_all |
332 | 277 | ||
333 | .align 2 | 278 | .align 2 |
334 | not_syscall_tra: | ||
335 | bra debug_trap | ||
336 | nop | ||
337 | |||
338 | .align 2 | ||
339 | syscall_badsys: ! Bad syscall number | 279 | syscall_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 | */ | ||
293 | debug_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 | ||
303 | 1: .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 |
377 | 1: .long schedule_tail | 339 | 1: .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 | */ | ||
379 | ENTRY(system_call) | 345 | ENTRY(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 |