]> err.no Git - linux-2.6/commitdiff
x86: only enable interrupts when kernel state has been set up
authorJeremy Fitzhardinge <jeremy@goop.org>
Mon, 24 Mar 2008 23:43:21 +0000 (16:43 -0700)
committerIngo Molnar <mingo@elte.hu>
Thu, 17 Apr 2008 15:41:29 +0000 (17:41 +0200)
The sysenter path tries to enable interrupts immediately.  Unfortunately
this doesn't work in a paravirt environment, because not enough kernel
state has been set up at that point (namely, pointing %fs to the kernel
percpu data segment).  To fix this, defer ENABLE_INTERRUPTS until after
the kernel state has been set up.

Unfortunately this means that we're running with interrupts disabled
for a while without calling the IRQ tracing code, but that can't be
called without setting up %fs either.

Signed-off-by: Jeremy Fitzhardinge <jeremy.fitzhardinge@citrix.com>
Signed-off-by: Ingo Molnar <mingo@elte.hu>
arch/x86/kernel/entry_32.S

index 4b87c32b639f50b08d92021027b40de1307871fb..a664d5726d8de675037c379eaa87fc88b79496d3 100644 (file)
@@ -291,10 +291,10 @@ ENTRY(ia32_sysenter_target)
        movl TSS_sysenter_sp0(%esp),%esp
 sysenter_past_esp:
        /*
-        * No need to follow this irqs on/off section: the syscall
-        * disabled irqs and here we enable it straight after entry:
+        * Interrupts are disabled here, but we can't trace it until
+        * enough kernel state to call TRACE_IRQS_OFF can be called - but
+        * we immediately enable interrupts at that point anyway.
         */
-       ENABLE_INTERRUPTS(CLBR_NONE)
        pushl $(__USER_DS)
        CFI_ADJUST_CFA_OFFSET 4
        /*CFI_REL_OFFSET ss, 0*/
@@ -302,6 +302,7 @@ sysenter_past_esp:
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET esp, 0
        pushfl
+       orl $X86_EFLAGS_IF, (%esp)
        CFI_ADJUST_CFA_OFFSET 4
        pushl $(__USER_CS)
        CFI_ADJUST_CFA_OFFSET 4
@@ -315,6 +316,11 @@ sysenter_past_esp:
        CFI_ADJUST_CFA_OFFSET 4
        CFI_REL_OFFSET eip, 0
 
+       pushl %eax
+       CFI_ADJUST_CFA_OFFSET 4
+       SAVE_ALL
+       ENABLE_INTERRUPTS(CLBR_NONE)
+
 /*
  * Load the potential sixth argument from user stack.
  * Careful about security.
@@ -322,14 +328,12 @@ sysenter_past_esp:
        cmpl $__PAGE_OFFSET-3,%ebp
        jae syscall_fault
 1:     movl (%ebp),%ebp
+       movl %ebp,PT_EBP(%esp)
 .section __ex_table,"a"
        .align 4
        .long 1b,syscall_fault
 .previous
 
-       pushl %eax
-       CFI_ADJUST_CFA_OFFSET 4
-       SAVE_ALL
        GET_THREAD_INFO(%ebp)
 
        /* Note, _TIF_SECCOMP is bit number 8, and so it needs testw and not testb */
@@ -543,9 +547,6 @@ END(syscall_exit_work)
 
        RING0_INT_FRAME                 # can't unwind into user space anyway
 syscall_fault:
-       pushl %eax                      # save orig_eax
-       CFI_ADJUST_CFA_OFFSET 4
-       SAVE_ALL
        GET_THREAD_INFO(%ebp)
        movl $-EFAULT,PT_EAX(%esp)
        jmp resume_userspace