diff options
-rw-r--r-- | arch/x86/kernel/entry_32.S | 15 | ||||
-rw-r--r-- | arch/x86/kernel/traps_32.c | 14 |
2 files changed, 15 insertions, 14 deletions
diff --git a/arch/x86/kernel/entry_32.S b/arch/x86/kernel/entry_32.S index 109792bc7cfa..5a885855fc88 100644 --- a/arch/x86/kernel/entry_32.S +++ b/arch/x86/kernel/entry_32.S | |||
@@ -760,20 +760,9 @@ ENTRY(device_not_available) | |||
760 | RING0_INT_FRAME | 760 | RING0_INT_FRAME |
761 | pushl $-1 # mark this as an int | 761 | pushl $-1 # mark this as an int |
762 | CFI_ADJUST_CFA_OFFSET 4 | 762 | CFI_ADJUST_CFA_OFFSET 4 |
763 | SAVE_ALL | 763 | pushl $do_device_not_available |
764 | GET_CR0_INTO_EAX | ||
765 | testl $0x4, %eax # EM (math emulation bit) | ||
766 | jne device_not_available_emulate | ||
767 | preempt_stop(CLBR_ANY) | ||
768 | call math_state_restore | ||
769 | jmp ret_from_exception | ||
770 | device_not_available_emulate: | ||
771 | pushl $0 # temporary storage for ORIG_EIP | ||
772 | CFI_ADJUST_CFA_OFFSET 4 | 764 | CFI_ADJUST_CFA_OFFSET 4 |
773 | call math_emulate | 765 | jmp error_code |
774 | addl $4, %esp | ||
775 | CFI_ADJUST_CFA_OFFSET -4 | ||
776 | jmp ret_from_exception | ||
777 | CFI_ENDPROC | 766 | CFI_ENDPROC |
778 | END(device_not_available) | 767 | END(device_not_available) |
779 | 768 | ||
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 @@ | |||
46 | #include <linux/edac.h> | 46 | #include <linux/edac.h> |
47 | #endif | 47 | #endif |
48 | 48 | ||
49 | #include <asm/processor-flags.h> | ||
49 | #include <asm/arch_hooks.h> | 50 | #include <asm/arch_hooks.h> |
50 | #include <asm/stacktrace.h> | 51 | #include <asm/stacktrace.h> |
51 | #include <asm/processor.h> | 52 | #include <asm/processor.h> |
@@ -1236,6 +1237,17 @@ asmlinkage void math_emulate(long arg) | |||
1236 | 1237 | ||
1237 | #endif /* CONFIG_MATH_EMULATION */ | 1238 | #endif /* CONFIG_MATH_EMULATION */ |
1238 | 1239 | ||
1240 | void __kprobes do_device_not_available(struct pt_regs *regs, long error) | ||
1241 | { | ||
1242 | if (read_cr0() & X86_CR0_EM) { | ||
1243 | conditional_sti(regs); | ||
1244 | math_emulate(0); | ||
1245 | } else { | ||
1246 | math_state_restore(); /* interrupts still off */ | ||
1247 | conditional_sti(regs); | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1239 | void __init trap_init(void) | 1251 | void __init trap_init(void) |
1240 | { | 1252 | { |
1241 | int i; | 1253 | int i; |
@@ -1255,7 +1267,7 @@ void __init trap_init(void) | |||
1255 | set_system_intr_gate(4, &overflow); /* int4 can be called from all */ | 1267 | set_system_intr_gate(4, &overflow); /* int4 can be called from all */ |
1256 | set_intr_gate(5, &bounds); | 1268 | set_intr_gate(5, &bounds); |
1257 | set_intr_gate(6, &invalid_op); | 1269 | set_intr_gate(6, &invalid_op); |
1258 | set_trap_gate(7, &device_not_available); | 1270 | set_intr_gate(7, &device_not_available); |
1259 | set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); | 1271 | set_task_gate(8, GDT_ENTRY_DOUBLEFAULT_TSS); |
1260 | set_trap_gate(9, &coprocessor_segment_overrun); | 1272 | set_trap_gate(9, &coprocessor_segment_overrun); |
1261 | set_trap_gate(10, &invalid_TSS); | 1273 | set_trap_gate(10, &invalid_TSS); |