Commit 01d259fe authored by Andi Kleen's avatar Andi Kleen Committed by Linus Torvalds

[PATCH] Enable interrupts in faults from VM86 mode

vm86 mode does a copy_to_user from the general protection fault handler
to update the process' vm86 state.

The problem is that the full GFP handler runs with interrupts off
currently and that trips the might_sleep() test in copy_to_user().

This happens very often in dosemu and once in a while while the X server
does its vm86 magic with the VGA bios. 

See

	http://bugzilla.kernel.org/show_bug.cgi?id=1339

for details

This patch fixes this by enabling interrupts when the original code ran
with interrupts on or ran in vm86 mode (vm86 can clear the IF flag)
parent 535a8a4c
...@@ -374,6 +374,9 @@ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr ...@@ -374,6 +374,9 @@ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, get_cr
asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
{ {
if (regs->eflags & X86_EFLAGS_IF)
local_irq_enable();
if (regs->eflags & VM_MASK) if (regs->eflags & VM_MASK)
goto gp_in_vm86; goto gp_in_vm86;
...@@ -386,6 +389,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code) ...@@ -386,6 +389,7 @@ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
return; return;
gp_in_vm86: gp_in_vm86:
local_irq_enable();
handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code); handle_vm86_fault((struct kernel_vm86_regs *) regs, error_code);
return; return;
......
...@@ -223,7 +223,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code) ...@@ -223,7 +223,7 @@ asmlinkage void do_page_fault(struct pt_regs *regs, unsigned long error_code)
__asm__("movl %%cr2,%0":"=r" (address)); __asm__("movl %%cr2,%0":"=r" (address));
/* It's safe to allow irq's after cr2 has been saved */ /* It's safe to allow irq's after cr2 has been saved */
if (regs->eflags & X86_EFLAGS_IF) if (regs->eflags & (X86_EFLAGS_IF|VM_MASK))
local_irq_enable(); local_irq_enable();
tsk = current; tsk = current;
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment