diff options
author | Alexander van Heukelum <heukelum@fastmail.fm> | 2008-09-09 21:56:02 +0200 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2008-10-13 10:20:17 +0200 |
commit | 7643e9b936b4af31ba4851eb7d5b3a3bfad52502 (patch) | |
tree | 1443d0d87a7d7c213253b5b46412fa467e21d6c1 /arch/x86/kernel/traps_32.c | |
parent | 12394cf567d509f6ab5d94544e1f414b35286d9e (diff) | |
download | talos-op-linux-7643e9b936b4af31ba4851eb7d5b3a3bfad52502.tar.gz talos-op-linux-7643e9b936b4af31ba4851eb7d5b3a3bfad52502.zip |
i386: convert hardware exception 7 to an interrupt gate
Handle no coprocessor exception with interrupt initially off.
device_not_available in entry_32.S calls either math_state_restore
or math_emulate. This patch adds an extra indirection to be
able to re-enable interrupts explicitly in traps_32.c
Signed-off-by: Alexander van Heukelum <heukelum@fastmail.fm>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/traps_32.c')
-rw-r--r-- | arch/x86/kernel/traps_32.c | 14 |
1 files changed, 13 insertions, 1 deletions
diff --git a/arch/x86/kernel/traps_32.c b/arch/x86/kernel/traps_32.c index 39a6101a6123..5b15f75d0591 100644 --- a/arch/x86/kernel/traps_32.c +++ b/arch/x86/kernel/traps_32.c @@ -46,6 +46,7 @@ #include <linux/edac.h> #endif +#include <asm/processor-flags.h> #include <asm/arch_hooks.h> #include <asm/stacktrace.h> #include <asm/processor.h> @@ -1236,6 +1237,17 @@ asmlinkage void math_emulate(long arg) #endif /* CONFIG_MATH_EMULATION */ +void __kprobes do_device_not_available(struct pt_regs *regs, long error) +{ + if (read_cr0() & X86_CR0_EM) { + conditional_sti(regs); + math_emulate(0); + } else { + math_state_restore(); /* interrupts still off */ + conditional_sti(regs); + } +} + void __init trap_init(void) { int i; @@ -1255,7 +1267,7 @@ void __init trap_init(void) set_system_intr_gate(4, &overflow); /* int4 can be called from all */ set_intr_gate(5, &bounds); set_intr_gate(6, &invalid_op); - set_trap_gate(7, &device_not_available); + set_intr_gate(7, &device_not_available); set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); set_trap_gate(9, &coprocessor_segment_overrun); set_trap_gate(10, &invalid_TSS); |