diff options
author | Kumar Gala <galak@kernel.crashing.org> | 2007-02-07 02:13:32 -0500 |
---|---|---|
committer | Kumar Gala <galak@kernel.crashing.org> | 2007-02-07 02:13:32 -0500 |
commit | 04903a30a327513b97c1271fc6bc4dad6502d1b8 (patch) | |
tree | 9761b3fbe0606102ee47d5fed12a50b9c9931280 | |
parent | 8209003547c4b1006943eac8dc6c1fb6493cafda (diff) |
[POWERPC] Enable interrupts if we are doing fp math emulation
Anytime we are emulating an instruction we are going to be doing some form of
get_user() to get the instruction image to decode. Since get_user() might
sleep we need to ensure we have interrupts enabled or we might see something
like:
Debug: sleeping function called from invalid context at arch/powerpc/kernel/traps.c:697
in_atomic():0, irqs_disabled():1
Call Trace:
[D6023EB0] [C0007F84] show_stack+0x58/0x174 (unreliable)
[D6023EE0] [C0022C34] __might_sleep+0xbc/0xd0
[D6023EF0] [C000D158] program_check_exception+0x1d8/0x4fc
[D6023F40] [C000E744] ret_from_except_full+0x0/0x4c
--- Exception: 700 at 0x102a7100
LR = 0xdb9ef04
However, we want to ensure that interrupts are disabled when handling a trap
exception that might be used for a kernel breakpoint. This is why ProgramCheck
is marked as EXC_XFER_STD instead of EXC_XFER_EE.
Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r-- | arch/powerpc/kernel/traps.c | 29 |
1 files changed, 15 insertions, 14 deletions
diff --git a/arch/powerpc/kernel/traps.c b/arch/powerpc/kernel/traps.c index 6915b91868b8..f038caa3c2b9 100644 --- a/arch/powerpc/kernel/traps.c +++ b/arch/powerpc/kernel/traps.c | |||
@@ -739,20 +739,7 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
739 | extern int do_mathemu(struct pt_regs *regs); | 739 | extern int do_mathemu(struct pt_regs *regs); |
740 | 740 | ||
741 | /* We can now get here via a FP Unavailable exception if the core | 741 | /* We can now get here via a FP Unavailable exception if the core |
742 | * has no FPU, in that case no reason flags will be set */ | 742 | * has no FPU, in that case the reason flags will be 0 */ |
743 | #ifdef CONFIG_MATH_EMULATION | ||
744 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | ||
745 | * but there seems to be a hardware bug on the 405GP (RevD) | ||
746 | * that means ESR is sometimes set incorrectly - either to | ||
747 | * ESR_DST (!?) or 0. In the process of chasing this with the | ||
748 | * hardware people - not sure if it can happen on any illegal | ||
749 | * instruction or only on FP instructions, whether there is a | ||
750 | * pattern to occurences etc. -dgibson 31/Mar/2003 */ | ||
751 | if (!(reason & REASON_TRAP) && do_mathemu(regs) == 0) { | ||
752 | emulate_single_step(regs); | ||
753 | return; | ||
754 | } | ||
755 | #endif /* CONFIG_MATH_EMULATION */ | ||
756 | 743 | ||
757 | if (reason & REASON_FP) { | 744 | if (reason & REASON_FP) { |
758 | /* IEEE FP exception */ | 745 | /* IEEE FP exception */ |
@@ -778,6 +765,20 @@ void __kprobes program_check_exception(struct pt_regs *regs) | |||
778 | 765 | ||
779 | local_irq_enable(); | 766 | local_irq_enable(); |
780 | 767 | ||
768 | #ifdef CONFIG_MATH_EMULATION | ||
769 | /* (reason & REASON_ILLEGAL) would be the obvious thing here, | ||
770 | * but there seems to be a hardware bug on the 405GP (RevD) | ||
771 | * that means ESR is sometimes set incorrectly - either to | ||
772 | * ESR_DST (!?) or 0. In the process of chasing this with the | ||
773 | * hardware people - not sure if it can happen on any illegal | ||
774 | * instruction or only on FP instructions, whether there is a | ||
775 | * pattern to occurences etc. -dgibson 31/Mar/2003 */ | ||
776 | if (do_mathemu(regs) == 0) { | ||
777 | emulate_single_step(regs); | ||
778 | return; | ||
779 | } | ||
780 | #endif /* CONFIG_MATH_EMULATION */ | ||
781 | |||
781 | /* Try to emulate it if we should. */ | 782 | /* Try to emulate it if we should. */ |
782 | if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { | 783 | if (reason & (REASON_ILLEGAL | REASON_PRIVILEGED)) { |
783 | switch (emulate_instruction(regs)) { | 784 | switch (emulate_instruction(regs)) { |