diff options
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r-- | arch/x86/kernel/traps.c | 25 |
1 files changed, 18 insertions, 7 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 98c2d055284b..a9e7548e1790 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -99,6 +99,12 @@ static inline void preempt_conditional_sti(struct pt_regs *regs) | |||
99 | local_irq_enable(); | 99 | local_irq_enable(); |
100 | } | 100 | } |
101 | 101 | ||
102 | static inline void conditional_cli(struct pt_regs *regs) | ||
103 | { | ||
104 | if (regs->flags & X86_EFLAGS_IF) | ||
105 | local_irq_disable(); | ||
106 | } | ||
107 | |||
102 | static inline void preempt_conditional_cli(struct pt_regs *regs) | 108 | static inline void preempt_conditional_cli(struct pt_regs *regs) |
103 | { | 109 | { |
104 | if (regs->flags & X86_EFLAGS_IF) | 110 | if (regs->flags & X86_EFLAGS_IF) |
@@ -626,8 +632,10 @@ clear_dr7: | |||
626 | 632 | ||
627 | #ifdef CONFIG_X86_32 | 633 | #ifdef CONFIG_X86_32 |
628 | debug_vm86: | 634 | debug_vm86: |
635 | /* reenable preemption: handle_vm86_trap() might sleep */ | ||
636 | dec_preempt_count(); | ||
629 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); | 637 | handle_vm86_trap((struct kernel_vm86_regs *) regs, error_code, 1); |
630 | preempt_conditional_cli(regs); | 638 | conditional_cli(regs); |
631 | return; | 639 | return; |
632 | #endif | 640 | #endif |
633 | 641 | ||
@@ -896,7 +904,7 @@ asmlinkage void math_state_restore(void) | |||
896 | EXPORT_SYMBOL_GPL(math_state_restore); | 904 | EXPORT_SYMBOL_GPL(math_state_restore); |
897 | 905 | ||
898 | #ifndef CONFIG_MATH_EMULATION | 906 | #ifndef CONFIG_MATH_EMULATION |
899 | asmlinkage void math_emulate(long arg) | 907 | void math_emulate(struct math_emu_info *info) |
900 | { | 908 | { |
901 | printk(KERN_EMERG | 909 | printk(KERN_EMERG |
902 | "math-emulation not enabled and no coprocessor found.\n"); | 910 | "math-emulation not enabled and no coprocessor found.\n"); |
@@ -906,16 +914,19 @@ asmlinkage void math_emulate(long arg) | |||
906 | } | 914 | } |
907 | #endif /* CONFIG_MATH_EMULATION */ | 915 | #endif /* CONFIG_MATH_EMULATION */ |
908 | 916 | ||
909 | dotraplinkage void __kprobes | 917 | dotraplinkage void __kprobes do_device_not_available(struct pt_regs regs) |
910 | do_device_not_available(struct pt_regs *regs, long error) | ||
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) { |
914 | conditional_sti(regs); | 921 | struct math_emu_info info = { }; |
915 | math_emulate(0); | 922 | |
923 | conditional_sti(®s); | ||
924 | |||
925 | info.regs = ®s; | ||
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(®s); |
919 | } | 930 | } |
920 | #else | 931 | #else |
921 | math_state_restore(); | 932 | math_state_restore(); |