]> err.no Git - linux-2.6/blobdiff - arch/x86_64/kernel/entry.S
[PATCH] x86_64: Always ack IPIs even on errors
[linux-2.6] / arch / x86_64 / kernel / entry.S
index 12a307100929a7dd5225c5ff53ff1c427aff6bc1..28817490fdc69510a527c9974be8bb550aa2a5b6 100644 (file)
 
        .code64
 
-#ifdef CONFIG_PREEMPT
-#define preempt_stop cli
-#else
-#define preempt_stop
+#ifndef CONFIG_PREEMPT
 #define retint_kernel retint_restore_args
 #endif 
        
@@ -223,13 +220,18 @@ sysret_careful:
        jmp sysret_check
 
        /* Handle a signal */ 
-       /* edx: work flags (arg3) */
 sysret_signal:
        sti
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    1f
+
+       /* Really a signal */
+       /* edx: work flags (arg3) */
        leaq do_notify_resume(%rip),%rax
        leaq -ARGOFFSET(%rsp),%rdi # &pt_regs -> arg1
        xorl %esi,%esi # oldset -> arg2
        call ptregscall_common
+1:     movl $_TIF_NEED_RESCHED,%edi
        jmp sysret_check
        
        /* Do syscall tracing */
@@ -284,6 +286,7 @@ int_careful:
        pushq %rdi
        call schedule
        popq %rdi
+       cli
        jmp int_with_check
 
        /* handle signals and tracing -- both require a full stack frame */
@@ -298,6 +301,7 @@ int_very_careful:
        call syscall_trace_leave
        popq %rdi
        andl $~(_TIF_SYSCALL_TRACE|_TIF_SYSCALL_AUDIT|_TIF_SINGLESTEP),%edi
+       cli
        jmp int_restore_rest
        
 int_signal:
@@ -309,6 +313,7 @@ int_signal:
 1:     movl $_TIF_NEED_RESCHED,%edi    
 int_restore_rest:
        RESTORE_REST
+       cli
        jmp int_with_check
        CFI_ENDPROC
                
@@ -453,7 +458,6 @@ retint_check:
        andl %edi,%edx
        jnz  retint_careful
 retint_swapgs:         
-       cli
        swapgs 
 retint_restore_args:                           
        cli
@@ -485,6 +489,8 @@ retint_careful:
        jmp retint_check
        
 retint_signal:
+       testl $(_TIF_SIGPENDING|_TIF_NOTIFY_RESUME|_TIF_SINGLESTEP),%edx
+       jz    retint_swapgs
        sti
        SAVE_REST
        movq $-1,ORIG_RAX(%rsp)                         
@@ -493,7 +499,8 @@ retint_signal:
        call do_notify_resume
        RESTORE_REST
        cli
-       GET_THREAD_INFO(%rcx)   
+       movl $_TIF_NEED_RESCHED,%edi
+       GET_THREAD_INFO(%rcx)
        jmp retint_check
 
 #ifdef CONFIG_PREEMPT
@@ -579,6 +586,7 @@ ENTRY(spurious_interrupt)
        movq ORIG_RAX(%rsp),%rsi
        movq $-1,ORIG_RAX(%rsp)
        call \sym
+       cli
        .endm
        
 /*
@@ -794,10 +802,6 @@ ENTRY(debug)
        pushq $0
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_debug
-       /* switch back to process stack to restore the state ptrace touched */
-       movq %rax,%rsp  
-       testl $3,CS(%rsp)
-       jnz   paranoid_userspace        
        jmp paranoid_exit
        CFI_ENDPROC
 
@@ -807,35 +811,49 @@ ENTRY(nmi)
        pushq $-1
        CFI_ADJUST_CFA_OFFSET 8         
        paranoidentry do_nmi
+       /*
+        * "Paranoid" exit path from exception stack.
+        * Paranoid because this is used by NMIs and cannot take
+        * any kernel state for granted.
+        * We don't do kernel preemption checks here, because only
+        * NMI should be common and it does not enable IRQs and
+        * cannot get reschedule ticks.
+        */
        /* ebx: no swapgs flag */
 paranoid_exit:
        testl %ebx,%ebx                         /* swapgs needed? */
        jnz paranoid_restore
+       testl $3,CS(%rsp)
+       jnz   paranoid_userspace
 paranoid_swapgs:       
-       cli
        swapgs
 paranoid_restore:      
        RESTORE_ALL 8
        iretq
 paranoid_userspace:    
-       cli
        GET_THREAD_INFO(%rcx)
-       movl threadinfo_flags(%rcx),%edx
-       testl $_TIF_WORK_MASK,%edx
+       movl threadinfo_flags(%rcx),%ebx
+       andl $_TIF_WORK_MASK,%ebx
        jz paranoid_swapgs
-       testl $_TIF_NEED_RESCHED,%edx
-       jnz paranoid_resched
+       movq %rsp,%rdi                  /* &pt_regs */
+       call sync_regs
+       movq %rax,%rsp                  /* switch stack for scheduling */
+       testl $_TIF_NEED_RESCHED,%ebx
+       jnz paranoid_schedule
+       movl %ebx,%edx                  /* arg3: thread flags */
        sti
-       xorl %esi,%esi /* oldset */
-       movq %rsp,%rdi /* &pt_regs */
+       xorl %esi,%esi                  /* arg2: oldset */
+       movq %rsp,%rdi                  /* arg1: &pt_regs */
        call do_notify_resume
-       jmp paranoid_exit
-paranoid_resched:
+       cli
+       jmp paranoid_userspace
+paranoid_schedule:
        sti
        call schedule
-       jmp paranoid_exit
+       cli
+       jmp paranoid_userspace
        CFI_ENDPROC
-       
+
 ENTRY(int3)
        zeroentry do_int3       
 
@@ -858,9 +876,6 @@ ENTRY(reserved)
 ENTRY(double_fault)
        CFI_STARTPROC
        paranoidentry do_double_fault
-       movq %rax,%rsp
-       testl $3,CS(%rsp)
-       jnz paranoid_userspace          
        jmp paranoid_exit
        CFI_ENDPROC
 
@@ -874,9 +889,6 @@ ENTRY(segment_not_present)
 ENTRY(stack_segment)
        CFI_STARTPROC
        paranoidentry do_stack_segment
-       movq %rax,%rsp
-       testl $3,CS(%rsp)
-       jnz paranoid_userspace
        jmp paranoid_exit
        CFI_ENDPROC