Commit | Line | Data |
---|---|---|
baf4326e | 1 | /* |
58862699 | 2 | * arch/sh/kernel/cpu/sh3/entry.S |
1da177e4 LT |
3 | * |
4 | * Copyright (C) 1999, 2000, 2002 Niibe Yutaka | |
baf4326e | 5 | * Copyright (C) 2003 - 2006 Paul Mundt |
1da177e4 LT |
6 | * |
7 | * This file is subject to the terms and conditions of the GNU General Public | |
8 | * License. See the file "COPYING" in the main directory of this archive | |
9 | * for more details. | |
1da177e4 | 10 | */ |
1da177e4 | 11 | #include <linux/sys.h> |
711fa809 | 12 | #include <linux/errno.h> |
1da177e4 | 13 | #include <linux/linkage.h> |
1da177e4 LT |
14 | #include <asm/asm-offsets.h> |
15 | #include <asm/thread_info.h> | |
db2e1fa3 | 16 | #include <asm/unistd.h> |
f15cbe6f | 17 | #include <cpu/mmu_context.h> |
1efe4ce3 | 18 | #include <asm/page.h> |
1d015cf0 | 19 | #include <asm/cache.h> |
1da177e4 | 20 | |
1da177e4 LT |
21 | ! NOTE: |
22 | ! GNU as (as of 2.9.1) changes bf/s into bt/s and bra, when the address | |
23 | ! to be jumped is too far, but it causes illegal slot exception. | |
24 | ||
25 | /* | |
26 | * entry.S contains the system-call and fault low-level handling routines. | |
27 | * This also contains the timer-interrupt handler, as well as all interrupts | |
28 | * and faults that can result in a task-switch. | |
29 | * | |
30 | * NOTE: This code handles signal-recognition, which happens every time | |
31 | * after a timer-interrupt and after each system call. | |
32 | * | |
33 | * NOTE: This code uses a convention that instructions in the delay slot | |
34 | * of a transfer-control instruction are indented by an extra space, thus: | |
35 | * | |
36 | * jmp @k0 ! control-transfer instruction | |
37 | * ldc k1, ssr ! delay slot | |
38 | * | |
39 | * Stack layout in 'ret_from_syscall': | |
40 | * ptrace needs to have all regs on the stack. | |
41 | * if the order here is changed, it needs to be | |
42 | * updated in ptrace.c and ptrace.h | |
43 | * | |
44 | * r0 | |
45 | * ... | |
46 | * r15 = stack pointer | |
47 | * spc | |
48 | * pr | |
49 | * ssr | |
50 | * gbr | |
51 | * mach | |
52 | * macl | |
53 | * syscall # | |
54 | * | |
55 | */ | |
ab6e570b | 56 | #if defined(CONFIG_KGDB) |
1da177e4 LT |
57 | NMI_VEC = 0x1c0 ! Must catch early for debounce |
58 | #endif | |
59 | ||
60 | /* Offsets to the stack */ | |
61 | OFF_R0 = 0 /* Return value. New ABI also arg4 */ | |
62 | OFF_R1 = 4 /* New ABI: arg5 */ | |
63 | OFF_R2 = 8 /* New ABI: arg6 */ | |
64 | OFF_R3 = 12 /* New ABI: syscall_nr */ | |
65 | OFF_R4 = 16 /* New ABI: arg0 */ | |
66 | OFF_R5 = 20 /* New ABI: arg1 */ | |
67 | OFF_R6 = 24 /* New ABI: arg2 */ | |
68 | OFF_R7 = 28 /* New ABI: arg3 */ | |
69 | OFF_SP = (15*4) | |
70 | OFF_PC = (16*4) | |
71 | OFF_SR = (16*4+8) | |
72 | OFF_TRA = (16*4+6*4) | |
73 | ||
74 | ||
75 | #define k0 r0 | |
76 | #define k1 r1 | |
77 | #define k2 r2 | |
78 | #define k3 r3 | |
79 | #define k4 r4 | |
80 | ||
1da177e4 LT |
81 | #define g_imask r6 /* r6_bank1 */ |
82 | #define k_g_imask r6_bank /* r6_bank1 */ | |
83 | #define current r7 /* r7_bank1 */ | |
84 | ||
de398406 YS |
85 | #include <asm/entry-macros.S> |
86 | ||
1da177e4 LT |
87 | /* |
88 | * Kernel mode register usage: | |
89 | * k0 scratch | |
90 | * k1 scratch | |
91 | * k2 scratch (Exception code) | |
92 | * k3 scratch (Return address) | |
93 | * k4 scratch | |
94 | * k5 reserved | |
95 | * k6 Global Interrupt Mask (0--15 << 4) | |
96 | * k7 CURRENT_THREAD_INFO (pointer to current thread info) | |
97 | */ | |
98 | ||
99 | ! | |
100 | ! TLB Miss / Initial Page write exception handling | |
101 | ! _and_ | |
102 | ! TLB hits, but the access violate the protection. | |
103 | ! It can be valid access, such as stack grow and/or C-O-W. | |
104 | ! | |
105 | ! | |
106 | ! Find the pmd/pte entry and loadtlb | |
107 | ! If it's not found, cause address error (SEGV) | |
108 | ! | |
109 | ! Although this could be written in assembly language (and it'd be faster), | |
110 | ! this first version depends *much* on C implementation. | |
111 | ! | |
112 | ||
1da177e4 LT |
113 | #if defined(CONFIG_MMU) |
114 | .align 2 | |
115 | ENTRY(tlb_miss_load) | |
112e5847 | 116 | bra call_handle_tlbmiss |
1da177e4 LT |
117 | mov #0, r5 |
118 | ||
119 | .align 2 | |
120 | ENTRY(tlb_miss_store) | |
112e5847 | 121 | bra call_handle_tlbmiss |
1da177e4 LT |
122 | mov #1, r5 |
123 | ||
124 | .align 2 | |
125 | ENTRY(initial_page_write) | |
112e5847 | 126 | bra call_handle_tlbmiss |
8010fbe7 | 127 | mov #2, r5 |
1da177e4 LT |
128 | |
129 | .align 2 | |
130 | ENTRY(tlb_protection_violation_load) | |
112e5847 | 131 | bra call_do_page_fault |
1da177e4 LT |
132 | mov #0, r5 |
133 | ||
134 | .align 2 | |
135 | ENTRY(tlb_protection_violation_store) | |
112e5847 | 136 | bra call_do_page_fault |
1da177e4 LT |
137 | mov #1, r5 |
138 | ||
112e5847 | 139 | call_handle_tlbmiss: |
0b930489 | 140 | setup_frame_reg |
1da177e4 | 141 | mov.l 1f, r0 |
db2e1fa3 PM |
142 | mov r5, r8 |
143 | mov.l @r0, r6 | |
db2e1fa3 PM |
144 | mov.l 2f, r0 |
145 | sts pr, r10 | |
146 | jsr @r0 | |
147 | mov r15, r4 | |
148 | ! | |
149 | tst r0, r0 | |
150 | bf/s 0f | |
151 | lds r10, pr | |
152 | rts | |
153 | nop | |
112e5847 | 154 | 0: |
db2e1fa3 | 155 | mov r8, r5 |
112e5847 PM |
156 | call_do_page_fault: |
157 | mov.l 1f, r0 | |
158 | mov.l @r0, r6 | |
159 | ||
160 | sti | |
161 | ||
162 | mov.l 3f, r0 | |
163 | mov.l 4f, r1 | |
164 | mov r15, r4 | |
1da177e4 | 165 | jmp @r0 |
112e5847 | 166 | lds r1, pr |
1da177e4 LT |
167 | |
168 | .align 2 | |
169 | 1: .long MMU_TEA | |
112e5847 | 170 | 2: .long handle_tlbmiss |
1da177e4 | 171 | 3: .long do_page_fault |
112e5847 | 172 | 4: .long ret_from_exception |
1da177e4 LT |
173 | |
174 | .align 2 | |
175 | ENTRY(address_error_load) | |
176 | bra call_dae | |
177 | mov #0,r5 ! writeaccess = 0 | |
178 | ||
179 | .align 2 | |
180 | ENTRY(address_error_store) | |
181 | bra call_dae | |
182 | mov #1,r5 ! writeaccess = 1 | |
183 | ||
184 | .align 2 | |
185 | call_dae: | |
186 | mov.l 1f, r0 | |
187 | mov.l @r0, r6 ! address | |
188 | mov.l 2f, r0 | |
189 | jmp @r0 | |
190 | mov r15, r4 ! regs | |
191 | ||
192 | .align 2 | |
193 | 1: .long MMU_TEA | |
194 | 2: .long do_address_error | |
195 | #endif /* CONFIG_MMU */ | |
196 | ||
1da177e4 LT |
197 | #if defined(CONFIG_SH_STANDARD_BIOS) |
198 | /* Unwind the stack and jmp to the debug entry */ | |
f413d0d9 | 199 | ENTRY(sh_bios_handler) |
1dd22722 MD |
200 | mov.l 1f, r8 |
201 | bsr restore_regs | |
202 | nop | |
203 | ||
204 | lds k2, pr ! restore pr | |
205 | mov k4, r15 | |
1da177e4 LT |
206 | ! |
207 | mov.l 2f, k0 | |
208 | mov.l @k0, k0 | |
209 | jmp @k0 | |
1dd22722 | 210 | ldc k3, ssr |
1da177e4 LT |
211 | .align 2 |
212 | 1: .long 0x300000f0 | |
213 | 2: .long gdb_vbr_vector | |
214 | #endif /* CONFIG_SH_STANDARD_BIOS */ | |
215 | ||
1dd22722 MD |
216 | ! restore_regs() |
217 | ! - restore r0, r1, r2, r3, r4, r5, r6, r7 from the stack | |
218 | ! - switch bank | |
219 | ! - restore r8, r9, r10, r11, r12, r13, r14, r15 from the stack | |
220 | ! - restore spc, pr*, ssr, gbr, mach, macl, skip default tra | |
221 | ! k2 returns original pr | |
222 | ! k3 returns original sr | |
223 | ! k4 returns original stack pointer | |
224 | ! r8 passes SR bitmask, overwritten with restored data on return | |
225 | ! r9 trashed | |
226 | ! BL=0 on entry, on exit BL=1 (depending on r8). | |
227 | ||
2ef7f0da | 228 | ENTRY(restore_regs) |
1da177e4 LT |
229 | mov.l @r15+, r0 |
230 | mov.l @r15+, r1 | |
231 | mov.l @r15+, r2 | |
232 | mov.l @r15+, r3 | |
233 | mov.l @r15+, r4 | |
234 | mov.l @r15+, r5 | |
235 | mov.l @r15+, r6 | |
236 | mov.l @r15+, r7 | |
237 | ! | |
1dd22722 MD |
238 | stc sr, r9 |
239 | or r8, r9 | |
240 | ldc r9, sr | |
1da177e4 LT |
241 | ! |
242 | mov.l @r15+, r8 | |
243 | mov.l @r15+, r9 | |
244 | mov.l @r15+, r10 | |
245 | mov.l @r15+, r11 | |
246 | mov.l @r15+, r12 | |
247 | mov.l @r15+, r13 | |
248 | mov.l @r15+, r14 | |
249 | mov.l @r15+, k4 ! original stack pointer | |
250 | ldc.l @r15+, spc | |
1dd22722 | 251 | mov.l @r15+, k2 ! original PR |
1da177e4 LT |
252 | mov.l @r15+, k3 ! original SR |
253 | ldc.l @r15+, gbr | |
254 | lds.l @r15+, mach | |
255 | lds.l @r15+, macl | |
1dd22722 MD |
256 | rts |
257 | add #4, r15 ! Skip syscall number | |
258 | ||
259 | restore_all: | |
260 | mov.l 7f, r8 | |
261 | bsr restore_regs | |
262 | nop | |
263 | ||
264 | lds k2, pr ! restore pr | |
1da177e4 | 265 | ! |
1da177e4 LT |
266 | ! Calculate new SR value |
267 | mov k3, k2 ! original SR value | |
fea966f7 | 268 | mov #0xfffffff0, k1 |
de398406 YS |
269 | extu.b k1, k1 |
270 | not k1, k1 | |
1d015cf0 | 271 | and k1, k2 ! Mask original SR value |
1da177e4 LT |
272 | ! |
273 | mov k3, k0 ! Calculate IMASK-bits | |
274 | shlr2 k0 | |
275 | and #0x3c, k0 | |
276 | cmp/eq #0x3c, k0 | |
277 | bt/s 6f | |
278 | shll2 k0 | |
279 | mov g_imask, k0 | |
280 | ! | |
281 | 6: or k0, k2 ! Set the IMASK-bits | |
282 | ldc k2, ssr | |
283 | ! | |
ab6e570b | 284 | #if defined(CONFIG_KGDB) |
1da177e4 | 285 | ! Clear in_nmi |
6ae5e8d7 | 286 | mov.l 6f, k0 |
1da177e4 LT |
287 | mov #0, k1 |
288 | mov.b k1, @k0 | |
289 | #endif | |
1da177e4 LT |
290 | mov k4, r15 |
291 | rte | |
292 | nop | |
293 | ||
294 | .align 2 | |
1da177e4 | 295 | 5: .long 0x00001000 ! DSP |
ab6e570b | 296 | #ifdef CONFIG_KGDB |
370ac91a | 297 | 6: .long in_nmi |
c596b1a3 | 298 | #endif |
1da177e4 | 299 | 7: .long 0x30000000 |
1da177e4 | 300 | |
de398406 | 301 | ! common exception handler |
716067f2 | 302 | #include "../../entry-common.S" |
de398406 | 303 | |
1da177e4 LT |
304 | ! Exception Vector Base |
305 | ! | |
306 | ! Should be aligned page boundary. | |
307 | ! | |
308 | .balign 4096,0,4096 | |
309 | ENTRY(vbr_base) | |
310 | .long 0 | |
1d015cf0 MD |
311 | ! |
312 | ! 0x100: General exception vector | |
1da177e4 LT |
313 | ! |
314 | .balign 256,0,256 | |
315 | general_exception: | |
1d015cf0 MD |
316 | #ifndef CONFIG_CPU_SUBTYPE_SHX3 |
317 | bra handle_exception | |
318 | sts pr, k3 ! save original pr value in k3 | |
319 | #else | |
320 | mov.l 1f, k4 | |
321 | mov.l @k4, k4 | |
2b1bd1ac PM |
322 | |
323 | ! Is EXPEVT larger than 0x800? | |
324 | mov #0x8, k0 | |
325 | shll8 k0 | |
1d015cf0 | 326 | cmp/hs k0, k4 |
2b1bd1ac PM |
327 | bf 0f |
328 | ||
329 | ! then add 0x580 (k2 is 0xd80 or 0xda0) | |
330 | mov #0x58, k0 | |
331 | shll2 k0 | |
332 | shll2 k0 | |
1d015cf0 | 333 | add k0, k4 |
2b1bd1ac | 334 | 0: |
1d015cf0 | 335 | ! Setup stack and save DSP context (k0 contains original r15 on return) |
01ab1039 | 336 | bsr prepare_stack |
2b1bd1ac | 337 | nop |
9b3a53ab | 338 | |
1d015cf0 | 339 | ! Save registers / Switch to bank 0 |
7a516280 | 340 | mov k4, k2 ! keep vector in k2 |
2ef7f0da | 341 | mov.l 1f, k4 ! SR bits to clear in k4 |
1d015cf0 | 342 | bsr save_regs ! needs original pr value in k3 |
2ef7f0da | 343 | nop |
1d015cf0 MD |
344 | |
345 | bra handle_exception_special | |
1da177e4 | 346 | nop |
1da177e4 LT |
347 | |
348 | .align 2 | |
349 | 1: .long EXPEVT | |
1d015cf0 | 350 | #endif |
1da177e4 | 351 | |
01ab1039 | 352 | ! prepare_stack() |
1d015cf0 MD |
353 | ! - roll back gRB |
354 | ! - switch to kernel stack | |
1d015cf0 MD |
355 | ! k0 returns original sp (after roll back) |
356 | ! k1 trashed | |
357 | ! k2 trashed | |
1efe4ce3 | 358 | |
01ab1039 | 359 | prepare_stack: |
1efe4ce3 SM |
360 | #ifdef CONFIG_GUSA |
361 | ! Check for roll back gRB (User and Kernel) | |
362 | mov r15, k0 | |
363 | shll k0 | |
364 | bf/s 1f | |
365 | shll k0 | |
366 | bf/s 1f | |
367 | stc spc, k1 | |
368 | stc r0_bank, k0 | |
369 | cmp/hs k0, k1 ! test k1 (saved PC) >= k0 (saved r0) | |
370 | bt/s 2f | |
371 | stc r1_bank, k1 | |
372 | ||
373 | add #-2, k0 | |
374 | add r15, k0 | |
375 | ldc k0, spc ! PC = saved r0 + r15 - 2 | |
376 | 2: mov k1, r15 ! SP = r1 | |
377 | 1: | |
378 | #endif | |
1d015cf0 | 379 | ! Switch to kernel stack if needed |
1da177e4 LT |
380 | stc ssr, k0 ! Is it from kernel space? |
381 | shll k0 ! Check MD bit (bit30) by shifting it into... | |
382 | shll k0 ! ...the T bit | |
383 | bt/s 1f ! It's a kernel to kernel transition. | |
384 | mov r15, k0 ! save original stack to k0 | |
385 | /* User space to kernel */ | |
510c72ad | 386 | mov #(THREAD_SIZE >> 10), k1 |
a6a31139 | 387 | shll8 k1 ! k1 := THREAD_SIZE |
510c72ad | 388 | shll2 k1 |
1da177e4 LT |
389 | add current, k1 |
390 | mov k1, r15 ! change to kernel stack | |
391 | ! | |
1d015cf0 | 392 | 1: |
1d015cf0 MD |
393 | rts |
394 | nop | |
01ab1039 | 395 | |
1d015cf0 MD |
396 | ! |
397 | ! 0x400: Instruction and Data TLB miss exception vector | |
398 | ! | |
399 | .balign 1024,0,1024 | |
400 | tlb_miss: | |
401 | sts pr, k3 ! save original pr value in k3 | |
baf4326e | 402 | |
1d015cf0 | 403 | handle_exception: |
0197f21c MD |
404 | mova exception_data, k0 |
405 | ||
1d015cf0 | 406 | ! Setup stack and save DSP context (k0 contains original r15 on return) |
01ab1039 | 407 | bsr prepare_stack |
0197f21c | 408 | PREF(k0) |
1d015cf0 MD |
409 | |
410 | ! Save registers / Switch to bank 0 | |
411 | mov.l 5f, k2 ! vector register address | |
2ef7f0da | 412 | mov.l 1f, k4 ! SR bits to clear in k4 |
1d015cf0 MD |
413 | bsr save_regs ! needs original pr value in k3 |
414 | mov.l @k2, k2 ! read out vector and keep in k2 | |
415 | ||
416 | handle_exception_special: | |
417 | ! Setup return address and jump to exception handler | |
418 | mov.l 7f, r9 ! fetch return address | |
419 | stc r2_bank, r0 ! k2 (vector) | |
420 | mov.l 6f, r10 | |
421 | shlr2 r0 | |
422 | shlr r0 | |
423 | mov.l @(r0, r10), r10 | |
424 | jmp @r10 | |
425 | lds r9, pr ! put return address in pr | |
426 | ||
427 | .align L1_CACHE_SHIFT | |
428 | ||
429 | ! save_regs() | |
4f099ebb | 430 | ! - save default tra, macl, mach, gbr, ssr, pr* and spc on the stack |
1d015cf0 MD |
431 | ! - save r15*, r14, r13, r12, r11, r10, r9, r8 on the stack |
432 | ! - switch bank | |
433 | ! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack | |
434 | ! k0 contains original stack pointer* | |
435 | ! k1 trashed | |
1d015cf0 | 436 | ! k3 passes original pr* |
2ef7f0da | 437 | ! k4 passes SR bitmask |
1d015cf0 MD |
438 | ! BL=1 on entry, on exit BL=0. |
439 | ||
2ef7f0da | 440 | ENTRY(save_regs) |
1d015cf0 | 441 | mov #-1, r1 |
1d015cf0 | 442 | mov.l k1, @-r15 ! set TRA (default: -1) |
1da177e4 LT |
443 | sts.l macl, @-r15 |
444 | sts.l mach, @-r15 | |
445 | stc.l gbr, @-r15 | |
446 | stc.l ssr, @-r15 | |
1d015cf0 | 447 | mov.l k3, @-r15 ! original pr in k3 |
1da177e4 | 448 | stc.l spc, @-r15 |
1d015cf0 MD |
449 | |
450 | mov.l k0, @-r15 ! original stack pointer in k0 | |
1da177e4 LT |
451 | mov.l r14, @-r15 |
452 | mov.l r13, @-r15 | |
453 | mov.l r12, @-r15 | |
454 | mov.l r11, @-r15 | |
455 | mov.l r10, @-r15 | |
456 | mov.l r9, @-r15 | |
457 | mov.l r8, @-r15 | |
1d015cf0 MD |
458 | |
459 | mov.l 0f, k3 ! SR bits to set in k3 | |
1d015cf0 | 460 | |
2ef7f0da MD |
461 | ! fall-through |
462 | ||
463 | ! save_low_regs() | |
464 | ! - modify SR for bank switch | |
465 | ! - save r7, r6, r5, r4, r3, r2, r1, r0 on the stack | |
466 | ! k3 passes bits to set in SR | |
467 | ! k4 passes bits to clear in SR | |
468 | ||
469 | ENTRY(save_low_regs) | |
1d015cf0 MD |
470 | stc sr, r8 |
471 | or k3, r8 | |
472 | and k4, r8 | |
473 | ldc r8, sr | |
474 | ||
1da177e4 LT |
475 | mov.l r7, @-r15 |
476 | mov.l r6, @-r15 | |
477 | mov.l r5, @-r15 | |
478 | mov.l r4, @-r15 | |
479 | mov.l r3, @-r15 | |
480 | mov.l r2, @-r15 | |
481 | mov.l r1, @-r15 | |
baf4326e | 482 | rts |
1d015cf0 | 483 | mov.l r0, @-r15 |
1da177e4 | 484 | |
1d015cf0 MD |
485 | ! |
486 | ! 0x600: Interrupt / NMI vector | |
487 | ! | |
488 | .balign 512,0,512 | |
489 | ENTRY(handle_interrupt) | |
490 | #if defined(CONFIG_KGDB) | |
491 | mov.l 2f, k2 | |
492 | ! Debounce (filter nested NMI) | |
493 | mov.l @k2, k0 | |
494 | mov.l 9f, k1 | |
495 | cmp/eq k1, k0 | |
496 | bf 11f | |
497 | mov.l 10f, k1 | |
498 | tas.b @k1 | |
499 | bt 11f | |
500 | rte | |
501 | nop | |
1da177e4 | 502 | .align 2 |
1d015cf0 MD |
503 | 9: .long NMI_VEC |
504 | 10: .long in_nmi | |
505 | 11: | |
506 | #endif /* defined(CONFIG_KGDB) */ | |
507 | sts pr, k3 ! save original pr value in k3 | |
0197f21c | 508 | mova exception_data, k0 |
1da177e4 | 509 | |
1d015cf0 | 510 | ! Setup stack and save DSP context (k0 contains original r15 on return) |
01ab1039 | 511 | bsr prepare_stack |
0197f21c | 512 | PREF(k0) |
baf4326e | 513 | |
1d015cf0 | 514 | ! Save registers / Switch to bank 0 |
2ef7f0da | 515 | mov.l 1f, k4 ! SR bits to clear in k4 |
1d015cf0 MD |
516 | bsr save_regs ! needs original pr value in k3 |
517 | mov #-1, k2 ! default vector kept in k2 | |
518 | ||
fe98dd31 MF |
519 | setup_frame_reg |
520 | ||
f3a83088 MF |
521 | stc sr, r0 ! get status register |
522 | shlr2 r0 | |
523 | and #0x3c, r0 | |
524 | cmp/eq #0x3c, r0 | |
525 | bf 9f | |
526 | TRACE_IRQS_OFF | |
527 | 9: | |
528 | ||
1d015cf0 MD |
529 | ! Setup return address and jump to do_IRQ |
530 | mov.l 4f, r9 ! fetch return address | |
531 | lds r9, pr ! put return address in pr | |
532 | mov.l 2f, r4 | |
533 | mov.l 3f, r9 | |
534 | mov.l @r4, r4 ! pass INTEVT vector as arg0 | |
1e1030dc PM |
535 | |
536 | shlr2 r4 | |
537 | shlr r4 | |
538 | mov r4, r0 ! save vector->jmp table offset for later | |
539 | ||
540 | shlr2 r4 ! vector to IRQ# conversion | |
541 | add #-0x10, r4 | |
542 | ||
543 | cmp/pz r4 ! is it a valid IRQ? | |
544 | bt 10f | |
545 | ||
546 | /* | |
547 | * We got here as a result of taking the INTEVT path for something | |
548 | * that isn't a valid hard IRQ, therefore we bypass the do_IRQ() | |
549 | * path and special case the event dispatch instead. This is the | |
550 | * expected path for the NMI (and any other brilliantly implemented | |
551 | * exception), which effectively wants regular exception dispatch | |
552 | * but is unfortunately reported through INTEVT rather than | |
553 | * EXPEVT. Grr. | |
554 | */ | |
555 | mov.l 6f, r9 | |
556 | mov.l @(r0, r9), r9 | |
1d015cf0 | 557 | jmp @r9 |
1e1030dc PM |
558 | mov r15, r8 ! trap handlers take saved regs in r8 |
559 | ||
560 | 10: | |
561 | jmp @r9 ! Off to do_IRQ() we go. | |
1d015cf0 | 562 | mov r15, r5 ! pass saved registers as arg1 |
baf4326e | 563 | |
1da177e4 LT |
564 | ENTRY(exception_none) |
565 | rts | |
566 | nop | |
1d015cf0 MD |
567 | |
568 | .align L1_CACHE_SHIFT | |
569 | exception_data: | |
570 | 0: .long 0x000080f0 ! FD=1, IMASK=15 | |
571 | 1: .long 0xcfffffff ! RB=0, BL=0 | |
572 | 2: .long INTEVT | |
573 | 3: .long do_IRQ | |
574 | 4: .long ret_from_irq | |
575 | 5: .long EXPEVT | |
576 | 6: .long exception_handling_table | |
577 | 7: .long ret_from_exception |