diff options
Diffstat (limited to 'arch/powerpc/kernel/exceptions-64e.S')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 236 |
1 files changed, 155 insertions, 81 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 429983c06f91..7215cc2495df 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -24,6 +24,7 @@ | |||
24 | #include <asm/ptrace.h> | 24 | #include <asm/ptrace.h> |
25 | #include <asm/ppc-opcode.h> | 25 | #include <asm/ppc-opcode.h> |
26 | #include <asm/mmu.h> | 26 | #include <asm/mmu.h> |
27 | #include <asm/hw_irq.h> | ||
27 | 28 | ||
28 | /* XXX This will ultimately add space for a special exception save | 29 | /* XXX This will ultimately add space for a special exception save |
29 | * structure used to save things like SRR0/SRR1, SPRGs, MAS, etc... | 30 | * structure used to save things like SRR0/SRR1, SPRGs, MAS, etc... |
@@ -77,59 +78,55 @@ | |||
77 | #define SPRN_MC_SRR1 SPRN_MCSRR1 | 78 | #define SPRN_MC_SRR1 SPRN_MCSRR1 |
78 | 79 | ||
79 | #define NORMAL_EXCEPTION_PROLOG(n, addition) \ | 80 | #define NORMAL_EXCEPTION_PROLOG(n, addition) \ |
80 | EXCEPTION_PROLOG(n, GEN, addition##_GEN) | 81 | EXCEPTION_PROLOG(n, GEN, addition##_GEN(n)) |
81 | 82 | ||
82 | #define CRIT_EXCEPTION_PROLOG(n, addition) \ | 83 | #define CRIT_EXCEPTION_PROLOG(n, addition) \ |
83 | EXCEPTION_PROLOG(n, CRIT, addition##_CRIT) | 84 | EXCEPTION_PROLOG(n, CRIT, addition##_CRIT(n)) |
84 | 85 | ||
85 | #define DBG_EXCEPTION_PROLOG(n, addition) \ | 86 | #define DBG_EXCEPTION_PROLOG(n, addition) \ |
86 | EXCEPTION_PROLOG(n, DBG, addition##_DBG) | 87 | EXCEPTION_PROLOG(n, DBG, addition##_DBG(n)) |
87 | 88 | ||
88 | #define MC_EXCEPTION_PROLOG(n, addition) \ | 89 | #define MC_EXCEPTION_PROLOG(n, addition) \ |
89 | EXCEPTION_PROLOG(n, MC, addition##_MC) | 90 | EXCEPTION_PROLOG(n, MC, addition##_MC(n)) |
90 | 91 | ||
91 | 92 | ||
92 | /* Variants of the "addition" argument for the prolog | 93 | /* Variants of the "addition" argument for the prolog |
93 | */ | 94 | */ |
94 | #define PROLOG_ADDITION_NONE_GEN | 95 | #define PROLOG_ADDITION_NONE_GEN(n) |
95 | #define PROLOG_ADDITION_NONE_CRIT | 96 | #define PROLOG_ADDITION_NONE_CRIT(n) |
96 | #define PROLOG_ADDITION_NONE_DBG | 97 | #define PROLOG_ADDITION_NONE_DBG(n) |
97 | #define PROLOG_ADDITION_NONE_MC | 98 | #define PROLOG_ADDITION_NONE_MC(n) |
98 | 99 | ||
99 | #define PROLOG_ADDITION_MASKABLE_GEN \ | 100 | #define PROLOG_ADDITION_MASKABLE_GEN(n) \ |
100 | lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ | 101 | lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ |
101 | cmpwi cr0,r11,0; /* yes -> go out of line */ \ | 102 | cmpwi cr0,r11,0; /* yes -> go out of line */ \ |
102 | beq masked_interrupt_book3e; | 103 | beq masked_interrupt_book3e_##n |
103 | 104 | ||
104 | #define PROLOG_ADDITION_2REGS_GEN \ | 105 | #define PROLOG_ADDITION_2REGS_GEN(n) \ |
105 | std r14,PACA_EXGEN+EX_R14(r13); \ | 106 | std r14,PACA_EXGEN+EX_R14(r13); \ |
106 | std r15,PACA_EXGEN+EX_R15(r13) | 107 | std r15,PACA_EXGEN+EX_R15(r13) |
107 | 108 | ||
108 | #define PROLOG_ADDITION_1REG_GEN \ | 109 | #define PROLOG_ADDITION_1REG_GEN(n) \ |
109 | std r14,PACA_EXGEN+EX_R14(r13); | 110 | std r14,PACA_EXGEN+EX_R14(r13); |
110 | 111 | ||
111 | #define PROLOG_ADDITION_2REGS_CRIT \ | 112 | #define PROLOG_ADDITION_2REGS_CRIT(n) \ |
112 | std r14,PACA_EXCRIT+EX_R14(r13); \ | 113 | std r14,PACA_EXCRIT+EX_R14(r13); \ |
113 | std r15,PACA_EXCRIT+EX_R15(r13) | 114 | std r15,PACA_EXCRIT+EX_R15(r13) |
114 | 115 | ||
115 | #define PROLOG_ADDITION_2REGS_DBG \ | 116 | #define PROLOG_ADDITION_2REGS_DBG(n) \ |
116 | std r14,PACA_EXDBG+EX_R14(r13); \ | 117 | std r14,PACA_EXDBG+EX_R14(r13); \ |
117 | std r15,PACA_EXDBG+EX_R15(r13) | 118 | std r15,PACA_EXDBG+EX_R15(r13) |
118 | 119 | ||
119 | #define PROLOG_ADDITION_2REGS_MC \ | 120 | #define PROLOG_ADDITION_2REGS_MC(n) \ |
120 | std r14,PACA_EXMC+EX_R14(r13); \ | 121 | std r14,PACA_EXMC+EX_R14(r13); \ |
121 | std r15,PACA_EXMC+EX_R15(r13) | 122 | std r15,PACA_EXMC+EX_R15(r13) |
122 | 123 | ||
123 | #define PROLOG_ADDITION_DOORBELL_GEN \ | ||
124 | lbz r11,PACASOFTIRQEN(r13); /* are irqs soft-disabled ? */ \ | ||
125 | cmpwi cr0,r11,0; /* yes -> go out of line */ \ | ||
126 | beq masked_doorbell_book3e | ||
127 | |||
128 | 124 | ||
129 | /* Core exception code for all exceptions except TLB misses. | 125 | /* Core exception code for all exceptions except TLB misses. |
130 | * XXX: Needs to make SPRN_SPRG_GEN depend on exception type | 126 | * XXX: Needs to make SPRN_SPRG_GEN depend on exception type |
131 | */ | 127 | */ |
132 | #define EXCEPTION_COMMON(n, excf, ints) \ | 128 | #define EXCEPTION_COMMON(n, excf, ints) \ |
129 | exc_##n##_common: \ | ||
133 | std r0,GPR0(r1); /* save r0 in stackframe */ \ | 130 | std r0,GPR0(r1); /* save r0 in stackframe */ \ |
134 | std r2,GPR2(r1); /* save r2 in stackframe */ \ | 131 | std r2,GPR2(r1); /* save r2 in stackframe */ \ |
135 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ | 132 | SAVE_4GPRS(3, r1); /* save r3 - r6 in stackframe */ \ |
@@ -167,20 +164,21 @@ | |||
167 | std r0,RESULT(r1); /* clear regs->result */ \ | 164 | std r0,RESULT(r1); /* clear regs->result */ \ |
168 | ints; | 165 | ints; |
169 | 166 | ||
170 | /* Variants for the "ints" argument */ | 167 | /* Variants for the "ints" argument. This one does nothing when we want |
168 | * to keep interrupts in their original state | ||
169 | */ | ||
171 | #define INTS_KEEP | 170 | #define INTS_KEEP |
172 | #define INTS_DISABLE_SOFT \ | 171 | |
173 | stb r0,PACASOFTIRQEN(r13); /* mark interrupts soft-disabled */ \ | 172 | /* This second version is meant for exceptions that don't immediately |
174 | TRACE_DISABLE_INTS; | 173 | * hard-enable. We set a bit in paca->irq_happened to ensure that |
175 | #define INTS_DISABLE_HARD \ | 174 | * a subsequent call to arch_local_irq_restore() will properly |
176 | stb r0,PACAHARDIRQEN(r13); /* and hard disabled */ | 175 | * hard-enable and avoid the fast-path |
177 | #define INTS_DISABLE_ALL \ | 176 | */ |
178 | INTS_DISABLE_SOFT \ | 177 | #define INTS_DISABLE SOFT_DISABLE_INTS(r3,r4) |
179 | INTS_DISABLE_HARD | 178 | |
180 | 179 | /* This is called by exceptions that used INTS_KEEP (that did not touch | |
181 | /* This is called by exceptions that used INTS_KEEP (that is did not clear | 180 | * irq indicators in the PACA). This will restore MSR:EE to it's previous |
182 | * neither soft nor hard IRQ indicators in the PACA. This will restore MSR:EE | 181 | * value |
183 | * to it's previous value | ||
184 | * | 182 | * |
185 | * XXX In the long run, we may want to open-code it in order to separate the | 183 | * XXX In the long run, we may want to open-code it in order to separate the |
186 | * load from the wrtee, thus limiting the latency caused by the dependency | 184 | * load from the wrtee, thus limiting the latency caused by the dependency |
@@ -238,7 +236,7 @@ exc_##n##_bad_stack: \ | |||
238 | #define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ | 236 | #define MASKABLE_EXCEPTION(trapnum, label, hdlr, ack) \ |
239 | START_EXCEPTION(label); \ | 237 | START_EXCEPTION(label); \ |
240 | NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ | 238 | NORMAL_EXCEPTION_PROLOG(trapnum, PROLOG_ADDITION_MASKABLE) \ |
241 | EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE_ALL) \ | 239 | EXCEPTION_COMMON(trapnum, PACA_EXGEN, INTS_DISABLE) \ |
242 | ack(r8); \ | 240 | ack(r8); \ |
243 | CHECK_NAPPING(); \ | 241 | CHECK_NAPPING(); \ |
244 | addi r3,r1,STACK_FRAME_OVERHEAD; \ | 242 | addi r3,r1,STACK_FRAME_OVERHEAD; \ |
@@ -289,7 +287,7 @@ interrupt_end_book3e: | |||
289 | /* Critical Input Interrupt */ | 287 | /* Critical Input Interrupt */ |
290 | START_EXCEPTION(critical_input); | 288 | START_EXCEPTION(critical_input); |
291 | CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) | 289 | CRIT_EXCEPTION_PROLOG(0x100, PROLOG_ADDITION_NONE) |
292 | // EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE_ALL) | 290 | // EXCEPTION_COMMON(0x100, PACA_EXCRIT, INTS_DISABLE) |
293 | // bl special_reg_save_crit | 291 | // bl special_reg_save_crit |
294 | // CHECK_NAPPING(); | 292 | // CHECK_NAPPING(); |
295 | // addi r3,r1,STACK_FRAME_OVERHEAD | 293 | // addi r3,r1,STACK_FRAME_OVERHEAD |
@@ -300,7 +298,7 @@ interrupt_end_book3e: | |||
300 | /* Machine Check Interrupt */ | 298 | /* Machine Check Interrupt */ |
301 | START_EXCEPTION(machine_check); | 299 | START_EXCEPTION(machine_check); |
302 | CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE) | 300 | CRIT_EXCEPTION_PROLOG(0x200, PROLOG_ADDITION_NONE) |
303 | // EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE_ALL) | 301 | // EXCEPTION_COMMON(0x200, PACA_EXMC, INTS_DISABLE) |
304 | // bl special_reg_save_mc | 302 | // bl special_reg_save_mc |
305 | // addi r3,r1,STACK_FRAME_OVERHEAD | 303 | // addi r3,r1,STACK_FRAME_OVERHEAD |
306 | // CHECK_NAPPING(); | 304 | // CHECK_NAPPING(); |
@@ -313,7 +311,7 @@ interrupt_end_book3e: | |||
313 | NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS) | 311 | NORMAL_EXCEPTION_PROLOG(0x300, PROLOG_ADDITION_2REGS) |
314 | mfspr r14,SPRN_DEAR | 312 | mfspr r14,SPRN_DEAR |
315 | mfspr r15,SPRN_ESR | 313 | mfspr r15,SPRN_ESR |
316 | EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_KEEP) | 314 | EXCEPTION_COMMON(0x300, PACA_EXGEN, INTS_DISABLE) |
317 | b storage_fault_common | 315 | b storage_fault_common |
318 | 316 | ||
319 | /* Instruction Storage Interrupt */ | 317 | /* Instruction Storage Interrupt */ |
@@ -321,7 +319,7 @@ interrupt_end_book3e: | |||
321 | NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS) | 319 | NORMAL_EXCEPTION_PROLOG(0x400, PROLOG_ADDITION_2REGS) |
322 | li r15,0 | 320 | li r15,0 |
323 | mr r14,r10 | 321 | mr r14,r10 |
324 | EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_KEEP) | 322 | EXCEPTION_COMMON(0x400, PACA_EXGEN, INTS_DISABLE) |
325 | b storage_fault_common | 323 | b storage_fault_common |
326 | 324 | ||
327 | /* External Input Interrupt */ | 325 | /* External Input Interrupt */ |
@@ -339,12 +337,11 @@ interrupt_end_book3e: | |||
339 | START_EXCEPTION(program); | 337 | START_EXCEPTION(program); |
340 | NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG) | 338 | NORMAL_EXCEPTION_PROLOG(0x700, PROLOG_ADDITION_1REG) |
341 | mfspr r14,SPRN_ESR | 339 | mfspr r14,SPRN_ESR |
342 | EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE_SOFT) | 340 | EXCEPTION_COMMON(0x700, PACA_EXGEN, INTS_DISABLE) |
343 | std r14,_DSISR(r1) | 341 | std r14,_DSISR(r1) |
344 | addi r3,r1,STACK_FRAME_OVERHEAD | 342 | addi r3,r1,STACK_FRAME_OVERHEAD |
345 | ld r14,PACA_EXGEN+EX_R14(r13) | 343 | ld r14,PACA_EXGEN+EX_R14(r13) |
346 | bl .save_nvgprs | 344 | bl .save_nvgprs |
347 | INTS_RESTORE_HARD | ||
348 | bl .program_check_exception | 345 | bl .program_check_exception |
349 | b .ret_from_except | 346 | b .ret_from_except |
350 | 347 | ||
@@ -353,15 +350,16 @@ interrupt_end_book3e: | |||
353 | NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE) | 350 | NORMAL_EXCEPTION_PROLOG(0x800, PROLOG_ADDITION_NONE) |
354 | /* we can probably do a shorter exception entry for that one... */ | 351 | /* we can probably do a shorter exception entry for that one... */ |
355 | EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) | 352 | EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) |
356 | bne 1f /* if from user, just load it up */ | 353 | ld r12,_MSR(r1) |
354 | andi. r0,r12,MSR_PR; | ||
355 | beq- 1f | ||
356 | bl .load_up_fpu | ||
357 | b fast_exception_return | ||
358 | 1: INTS_DISABLE | ||
357 | bl .save_nvgprs | 359 | bl .save_nvgprs |
358 | addi r3,r1,STACK_FRAME_OVERHEAD | 360 | addi r3,r1,STACK_FRAME_OVERHEAD |
359 | INTS_RESTORE_HARD | ||
360 | bl .kernel_fp_unavailable_exception | 361 | bl .kernel_fp_unavailable_exception |
361 | BUG_OPCODE | 362 | b .ret_from_except |
362 | 1: ld r12,_MSR(r1) | ||
363 | bl .load_up_fpu | ||
364 | b fast_exception_return | ||
365 | 363 | ||
366 | /* Decrementer Interrupt */ | 364 | /* Decrementer Interrupt */ |
367 | MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC) | 365 | MASKABLE_EXCEPTION(0x900, decrementer, .timer_interrupt, ACK_DEC) |
@@ -372,7 +370,7 @@ interrupt_end_book3e: | |||
372 | /* Watchdog Timer Interrupt */ | 370 | /* Watchdog Timer Interrupt */ |
373 | START_EXCEPTION(watchdog); | 371 | START_EXCEPTION(watchdog); |
374 | CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) | 372 | CRIT_EXCEPTION_PROLOG(0x9f0, PROLOG_ADDITION_NONE) |
375 | // EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE_ALL) | 373 | // EXCEPTION_COMMON(0x9f0, PACA_EXCRIT, INTS_DISABLE) |
376 | // bl special_reg_save_crit | 374 | // bl special_reg_save_crit |
377 | // CHECK_NAPPING(); | 375 | // CHECK_NAPPING(); |
378 | // addi r3,r1,STACK_FRAME_OVERHEAD | 376 | // addi r3,r1,STACK_FRAME_OVERHEAD |
@@ -391,10 +389,9 @@ interrupt_end_book3e: | |||
391 | /* Auxiliary Processor Unavailable Interrupt */ | 389 | /* Auxiliary Processor Unavailable Interrupt */ |
392 | START_EXCEPTION(ap_unavailable); | 390 | START_EXCEPTION(ap_unavailable); |
393 | NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) | 391 | NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) |
394 | EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP) | 392 | EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE) |
395 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
396 | bl .save_nvgprs | 393 | bl .save_nvgprs |
397 | INTS_RESTORE_HARD | 394 | addi r3,r1,STACK_FRAME_OVERHEAD |
398 | bl .unknown_exception | 395 | bl .unknown_exception |
399 | b .ret_from_except | 396 | b .ret_from_except |
400 | 397 | ||
@@ -450,7 +447,7 @@ interrupt_end_book3e: | |||
450 | mfspr r15,SPRN_SPRG_CRIT_SCRATCH | 447 | mfspr r15,SPRN_SPRG_CRIT_SCRATCH |
451 | mtspr SPRN_SPRG_GEN_SCRATCH,r15 | 448 | mtspr SPRN_SPRG_GEN_SCRATCH,r15 |
452 | mfspr r14,SPRN_DBSR | 449 | mfspr r14,SPRN_DBSR |
453 | EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE_ALL) | 450 | EXCEPTION_COMMON(0xd00, PACA_EXCRIT, INTS_DISABLE) |
454 | std r14,_DSISR(r1) | 451 | std r14,_DSISR(r1) |
455 | addi r3,r1,STACK_FRAME_OVERHEAD | 452 | addi r3,r1,STACK_FRAME_OVERHEAD |
456 | mr r4,r14 | 453 | mr r4,r14 |
@@ -465,7 +462,7 @@ kernel_dbg_exc: | |||
465 | 462 | ||
466 | /* Debug exception as a debug interrupt*/ | 463 | /* Debug exception as a debug interrupt*/ |
467 | START_EXCEPTION(debug_debug); | 464 | START_EXCEPTION(debug_debug); |
468 | DBG_EXCEPTION_PROLOG(0xd00, PROLOG_ADDITION_2REGS) | 465 | DBG_EXCEPTION_PROLOG(0xd08, PROLOG_ADDITION_2REGS) |
469 | 466 | ||
470 | /* | 467 | /* |
471 | * If there is a single step or branch-taken exception in an | 468 | * If there is a single step or branch-taken exception in an |
@@ -515,7 +512,7 @@ kernel_dbg_exc: | |||
515 | mfspr r15,SPRN_SPRG_DBG_SCRATCH | 512 | mfspr r15,SPRN_SPRG_DBG_SCRATCH |
516 | mtspr SPRN_SPRG_GEN_SCRATCH,r15 | 513 | mtspr SPRN_SPRG_GEN_SCRATCH,r15 |
517 | mfspr r14,SPRN_DBSR | 514 | mfspr r14,SPRN_DBSR |
518 | EXCEPTION_COMMON(0xd00, PACA_EXDBG, INTS_DISABLE_ALL) | 515 | EXCEPTION_COMMON(0xd08, PACA_EXDBG, INTS_DISABLE) |
519 | std r14,_DSISR(r1) | 516 | std r14,_DSISR(r1) |
520 | addi r3,r1,STACK_FRAME_OVERHEAD | 517 | addi r3,r1,STACK_FRAME_OVERHEAD |
521 | mr r4,r14 | 518 | mr r4,r14 |
@@ -525,21 +522,20 @@ kernel_dbg_exc: | |||
525 | bl .DebugException | 522 | bl .DebugException |
526 | b .ret_from_except | 523 | b .ret_from_except |
527 | 524 | ||
528 | MASKABLE_EXCEPTION(0x260, perfmon, .performance_monitor_exception, ACK_NONE) | 525 | START_EXCEPTION(perfmon); |
529 | 526 | NORMAL_EXCEPTION_PROLOG(0x260, PROLOG_ADDITION_NONE) | |
530 | /* Doorbell interrupt */ | 527 | EXCEPTION_COMMON(0x260, PACA_EXGEN, INTS_DISABLE) |
531 | START_EXCEPTION(doorbell) | ||
532 | NORMAL_EXCEPTION_PROLOG(0x2070, PROLOG_ADDITION_DOORBELL) | ||
533 | EXCEPTION_COMMON(0x2070, PACA_EXGEN, INTS_DISABLE_ALL) | ||
534 | CHECK_NAPPING() | ||
535 | addi r3,r1,STACK_FRAME_OVERHEAD | 528 | addi r3,r1,STACK_FRAME_OVERHEAD |
536 | bl .doorbell_exception | 529 | bl .performance_monitor_exception |
537 | b .ret_from_except_lite | 530 | b .ret_from_except_lite |
538 | 531 | ||
532 | /* Doorbell interrupt */ | ||
533 | MASKABLE_EXCEPTION(0x280, doorbell, .doorbell_exception, ACK_NONE) | ||
534 | |||
539 | /* Doorbell critical Interrupt */ | 535 | /* Doorbell critical Interrupt */ |
540 | START_EXCEPTION(doorbell_crit); | 536 | START_EXCEPTION(doorbell_crit); |
541 | CRIT_EXCEPTION_PROLOG(0x2080, PROLOG_ADDITION_NONE) | 537 | CRIT_EXCEPTION_PROLOG(0x2a0, PROLOG_ADDITION_NONE) |
542 | // EXCEPTION_COMMON(0x2080, PACA_EXCRIT, INTS_DISABLE_ALL) | 538 | // EXCEPTION_COMMON(0x2a0, PACA_EXCRIT, INTS_DISABLE) |
543 | // bl special_reg_save_crit | 539 | // bl special_reg_save_crit |
544 | // CHECK_NAPPING(); | 540 | // CHECK_NAPPING(); |
545 | // addi r3,r1,STACK_FRAME_OVERHEAD | 541 | // addi r3,r1,STACK_FRAME_OVERHEAD |
@@ -547,36 +543,114 @@ kernel_dbg_exc: | |||
547 | // b ret_from_crit_except | 543 | // b ret_from_crit_except |
548 | b . | 544 | b . |
549 | 545 | ||
546 | /* Guest Doorbell */ | ||
550 | MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE) | 547 | MASKABLE_EXCEPTION(0x2c0, guest_doorbell, .unknown_exception, ACK_NONE) |
551 | MASKABLE_EXCEPTION(0x2e0, guest_doorbell_crit, .unknown_exception, ACK_NONE) | ||
552 | MASKABLE_EXCEPTION(0x310, hypercall, .unknown_exception, ACK_NONE) | ||
553 | MASKABLE_EXCEPTION(0x320, ehpriv, .unknown_exception, ACK_NONE) | ||
554 | 548 | ||
549 | /* Guest Doorbell critical Interrupt */ | ||
550 | START_EXCEPTION(guest_doorbell_crit); | ||
551 | CRIT_EXCEPTION_PROLOG(0x2e0, PROLOG_ADDITION_NONE) | ||
552 | // EXCEPTION_COMMON(0x2e0, PACA_EXCRIT, INTS_DISABLE) | ||
553 | // bl special_reg_save_crit | ||
554 | // CHECK_NAPPING(); | ||
555 | // addi r3,r1,STACK_FRAME_OVERHEAD | ||
556 | // bl .guest_doorbell_critical_exception | ||
557 | // b ret_from_crit_except | ||
558 | b . | ||
559 | |||
560 | /* Hypervisor call */ | ||
561 | START_EXCEPTION(hypercall); | ||
562 | NORMAL_EXCEPTION_PROLOG(0x310, PROLOG_ADDITION_NONE) | ||
563 | EXCEPTION_COMMON(0x310, PACA_EXGEN, INTS_KEEP) | ||
564 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
565 | bl .save_nvgprs | ||
566 | INTS_RESTORE_HARD | ||
567 | bl .unknown_exception | ||
568 | b .ret_from_except | ||
569 | |||
570 | /* Embedded Hypervisor priviledged */ | ||
571 | START_EXCEPTION(ehpriv); | ||
572 | NORMAL_EXCEPTION_PROLOG(0x320, PROLOG_ADDITION_NONE) | ||
573 | EXCEPTION_COMMON(0x320, PACA_EXGEN, INTS_KEEP) | ||
574 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
575 | bl .save_nvgprs | ||
576 | INTS_RESTORE_HARD | ||
577 | bl .unknown_exception | ||
578 | b .ret_from_except | ||
555 | 579 | ||
556 | /* | 580 | /* |
557 | * An interrupt came in while soft-disabled; clear EE in SRR1, | 581 | * An interrupt came in while soft-disabled; We mark paca->irq_happened |
558 | * clear paca->hard_enabled and return. | 582 | * accordingly and if the interrupt is level sensitive, we hard disable |
559 | */ | 583 | */ |
560 | masked_doorbell_book3e: | ||
561 | mtcr r10 | ||
562 | /* Resend the doorbell to fire again when ints enabled */ | ||
563 | mfspr r10,SPRN_PIR | ||
564 | PPC_MSGSND(r10) | ||
565 | b masked_interrupt_book3e_common | ||
566 | 584 | ||
567 | masked_interrupt_book3e: | 585 | masked_interrupt_book3e_0x500: |
586 | /* XXX When adding support for EPR, use PACA_IRQ_EE_EDGE */ | ||
587 | li r11,PACA_IRQ_EE | ||
588 | b masked_interrupt_book3e_full_mask | ||
589 | |||
590 | masked_interrupt_book3e_0x900: | ||
591 | ACK_DEC(r11); | ||
592 | li r11,PACA_IRQ_DEC | ||
593 | b masked_interrupt_book3e_no_mask | ||
594 | masked_interrupt_book3e_0x980: | ||
595 | ACK_FIT(r11); | ||
596 | li r11,PACA_IRQ_DEC | ||
597 | b masked_interrupt_book3e_no_mask | ||
598 | masked_interrupt_book3e_0x280: | ||
599 | masked_interrupt_book3e_0x2c0: | ||
600 | li r11,PACA_IRQ_DBELL | ||
601 | b masked_interrupt_book3e_no_mask | ||
602 | |||
603 | masked_interrupt_book3e_no_mask: | ||
604 | mtcr r10 | ||
605 | lbz r10,PACAIRQHAPPENED(r13) | ||
606 | or r10,r10,r11 | ||
607 | stb r10,PACAIRQHAPPENED(r13) | ||
608 | b 1f | ||
609 | masked_interrupt_book3e_full_mask: | ||
568 | mtcr r10 | 610 | mtcr r10 |
569 | masked_interrupt_book3e_common: | 611 | lbz r10,PACAIRQHAPPENED(r13) |
570 | stb r11,PACAHARDIRQEN(r13) | 612 | or r10,r10,r11 |
613 | stb r10,PACAIRQHAPPENED(r13) | ||
571 | mfspr r10,SPRN_SRR1 | 614 | mfspr r10,SPRN_SRR1 |
572 | rldicl r11,r10,48,1 /* clear MSR_EE */ | 615 | rldicl r11,r10,48,1 /* clear MSR_EE */ |
573 | rotldi r10,r11,16 | 616 | rotldi r10,r11,16 |
574 | mtspr SPRN_SRR1,r10 | 617 | mtspr SPRN_SRR1,r10 |
575 | ld r10,PACA_EXGEN+EX_R10(r13); /* restore registers */ | 618 | 1: ld r10,PACA_EXGEN+EX_R10(r13); |
576 | ld r11,PACA_EXGEN+EX_R11(r13); | 619 | ld r11,PACA_EXGEN+EX_R11(r13); |
577 | mfspr r13,SPRN_SPRG_GEN_SCRATCH; | 620 | mfspr r13,SPRN_SPRG_GEN_SCRATCH; |
578 | rfi | 621 | rfi |
579 | b . | 622 | b . |
623 | /* | ||
624 | * Called from arch_local_irq_enable when an interrupt needs | ||
625 | * to be resent. r3 contains either 0x500,0x900,0x260 or 0x280 | ||
626 | * to indicate the kind of interrupt. MSR:EE is already off. | ||
627 | * We generate a stackframe like if a real interrupt had happened. | ||
628 | * | ||
629 | * Note: While MSR:EE is off, we need to make sure that _MSR | ||
630 | * in the generated frame has EE set to 1 or the exception | ||
631 | * handler will not properly re-enable them. | ||
632 | */ | ||
633 | _GLOBAL(__replay_interrupt) | ||
634 | /* We are going to jump to the exception common code which | ||
635 | * will retrieve various register values from the PACA which | ||
636 | * we don't give a damn about. | ||
637 | */ | ||
638 | mflr r10 | ||
639 | mfmsr r11 | ||
640 | mfcr r4 | ||
641 | mtspr SPRN_SPRG_GEN_SCRATCH,r13; | ||
642 | std r1,PACA_EXGEN+EX_R1(r13); | ||
643 | stw r4,PACA_EXGEN+EX_CR(r13); | ||
644 | ori r11,r11,MSR_EE | ||
645 | subi r1,r1,INT_FRAME_SIZE; | ||
646 | cmpwi cr0,r3,0x500 | ||
647 | beq exc_0x500_common | ||
648 | cmpwi cr0,r3,0x900 | ||
649 | beq exc_0x900_common | ||
650 | cmpwi cr0,r3,0x280 | ||
651 | beq exc_0x280_common | ||
652 | blr | ||
653 | |||
580 | 654 | ||
581 | /* | 655 | /* |
582 | * This is called from 0x300 and 0x400 handlers after the prologs with | 656 | * This is called from 0x300 and 0x400 handlers after the prologs with |
@@ -591,7 +665,6 @@ storage_fault_common: | |||
591 | mr r5,r15 | 665 | mr r5,r15 |
592 | ld r14,PACA_EXGEN+EX_R14(r13) | 666 | ld r14,PACA_EXGEN+EX_R14(r13) |
593 | ld r15,PACA_EXGEN+EX_R15(r13) | 667 | ld r15,PACA_EXGEN+EX_R15(r13) |
594 | INTS_RESTORE_HARD | ||
595 | bl .do_page_fault | 668 | bl .do_page_fault |
596 | cmpdi r3,0 | 669 | cmpdi r3,0 |
597 | bne- 1f | 670 | bne- 1f |
@@ -680,6 +753,8 @@ BAD_STACK_TRAMPOLINE(0x000) | |||
680 | BAD_STACK_TRAMPOLINE(0x100) | 753 | BAD_STACK_TRAMPOLINE(0x100) |
681 | BAD_STACK_TRAMPOLINE(0x200) | 754 | BAD_STACK_TRAMPOLINE(0x200) |
682 | BAD_STACK_TRAMPOLINE(0x260) | 755 | BAD_STACK_TRAMPOLINE(0x260) |
756 | BAD_STACK_TRAMPOLINE(0x280) | ||
757 | BAD_STACK_TRAMPOLINE(0x2a0) | ||
683 | BAD_STACK_TRAMPOLINE(0x2c0) | 758 | BAD_STACK_TRAMPOLINE(0x2c0) |
684 | BAD_STACK_TRAMPOLINE(0x2e0) | 759 | BAD_STACK_TRAMPOLINE(0x2e0) |
685 | BAD_STACK_TRAMPOLINE(0x300) | 760 | BAD_STACK_TRAMPOLINE(0x300) |
@@ -697,11 +772,10 @@ BAD_STACK_TRAMPOLINE(0xa00) | |||
697 | BAD_STACK_TRAMPOLINE(0xb00) | 772 | BAD_STACK_TRAMPOLINE(0xb00) |
698 | BAD_STACK_TRAMPOLINE(0xc00) | 773 | BAD_STACK_TRAMPOLINE(0xc00) |
699 | BAD_STACK_TRAMPOLINE(0xd00) | 774 | BAD_STACK_TRAMPOLINE(0xd00) |
775 | BAD_STACK_TRAMPOLINE(0xd08) | ||
700 | BAD_STACK_TRAMPOLINE(0xe00) | 776 | BAD_STACK_TRAMPOLINE(0xe00) |
701 | BAD_STACK_TRAMPOLINE(0xf00) | 777 | BAD_STACK_TRAMPOLINE(0xf00) |
702 | BAD_STACK_TRAMPOLINE(0xf20) | 778 | BAD_STACK_TRAMPOLINE(0xf20) |
703 | BAD_STACK_TRAMPOLINE(0x2070) | ||
704 | BAD_STACK_TRAMPOLINE(0x2080) | ||
705 | 779 | ||
706 | .globl bad_stack_book3e | 780 | .globl bad_stack_book3e |
707 | bad_stack_book3e: | 781 | bad_stack_book3e: |