x86/asm/entry: Clear EXTRA_REGS for all executable formats
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / entry_64.S
index 9f8d01f1f1b2fae67ff9e14d118052e46a1bd169..f4270ff73f2ab748e0c3dfd14c5f8d76dd830ca2 100644 (file)
@@ -331,10 +331,11 @@ tracesys_phase2:
        andl $__SYSCALL_MASK,%eax
        cmpl $__NR_syscall_max,%eax
 #endif
-       ja   int_ret_from_sys_call      /* RAX(%rsp) is already set */
+       ja      1f      /* return -ENOSYS (already in pt_regs->ax) */
        movq %r10,%rcx  /* fixup for C */
        call *sys_call_table(,%rax,8)
        movq %rax,RAX(%rsp)
+1:
        /* Use IRET because user could have changed pt_regs->foo */
 
 /*
@@ -418,25 +419,27 @@ END(stub_\func)
 
 ENTRY(stub_execve)
        CFI_STARTPROC
-       addq $8, %rsp
-       DEFAULT_FRAME 0
-       SAVE_EXTRA_REGS
-       call sys_execve
-       movq %rax,RAX(%rsp)
-       RESTORE_EXTRA_REGS
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    sys_execve
+return_from_execve:
+       testl   %eax, %eax
+       jz      1f
+       /* exec failed, can use fast SYSRET code path in this case */
+       ret
+1:
+       /* must use IRET code path (pt_regs->cs may have changed) */
+       addq    $8, %rsp
+       ZERO_EXTRA_REGS
+       movq    %rax,RAX(%rsp)
+       jmp     int_ret_from_sys_call
        CFI_ENDPROC
 END(stub_execve)
 
 ENTRY(stub_execveat)
        CFI_STARTPROC
-       addq $8, %rsp
-       DEFAULT_FRAME 0
-       SAVE_EXTRA_REGS
-       call sys_execveat
-       movq %rax,RAX(%rsp)
-       RESTORE_EXTRA_REGS
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    sys_execveat
+       jmp     return_from_execve
        CFI_ENDPROC
 END(stub_execveat)
 
@@ -471,25 +474,17 @@ END(stub_x32_rt_sigreturn)
 
 ENTRY(stub_x32_execve)
        CFI_STARTPROC
-       addq $8, %rsp
-       DEFAULT_FRAME 0
-       SAVE_EXTRA_REGS
-       call compat_sys_execve
-       movq %rax,RAX(%rsp)
-       RESTORE_EXTRA_REGS
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    compat_sys_execve
+       jmp     return_from_execve
        CFI_ENDPROC
 END(stub_x32_execve)
 
 ENTRY(stub_x32_execveat)
        CFI_STARTPROC
-       addq $8, %rsp
-       DEFAULT_FRAME 0
-       SAVE_EXTRA_REGS
-       call compat_sys_execveat
-       movq %rax,RAX(%rsp)
-       RESTORE_EXTRA_REGS
-       jmp int_ret_from_sys_call
+       DEFAULT_FRAME 0, 8
+       call    compat_sys_execveat
+       jmp     return_from_execve
        CFI_ENDPROC
 END(stub_x32_execveat)
 
@@ -654,7 +649,6 @@ ret_from_intr:
        CFI_DEF_CFA_REGISTER    rsp
        CFI_ADJUST_CFA_OFFSET   RBP
 
-exit_intr:
        testl $3,CS(%rsp)
        je retint_kernel
        /* Interrupt came from user space */
@@ -741,12 +735,12 @@ retint_kernel:
 #ifdef CONFIG_PREEMPT
        /* Interrupts are off */
        /* Check if we need preemption */
-       cmpl    $0,PER_CPU_VAR(__preempt_count)
-       jnz     1f
        bt      $9,EFLAGS(%rsp) /* interrupts were off? */
        jnc     1f
+0:     cmpl    $0,PER_CPU_VAR(__preempt_count)
+       jnz     1f
        call    preempt_schedule_irq
-       jmp     exit_intr
+       jmp     0b
 1:
 #endif
        /*
@@ -1355,19 +1349,7 @@ ENTRY(error_exit)
        CFI_ENDPROC
 END(error_exit)
 
-/*
- * Test if a given stack is an NMI stack or not.
- */
-       .macro test_in_nmi reg stack nmi_ret normal_ret
-       cmpq %\reg, \stack
-       ja \normal_ret
-       subq $EXCEPTION_STKSZ, %\reg
-       cmpq %\reg, \stack
-       jb \normal_ret
-       jmp \nmi_ret
-       .endm
-
-       /* runs on exception stack */
+/* Runs on exception stack */
 ENTRY(nmi)
        INTR_FRAME
        PARAVIRT_ADJUST_EXCEPTION_FRAME
@@ -1428,8 +1410,18 @@ ENTRY(nmi)
         * We check the variable because the first NMI could be in a
         * breakpoint routine using a breakpoint stack.
         */
-       lea 6*8(%rsp), %rdx
-       test_in_nmi rdx, 4*8(%rsp), nested_nmi, first_nmi
+       lea     6*8(%rsp), %rdx
+       /* Compare the NMI stack (rdx) with the stack we came from (4*8(%rsp)) */
+       cmpq    %rdx, 4*8(%rsp)
+       /* If the stack pointer is above the NMI stack, this is a normal NMI */
+       ja      first_nmi
+       subq    $EXCEPTION_STKSZ, %rdx
+       cmpq    %rdx, 4*8(%rsp)
+       /* If it is below the NMI stack, it is a normal NMI */
+       jb      first_nmi
+       /* Ah, it is within the NMI stack, treat it as nested */
+       jmp     nested_nmi
+
        CFI_REMEMBER_STATE
 
 nested_nmi: