diff options
author | Tejun Heo <tj@kernel.org> | 2009-02-09 08:17:39 -0500 |
---|---|---|
committer | Ingo Molnar <mingo@elte.hu> | 2009-02-09 18:39:14 -0500 |
commit | d315760ffa261c15ff92699ac6f514112543d7ca (patch) | |
tree | 3f7d185cf97a06e6686521a23a1c78d1809a51c4 /arch/x86/kernel/traps.c | |
parent | ae6af41f5a4841f06eb92bc86ad020ad44ae2a30 (diff) |
x86: fix math_emu register frame access
do_device_not_available() is the handler for #NM and it declares that
it takes a unsigned long and calls math_emu(), which takes a long
argument and surprisingly expects the stack frame starting at the zero
argument would match struct math_emu_info, which isn't true regardless
of configuration in the current code.
This patch makes do_device_not_available() take struct pt_regs like
other exception handlers and initialize struct math_emu_info with
pointer to it and pass pointer to the math_emu_info to math_emulate()
like normal C functions do. This way, unless gcc makes a copy of
struct pt_regs in do_device_not_available(), the register frame is
correctly accessed regardless of kernel configuration or compiler
used.
This doesn't fix all math_emu problems but it at least gets it
somewhat working.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
Diffstat (limited to 'arch/x86/kernel/traps.c')
-rw-r--r-- | arch/x86/kernel/traps.c | 15 |
1 files changed, 9 insertions, 6 deletions
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 98c2d055284b..7932338d7cb3 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c | |||
@@ -896,7 +896,7 @@ asmlinkage void math_state_restore(void) | |||
896 | EXPORT_SYMBOL_GPL(math_state_restore); | 896 | EXPORT_SYMBOL_GPL(math_state_restore); |
897 | 897 | ||
898 | #ifndef CONFIG_MATH_EMULATION | 898 | #ifndef CONFIG_MATH_EMULATION |
899 | asmlinkage void math_emulate(long arg) | 899 | void math_emulate(struct math_emu_info *info) |
900 | { | 900 | { |
901 | printk(KERN_EMERG | 901 | printk(KERN_EMERG |
902 | "math-emulation not enabled and no coprocessor found.\n"); | 902 | "math-emulation not enabled and no coprocessor found.\n"); |
@@ -906,16 +906,19 @@ asmlinkage void math_emulate(long arg) | |||
906 | } | 906 | } |
907 | #endif /* CONFIG_MATH_EMULATION */ | 907 | #endif /* CONFIG_MATH_EMULATION */ |
908 | 908 | ||
909 | dotraplinkage void __kprobes | 909 | dotraplinkage void __kprobes do_device_not_available(struct pt_regs regs) |
910 | do_device_not_available(struct pt_regs *regs, long error) | ||
911 | { | 910 | { |
912 | #ifdef CONFIG_X86_32 | 911 | #ifdef CONFIG_X86_32 |
913 | if (read_cr0() & X86_CR0_EM) { | 912 | if (read_cr0() & X86_CR0_EM) { |
914 | conditional_sti(regs); | 913 | struct math_emu_info info = { }; |
915 | math_emulate(0); | 914 | |
915 | conditional_sti(®s); | ||
916 | |||
917 | info.regs = ®s; | ||
918 | math_emulate(&info); | ||
916 | } else { | 919 | } else { |
917 | math_state_restore(); /* interrupts still off */ | 920 | math_state_restore(); /* interrupts still off */ |
918 | conditional_sti(regs); | 921 | conditional_sti(®s); |
919 | } | 922 | } |
920 | #else | 923 | #else |
921 | math_state_restore(); | 924 | math_state_restore(); |