aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kernel/traps.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r--arch/x86/kernel/traps.c29
1 files changed, 20 insertions, 9 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 98c2d055284b..c05430ac1b44 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -54,15 +54,14 @@
54#include <asm/desc.h> 54#include <asm/desc.h>
55#include <asm/i387.h> 55#include <asm/i387.h>
56 56
57#include <mach_traps.h> 57#include <asm/mach_traps.h>
58 58
59#ifdef CONFIG_X86_64 59#ifdef CONFIG_X86_64
60#include <asm/pgalloc.h> 60#include <asm/pgalloc.h>
61#include <asm/proto.h> 61#include <asm/proto.h>
62#include <asm/pda.h>
63#else 62#else
64#include <asm/processor-flags.h> 63#include <asm/processor-flags.h>
65#include <asm/arch_hooks.h> 64#include <asm/setup.h>
66#include <asm/traps.h> 65#include <asm/traps.h>
67 66
68#include "cpu/mcheck/mce.h" 67#include "cpu/mcheck/mce.h"
@@ -99,6 +98,12 @@ static inline void preempt_conditional_sti(struct pt_regs *regs)
99 local_irq_enable(); 98 local_irq_enable();
100} 99}
101 100
101static inline void conditional_cli(struct pt_regs *regs)
102{
103 if (regs->flags & X86_EFLAGS_IF)
104 local_irq_disable();
105}
106
102static inline void preempt_conditional_cli(struct pt_regs *regs) 107static inline void preempt_conditional_cli(struct pt_regs *regs)
103{ 108{
104 if (regs->flags & X86_EFLAGS_IF) 109 if (regs->flags & X86_EFLAGS_IF)
@@ -626,8 +631,10 @@ clear_dr7:
626 631
627#ifdef CONFIG_X86_32 632#ifdef CONFIG_X86_32
628debug_vm86: 633debug_vm86:
634 /* reenable preemption: handle_vm86_trap() might sleep */
635 dec_preempt_count();
629 handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); 636 handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1);
630 preempt_conditional_cli(regs); 637 conditional_cli(regs);
631 return; 638 return;
632#endif 639#endif
633 640
@@ -896,7 +903,7 @@ asmlinkage void math_state_restore(void)
896EXPORT_SYMBOL_GPL(math_state_restore); 903EXPORT_SYMBOL_GPL(math_state_restore);
897 904
898#ifndef CONFIG_MATH_EMULATION 905#ifndef CONFIG_MATH_EMULATION
899asmlinkage void math_emulate(long arg) 906void math_emulate(struct math_emu_info *info)
900{ 907{
901 printk(KERN_EMERG 908 printk(KERN_EMERG
902 "math-emulation not enabled and no coprocessor found.\n"); 909 "math-emulation not enabled and no coprocessor found.\n");
@@ -907,12 +914,16 @@ asmlinkage void math_emulate(long arg)
907#endif /* CONFIG_MATH_EMULATION */ 914#endif /* CONFIG_MATH_EMULATION */
908 915
909dotraplinkage void __kprobes 916dotraplinkage void __kprobes
910do_device_not_available(struct pt_regs *regs, long error) 917do_device_not_available(struct pt_regs *regs, long error_code)
911{ 918{
912#ifdef CONFIG_X86_32 919#ifdef CONFIG_X86_32
913 if (read_cr0() & X86_CR0_EM) { 920 if (read_cr0() & X86_CR0_EM) {
921 struct math_emu_info info = { };
922
914 conditional_sti(regs); 923 conditional_sti(regs);
915 math_emulate(0); 924
925 info.regs = regs;
926 math_emulate(&info);
916 } else { 927 } else {
917 math_state_restore(); /* interrupts still off */ 928 math_state_restore(); /* interrupts still off */
918 conditional_sti(regs); 929 conditional_sti(regs);
@@ -931,7 +942,7 @@ dotraplinkage void do_iret_error(struct pt_regs *regs, long error_code)
931 info.si_signo = SIGILL; 942 info.si_signo = SIGILL;
932 info.si_errno = 0; 943 info.si_errno = 0;
933 info.si_code = ILL_BADSTK; 944 info.si_code = ILL_BADSTK;
934 info.si_addr = 0; 945 info.si_addr = NULL;
935 if (notify_die(DIE_TRAP, "iret exception", 946 if (notify_die(DIE_TRAP, "iret exception",
936 regs, error_code, 32, SIGILL) == NOTIFY_STOP) 947 regs, error_code, 32, SIGILL) == NOTIFY_STOP)
937 return; 948 return;
@@ -1015,6 +1026,6 @@ void __init trap_init(void)
1015 cpu_init(); 1026 cpu_init();
1016 1027
1017#ifdef CONFIG_X86_32 1028#ifdef CONFIG_X86_32
1018 trap_init_hook(); 1029 x86_quirk_trap_init();
1019#endif 1030#endif
1020} 1031}