diff options
author | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-02-29 23:47:44 -0500 |
---|---|---|
committer | Benjamin Herrenschmidt <benh@kernel.crashing.org> | 2012-03-08 18:55:10 -0500 |
commit | 9f2f79e3a3c19ae745d0439d6e0eed31df28de3c (patch) | |
tree | 0f68f198e3ce6233c5c96d0267de9a73832858a4 /arch/powerpc | |
parent | a546498f3bf9aac311c66f965186373aee2ca0b0 (diff) |
powerpc: Disable interrupts in 64-bit kernel FP and vector faults
If we get a floating point, altivec or vsx unavaible interrupt in
kernel, we trigger a kernel error. There is no point preserving
the interrupt state, in fact, that can even make debugging harder
as the processor state might change (we may even preempt) between
taking the exception and landing in a debugger.
So just make those 3 disable interrupts unconditionally.
Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
---
v2: On BookE only disable when hitting the kernel unavailable
path, otherwise it will fail to restore softe as
fast_exception_return doesn't do it.
Diffstat (limited to 'arch/powerpc')
-rw-r--r-- | arch/powerpc/kernel/exceptions-64e.S | 7 | ||||
-rw-r--r-- | arch/powerpc/kernel/exceptions-64s.S | 6 | ||||
-rw-r--r-- | arch/powerpc/kernel/traps.c | 3 |
3 files changed, 9 insertions, 7 deletions
diff --git a/arch/powerpc/kernel/exceptions-64e.S b/arch/powerpc/kernel/exceptions-64e.S index 573613d747ac..3de9993c5c65 100644 --- a/arch/powerpc/kernel/exceptions-64e.S +++ b/arch/powerpc/kernel/exceptions-64e.S | |||
@@ -354,9 +354,9 @@ interrupt_end_book3e: | |||
354 | /* we can probably do a shorter exception entry for that one... */ | 354 | /* we can probably do a shorter exception entry for that one... */ |
355 | EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) | 355 | EXCEPTION_COMMON(0x800, PACA_EXGEN, INTS_KEEP) |
356 | bne 1f /* if from user, just load it up */ | 356 | bne 1f /* if from user, just load it up */ |
357 | INTS_DISABLE_ALL | ||
357 | bl .save_nvgprs | 358 | bl .save_nvgprs |
358 | addi r3,r1,STACK_FRAME_OVERHEAD | 359 | addi r3,r1,STACK_FRAME_OVERHEAD |
359 | INTS_RESTORE_HARD | ||
360 | bl .kernel_fp_unavailable_exception | 360 | bl .kernel_fp_unavailable_exception |
361 | BUG_OPCODE | 361 | BUG_OPCODE |
362 | 1: ld r12,_MSR(r1) | 362 | 1: ld r12,_MSR(r1) |
@@ -391,10 +391,9 @@ interrupt_end_book3e: | |||
391 | /* Auxiliary Processor Unavailable Interrupt */ | 391 | /* Auxiliary Processor Unavailable Interrupt */ |
392 | START_EXCEPTION(ap_unavailable); | 392 | START_EXCEPTION(ap_unavailable); |
393 | NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) | 393 | NORMAL_EXCEPTION_PROLOG(0xf20, PROLOG_ADDITION_NONE) |
394 | EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_KEEP) | 394 | EXCEPTION_COMMON(0xf20, PACA_EXGEN, INTS_DISABLE_ALL) |
395 | addi r3,r1,STACK_FRAME_OVERHEAD | ||
396 | bl .save_nvgprs | 395 | bl .save_nvgprs |
397 | INTS_RESTORE_HARD | 396 | addi r3,r1,STACK_FRAME_OVERHEAD |
398 | bl .unknown_exception | 397 | bl .unknown_exception |
399 | b .ret_from_except | 398 | b .ret_from_except |
400 | 399 | ||
diff --git a/arch/powerpc/kernel/exceptions-64s.S b/arch/powerpc/kernel/exceptions-64s.S index d8ff6d37fc4d..0fb42ae21694 100644 --- a/arch/powerpc/kernel/exceptions-64s.S +++ b/arch/powerpc/kernel/exceptions-64s.S | |||
@@ -762,8 +762,8 @@ fp_unavailable_common: | |||
762 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) | 762 | EXCEPTION_PROLOG_COMMON(0x800, PACA_EXGEN) |
763 | bne 1f /* if from user, just load it up */ | 763 | bne 1f /* if from user, just load it up */ |
764 | bl .save_nvgprs | 764 | bl .save_nvgprs |
765 | DISABLE_INTS | ||
765 | addi r3,r1,STACK_FRAME_OVERHEAD | 766 | addi r3,r1,STACK_FRAME_OVERHEAD |
766 | ENABLE_INTS | ||
767 | bl .kernel_fp_unavailable_exception | 767 | bl .kernel_fp_unavailable_exception |
768 | BUG_OPCODE | 768 | BUG_OPCODE |
769 | 1: bl .load_up_fpu | 769 | 1: bl .load_up_fpu |
@@ -782,8 +782,8 @@ BEGIN_FTR_SECTION | |||
782 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) | 782 | END_FTR_SECTION_IFSET(CPU_FTR_ALTIVEC) |
783 | #endif | 783 | #endif |
784 | bl .save_nvgprs | 784 | bl .save_nvgprs |
785 | DISABLE_INTS | ||
785 | addi r3,r1,STACK_FRAME_OVERHEAD | 786 | addi r3,r1,STACK_FRAME_OVERHEAD |
786 | ENABLE_INTS | ||
787 | bl .altivec_unavailable_exception | 787 | bl .altivec_unavailable_exception |
788 | b .ret_from_except | 788 | b .ret_from_except |
789 | 789 | ||
@@ -798,8 +798,8 @@ BEGIN_FTR_SECTION | |||
798 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) | 798 | END_FTR_SECTION_IFSET(CPU_FTR_VSX) |
799 | #endif | 799 | #endif |
800 | bl .save_nvgprs | 800 | bl .save_nvgprs |
801 | DISABLE_INTS | ||
801 | addi r3,r1,STACK_FRAME_OVERHEAD | 802 | addi r3,r1,STACK_FRAME_OVERHEAD |
802 | ENABLE_INTS | ||
803 | bl .vsx_unavailable_exception | 803 | bl .vsx_unavailable_exception |
804 | b .ret_from_except | 804 | b .ret_from_except |
805 | 805 | ||
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 5d40e592ffcb..a750409ccc4e 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -247,6 +247,9 @@ void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) | |||
247 | addr, regs->nip, regs->link, code); | 247 | addr, regs->nip, regs->link, code); |
248 | } | 248 | } |
249 | 249 | ||
250 | if (!arch_irq_disabled_regs(regs)) | ||
251 | local_irq_enable(); | ||
252 | |||
250 | memset(&info, 0, sizeof(info)); | 253 | memset(&info, 0, sizeof(info)); |
251 | info.si_signo = signr; | 254 | info.si_signo = signr; |
252 | info.si_code = code; | 255 | info.si_code = code; |