diff options
Diffstat (limited to 'arch/sh/kernel/cpu/sh3/entry.S')
-rw-r--r-- | arch/sh/kernel/cpu/sh3/entry.S | 102 |
1 files changed, 58 insertions, 44 deletions
diff --git a/arch/sh/kernel/cpu/sh3/entry.S b/arch/sh/kernel/cpu/sh3/entry.S index 3cb531f233f2..0151933e5253 100644 --- a/arch/sh/kernel/cpu/sh3/entry.S +++ b/arch/sh/kernel/cpu/sh3/entry.S | |||
@@ -53,10 +53,6 @@ | |||
53 | * syscall # | 53 | * syscall # |
54 | * | 54 | * |
55 | */ | 55 | */ |
56 | #if defined(CONFIG_KGDB) | ||
57 | NMI_VEC = 0x1c0 ! Must catch early for debounce | ||
58 | #endif | ||
59 | |||
60 | /* Offsets to the stack */ | 56 | /* Offsets to the stack */ |
61 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | 57 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ |
62 | OFF_R1 = 4 /* New ABI: arg5 */ | 58 | OFF_R1 = 4 /* New ABI: arg5 */ |
@@ -71,7 +67,6 @@ OFF_PC = (16*4) | |||
71 | OFF_SR = (16*4+8) | 67 | OFF_SR = (16*4+8) |
72 | OFF_TRA = (16*4+6*4) | 68 | OFF_TRA = (16*4+6*4) |
73 | 69 | ||
74 | |||
75 | #define k0 r0 | 70 | #define k0 r0 |
76 | #define k1 r1 | 71 | #define k1 r1 |
77 | #define k2 r2 | 72 | #define k2 r2 |
@@ -113,34 +108,34 @@ OFF_TRA = (16*4+6*4) | |||
113 | #if defined(CONFIG_MMU) | 108 | #if defined(CONFIG_MMU) |
114 | .align 2 | 109 | .align 2 |
115 | ENTRY(tlb_miss_load) | 110 | ENTRY(tlb_miss_load) |
116 | bra call_dpf | 111 | bra call_handle_tlbmiss |
117 | mov #0, r5 | 112 | mov #0, r5 |
118 | 113 | ||
119 | .align 2 | 114 | .align 2 |
120 | ENTRY(tlb_miss_store) | 115 | ENTRY(tlb_miss_store) |
121 | bra call_dpf | 116 | bra call_handle_tlbmiss |
122 | mov #1, r5 | 117 | mov #1, r5 |
123 | 118 | ||
124 | .align 2 | 119 | .align 2 |
125 | ENTRY(initial_page_write) | 120 | ENTRY(initial_page_write) |
126 | bra call_dpf | 121 | bra call_handle_tlbmiss |
127 | mov #1, r5 | 122 | mov #2, r5 |
128 | 123 | ||
129 | .align 2 | 124 | .align 2 |
130 | ENTRY(tlb_protection_violation_load) | 125 | ENTRY(tlb_protection_violation_load) |
131 | bra call_dpf | 126 | bra call_do_page_fault |
132 | mov #0, r5 | 127 | mov #0, r5 |
133 | 128 | ||
134 | .align 2 | 129 | .align 2 |
135 | ENTRY(tlb_protection_violation_store) | 130 | ENTRY(tlb_protection_violation_store) |
136 | bra call_dpf | 131 | bra call_do_page_fault |
137 | mov #1, r5 | 132 | mov #1, r5 |
138 | 133 | ||
139 | call_dpf: | 134 | call_handle_tlbmiss: |
135 | setup_frame_reg | ||
140 | mov.l 1f, r0 | 136 | mov.l 1f, r0 |
141 | mov r5, r8 | 137 | mov r5, r8 |
142 | mov.l @r0, r6 | 138 | mov.l @r0, r6 |
143 | mov r6, r9 | ||
144 | mov.l 2f, r0 | 139 | mov.l 2f, r0 |
145 | sts pr, r10 | 140 | sts pr, r10 |
146 | jsr @r0 | 141 | jsr @r0 |
@@ -151,16 +146,25 @@ call_dpf: | |||
151 | lds r10, pr | 146 | lds r10, pr |
152 | rts | 147 | rts |
153 | nop | 148 | nop |
154 | 0: mov.l 3f, r0 | 149 | 0: |
155 | mov r9, r6 | ||
156 | mov r8, r5 | 150 | mov r8, r5 |
151 | call_do_page_fault: | ||
152 | mov.l 1f, r0 | ||
153 | mov.l @r0, r6 | ||
154 | |||
155 | sti | ||
156 | |||
157 | mov.l 3f, r0 | ||
158 | mov.l 4f, r1 | ||
159 | mov r15, r4 | ||
157 | jmp @r0 | 160 | jmp @r0 |
158 | mov r15, r4 | 161 | lds r1, pr |
159 | 162 | ||
160 | .align 2 | 163 | .align 2 |
161 | 1: .long MMU_TEA | 164 | 1: .long MMU_TEA |
162 | 2: .long __do_page_fault | 165 | 2: .long handle_tlbmiss |
163 | 3: .long do_page_fault | 166 | 3: .long do_page_fault |
167 | 4: .long ret_from_exception | ||
164 | 168 | ||
165 | .align 2 | 169 | .align 2 |
166 | ENTRY(address_error_load) | 170 | ENTRY(address_error_load) |
@@ -256,7 +260,7 @@ restore_all: | |||
256 | ! | 260 | ! |
257 | ! Calculate new SR value | 261 | ! Calculate new SR value |
258 | mov k3, k2 ! original SR value | 262 | mov k3, k2 ! original SR value |
259 | mov #0xf0, k1 | 263 | mov #0xfffffff0, k1 |
260 | extu.b k1, k1 | 264 | extu.b k1, k1 |
261 | not k1, k1 | 265 | not k1, k1 |
262 | and k1, k2 ! Mask original SR value | 266 | and k1, k2 ! Mask original SR value |
@@ -272,21 +276,12 @@ restore_all: | |||
272 | 6: or k0, k2 ! Set the IMASK-bits | 276 | 6: or k0, k2 ! Set the IMASK-bits |
273 | ldc k2, ssr | 277 | ldc k2, ssr |
274 | ! | 278 | ! |
275 | #if defined(CONFIG_KGDB) | ||
276 | ! Clear in_nmi | ||
277 | mov.l 6f, k0 | ||
278 | mov #0, k1 | ||
279 | mov.b k1, @k0 | ||
280 | #endif | ||
281 | mov k4, r15 | 279 | mov k4, r15 |
282 | rte | 280 | rte |
283 | nop | 281 | nop |
284 | 282 | ||
285 | .align 2 | 283 | .align 2 |
286 | 5: .long 0x00001000 ! DSP | 284 | 5: .long 0x00001000 ! DSP |
287 | #ifdef CONFIG_KGDB | ||
288 | 6: .long in_nmi | ||
289 | #endif | ||
290 | 7: .long 0x30000000 | 285 | 7: .long 0x30000000 |
291 | 286 | ||
292 | ! common exception handler | 287 | ! common exception handler |
@@ -478,23 +473,6 @@ ENTRY(save_low_regs) | |||
478 | ! | 473 | ! |
479 | .balign 512,0,512 | 474 | .balign 512,0,512 |
480 | ENTRY(handle_interrupt) | 475 | ENTRY(handle_interrupt) |
481 | #if defined(CONFIG_KGDB) | ||
482 | mov.l 2f, k2 | ||
483 | ! Debounce (filter nested NMI) | ||
484 | mov.l @k2, k0 | ||
485 | mov.l 9f, k1 | ||
486 | cmp/eq k1, k0 | ||
487 | bf 11f | ||
488 | mov.l 10f, k1 | ||
489 | tas.b @k1 | ||
490 | bt 11f | ||
491 | rte | ||
492 | nop | ||
493 | .align 2 | ||
494 | 9: .long NMI_VEC | ||
495 | 10: .long in_nmi | ||
496 | 11: | ||
497 | #endif /* defined(CONFIG_KGDB) */ | ||
498 | sts pr, k3 ! save original pr value in k3 | 476 | sts pr, k3 ! save original pr value in k3 |
499 | mova exception_data, k0 | 477 | mova exception_data, k0 |
500 | 478 | ||
@@ -507,13 +485,49 @@ ENTRY(handle_interrupt) | |||
507 | bsr save_regs ! needs original pr value in k3 | 485 | bsr save_regs ! needs original pr value in k3 |
508 | mov #-1, k2 ! default vector kept in k2 | 486 | mov #-1, k2 ! default vector kept in k2 |
509 | 487 | ||
488 | setup_frame_reg | ||
489 | |||
490 | stc sr, r0 ! get status register | ||
491 | shlr2 r0 | ||
492 | and #0x3c, r0 | ||
493 | cmp/eq #0x3c, r0 | ||
494 | bf 9f | ||
495 | TRACE_IRQS_OFF | ||
496 | 9: | ||
497 | |||
510 | ! Setup return address and jump to do_IRQ | 498 | ! Setup return address and jump to do_IRQ |
511 | mov.l 4f, r9 ! fetch return address | 499 | mov.l 4f, r9 ! fetch return address |
512 | lds r9, pr ! put return address in pr | 500 | lds r9, pr ! put return address in pr |
513 | mov.l 2f, r4 | 501 | mov.l 2f, r4 |
514 | mov.l 3f, r9 | 502 | mov.l 3f, r9 |
515 | mov.l @r4, r4 ! pass INTEVT vector as arg0 | 503 | mov.l @r4, r4 ! pass INTEVT vector as arg0 |
504 | |||
505 | shlr2 r4 | ||
506 | shlr r4 | ||
507 | mov r4, r0 ! save vector->jmp table offset for later | ||
508 | |||
509 | shlr2 r4 ! vector to IRQ# conversion | ||
510 | add #-0x10, r4 | ||
511 | |||
512 | cmp/pz r4 ! is it a valid IRQ? | ||
513 | bt 10f | ||
514 | |||
515 | /* | ||
516 | * We got here as a result of taking the INTEVT path for something | ||
517 | * that isn't a valid hard IRQ, therefore we bypass the do_IRQ() | ||
518 | * path and special case the event dispatch instead. This is the | ||
519 | * expected path for the NMI (and any other brilliantly implemented | ||
520 | * exception), which effectively wants regular exception dispatch | ||
521 | * but is unfortunately reported through INTEVT rather than | ||
522 | * EXPEVT. Grr. | ||
523 | */ | ||
524 | mov.l 6f, r9 | ||
525 | mov.l @(r0, r9), r9 | ||
516 | jmp @r9 | 526 | jmp @r9 |
527 | mov r15, r8 ! trap handlers take saved regs in r8 | ||
528 | |||
529 | 10: | ||
530 | jmp @r9 ! Off to do_IRQ() we go. | ||
517 | mov r15, r5 ! pass saved registers as arg1 | 531 | mov r15, r5 ! pass saved registers as arg1 |
518 | 532 | ||
519 | ENTRY(exception_none) | 533 | ENTRY(exception_none) |