x86/asm/entry/64: Remove 'int_check_syscall_exit_work'
[firefly-linux-kernel-4.4.55.git] / arch / x86 / kernel / entry_64.S
index e8372e08f8c2512a0b21a51d2b9c6e4ffda63f41..b0fbde1876e131598a0837176da45f36f2a56b65 100644 (file)
@@ -14,9 +14,6 @@
  * NOTE: This code handles signal-recognition, which happens every time
  * after an interrupt and after each system call.
  *
- * Normal syscalls and interrupts don't save a full stack frame, this is
- * only done for syscall tracing, signals or fork/exec et.al.
- *
  * A note on terminology:
  * - top of stack: Architecture defined interrupt frame from SS to RIP
  * at the top of the kernel process stack.
@@ -76,9 +73,9 @@ ENDPROC(native_usergs_sysret64)
 #endif /* CONFIG_PARAVIRT */
 
 
-.macro TRACE_IRQS_IRETQ offset=ARGOFFSET
+.macro TRACE_IRQS_IRETQ
 #ifdef CONFIG_TRACE_IRQFLAGS
-       bt   $9,EFLAGS-\offset(%rsp)    /* interrupts off? */
+       bt   $9,EFLAGS(%rsp)    /* interrupts off? */
        jnc  1f
        TRACE_IRQS_ON
 1:
@@ -110,8 +107,8 @@ ENDPROC(native_usergs_sysret64)
        call debug_stack_reset
 .endm
 
-.macro TRACE_IRQS_IRETQ_DEBUG offset=ARGOFFSET
-       bt   $9,EFLAGS-\offset(%rsp)    /* interrupts off? */
+.macro TRACE_IRQS_IRETQ_DEBUG
+       bt   $9,EFLAGS(%rsp)    /* interrupts off? */
        jnc  1f
        TRACE_IRQS_ON_DEBUG
 1:
@@ -151,7 +148,7 @@ ENDPROC(native_usergs_sysret64)
        .endm
 
 /*
- * initial frame state for interrupts (and exceptions without error code)
+ * empty frame
  */
        .macro EMPTY_FRAME start=1 offset=0
        .if \start
@@ -187,16 +184,16 @@ ENDPROC(native_usergs_sysret64)
  * frame that enables passing a complete pt_regs to a C function.
  */
        .macro DEFAULT_FRAME start=1 offset=0
-       XCPT_FRAME \start, ORIG_RAX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rdi, RDI+\offset-ARGOFFSET
-       CFI_REL_OFFSET rsi, RSI+\offset-ARGOFFSET
-       CFI_REL_OFFSET rdx, RDX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rcx, RCX+\offset-ARGOFFSET
-       CFI_REL_OFFSET rax, RAX+\offset-ARGOFFSET
-       CFI_REL_OFFSET r8, R8+\offset-ARGOFFSET
-       CFI_REL_OFFSET r9, R9+\offset-ARGOFFSET
-       CFI_REL_OFFSET r10, R10+\offset-ARGOFFSET
-       CFI_REL_OFFSET r11, R11+\offset-ARGOFFSET
+       XCPT_FRAME \start, ORIG_RAX+\offset
+       CFI_REL_OFFSET rdi, RDI+\offset
+       CFI_REL_OFFSET rsi, RSI+\offset
+       CFI_REL_OFFSET rdx, RDX+\offset
+       CFI_REL_OFFSET rcx, RCX+\offset
+       CFI_REL_OFFSET rax, RAX+\offset
+       CFI_REL_OFFSET r8, R8+\offset
+       CFI_REL_OFFSET r9, R9+\offset
+       CFI_REL_OFFSET r10, R10+\offset
+       CFI_REL_OFFSET r11, R11+\offset
        CFI_REL_OFFSET rbx, RBX+\offset
        CFI_REL_OFFSET rbp, RBP+\offset
        CFI_REL_OFFSET r12, R12+\offset
@@ -240,13 +237,13 @@ ENTRY(ret_from_fork)
 
        RESTORE_EXTRA_REGS
 
-       testl $3, CS-ARGOFFSET(%rsp)            # from kernel_thread?
+       testl $3,CS(%rsp)                       # from kernel_thread?
        jz   1f
 
        testl $_TIF_IA32, TI_flags(%rcx)        # 32-bit compat task needs IRET
        jnz  int_ret_from_sys_call
 
-       RESTORE_TOP_OF_STACK %rdi, -ARGOFFSET
+       RESTORE_TOP_OF_STACK %rdi
        jmp ret_from_sys_call                   # go to the SYSRET fastpath
 
 1:
@@ -313,11 +310,11 @@ GLOBAL(system_call_after_swapgs)
        ENABLE_INTERRUPTS(CLBR_NONE)
        ALLOC_PT_GPREGS_ON_STACK 8
        SAVE_C_REGS_EXCEPT_RAX_RCX
-       movq    $-ENOSYS,RAX-ARGOFFSET(%rsp)
-       movq_cfi rax,(ORIG_RAX-ARGOFFSET)
-       movq    %rcx,RIP-ARGOFFSET(%rsp)
-       CFI_REL_OFFSET rip,RIP-ARGOFFSET
-       testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       movq    $-ENOSYS,RAX(%rsp)
+       movq_cfi rax,ORIG_RAX
+       movq    %rcx,RIP(%rsp)
+       CFI_REL_OFFSET rip,RIP
+       testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP)
        jnz tracesys
 system_call_fastpath:
 #if __SYSCALL_MASK == ~0
@@ -329,13 +326,13 @@ system_call_fastpath:
        ja ret_from_sys_call  /* and return regs->ax */
        movq %r10,%rcx
        call *sys_call_table(,%rax,8)  # XXX:    rip relative
-       movq %rax,RAX-ARGOFFSET(%rsp)
+       movq %rax,RAX(%rsp)
 /*
  * Syscall return path ending with SYSRET (fast path)
  * Has incomplete stack frame and undefined top of stack.
  */
 ret_from_sys_call:
-       testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP-ARGOFFSET)
+       testl $_TIF_ALLWORK_MASK,TI_flags+THREAD_INFO(%rsp,RIP)
        jnz int_ret_from_sys_call_fixup /* Go the the slow path */
 
        LOCKDEP_SYS_EXIT
@@ -347,7 +344,7 @@ ret_from_sys_call:
         */
        TRACE_IRQS_ON
        RESTORE_C_REGS_EXCEPT_RCX
-       movq RIP-ARGOFFSET(%rsp),%rcx
+       movq RIP(%rsp),%rcx
        CFI_REGISTER    rip,rcx
        /*CFI_REGISTER  rflags,r11*/
        movq    PER_CPU_VAR(old_rsp), %rsp
@@ -356,7 +353,7 @@ ret_from_sys_call:
        CFI_RESTORE_STATE
 
 int_ret_from_sys_call_fixup:
-       FIXUP_TOP_OF_STACK %r11, -ARGOFFSET
+       FIXUP_TOP_OF_STACK %r11
        jmp int_ret_from_sys_call
 
        /* Do syscall tracing */
@@ -367,7 +364,7 @@ tracesys:
        test %rax, %rax
        jnz tracesys_phase2             /* if needed, run the slow path */
        RESTORE_C_REGS_EXCEPT_RAX       /* else restore clobbered regs */
-       movq ORIG_RAX-ARGOFFSET(%rsp), %rax
+       movq ORIG_RAX(%rsp), %rax
        jmp system_call_fastpath        /*      and return to the fast path */
 
 tracesys_phase2:
@@ -379,7 +376,7 @@ tracesys_phase2:
        call syscall_trace_enter_phase2
 
        /*
-        * Reload arg registers from stack in case ptrace changed them.
+        * Reload registers from stack in case ptrace changed them.
         * We don't reload %rax because syscall_trace_entry_phase2() returned
         * the value it wants us to use in the table lookup.
         */
@@ -394,7 +391,7 @@ tracesys_phase2:
        ja   int_ret_from_sys_call      /* RAX(%rsp) is already set */
        movq %r10,%rcx  /* fixup for C */
        call *sys_call_table(,%rax,8)
-       movq %rax,RAX-ARGOFFSET(%rsp)
+       movq %rax,RAX(%rsp)
        /* Use IRET because user could have changed frame */
 
 /*
@@ -434,7 +431,6 @@ int_careful:
 int_very_careful:
        TRACE_IRQS_ON
        ENABLE_INTERRUPTS(CLBR_NONE)
-int_check_syscall_exit_work:
        SAVE_EXTRA_REGS
        /* Check for syscall exit trace */
        testl $_TIF_WORK_SYSCALL_EXIT,%edx
@@ -478,9 +474,9 @@ END(stub_\func)
 ENTRY(\label)
        CFI_STARTPROC
        DEFAULT_FRAME 0, 8              /* offset 8: return address */
-       FIXUP_TOP_OF_STACK %r11, 8-ARGOFFSET
+       FIXUP_TOP_OF_STACK %r11, 8
        call \func
-       RESTORE_TOP_OF_STACK %r11, 8-ARGOFFSET
+       RESTORE_TOP_OF_STACK %r11, 8
        ret
        CFI_ENDPROC
 END(\label)
@@ -629,6 +625,13 @@ END(interrupt)
 /* 0(%rsp): ~(interrupt number) */
        .macro interrupt func
        cld
+       /*
+        * Since nothing in interrupt handling code touches r12...r15 members
+        * of "struct pt_regs", and since interrupts can nest, we can save
+        * four stack slots and simultaneously provide
+        * an unwind-friendly stack layout by saving "truncated" pt_regs
+        * exactly up to rbp slot, without these members.
+        */
        ALLOC_PT_GPREGS_ON_STACK -RBP
        SAVE_C_REGS -RBP
        /* this goes to 0(%rsp) for unwinder, not for saving the value: */
@@ -641,6 +644,7 @@ END(interrupt)
        SWAPGS
 1:
        /*
+        * Save previous stack pointer, optionally switch to interrupt stack.
         * irq_count is used to check if a CPU is already on an interrupt stack
         * or not. While this is essentially redundant with preempt_count it is
         * a little cheaper to use a separate counter in the PDA (short of
@@ -672,7 +676,7 @@ common_interrupt:
        ASM_CLAC
        addq $-0x80,(%rsp)              /* Adjust vector to [-256,-1] range */
        interrupt do_IRQ
-       /* 0(%rsp): old_rsp-ARGOFFSET */
+       /* 0(%rsp): old_rsp */
 ret_from_intr:
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF
@@ -681,18 +685,19 @@ ret_from_intr:
        /* Restore saved previous stack */
        popq %rsi
        CFI_DEF_CFA rsi,SS+8-RBP        /* reg/off reset after def_cfa_expr */
-       leaq ARGOFFSET-RBP(%rsi), %rsp
+       /* return code expects complete pt_regs - adjust rsp accordingly: */
+       leaq -RBP(%rsi),%rsp
        CFI_DEF_CFA_REGISTER    rsp
-       CFI_ADJUST_CFA_OFFSET   RBP-ARGOFFSET
+       CFI_ADJUST_CFA_OFFSET   RBP
 
 exit_intr:
        GET_THREAD_INFO(%rcx)
-       testl $3,CS-ARGOFFSET(%rsp)
+       testl $3,CS(%rsp)
        je retint_kernel
 
        /* Interrupt came from user space */
        /*
-        * Has a correct top of stack, but a partial stack frame
+        * Has a correct top of stack.
         * %rcx: thread info. Interrupts off.
         */
 retint_with_reschedule:
@@ -715,8 +720,8 @@ retint_swapgs:              /* return to user-space */
         * Try to use SYSRET instead of IRET if we're returning to
         * a completely clean 64-bit userspace context.
         */
-       movq (RCX-ARGOFFSET)(%rsp), %rcx
-       cmpq %rcx,(RIP-ARGOFFSET)(%rsp)         /* RCX == RIP */
+       movq RCX(%rsp),%rcx
+       cmpq %rcx,RIP(%rsp)             /* RCX == RIP */
        jne opportunistic_sysret_failed
 
        /*
@@ -737,19 +742,19 @@ retint_swapgs:            /* return to user-space */
        shr $__VIRTUAL_MASK_SHIFT, %rcx
        jnz opportunistic_sysret_failed
 
-       cmpq $__USER_CS,(CS-ARGOFFSET)(%rsp)    /* CS must match SYSRET */
+       cmpq $__USER_CS,CS(%rsp)        /* CS must match SYSRET */
        jne opportunistic_sysret_failed
 
-       movq (R11-ARGOFFSET)(%rsp), %r11
-       cmpq %r11,(EFLAGS-ARGOFFSET)(%rsp)      /* R11 == RFLAGS */
+       movq R11(%rsp),%r11
+       cmpq %r11,EFLAGS(%rsp)          /* R11 == RFLAGS */
        jne opportunistic_sysret_failed
 
-       testq $X86_EFLAGS_RF,%r11               /* sysret can't restore RF */
+       testq $X86_EFLAGS_RF,%r11       /* sysret can't restore RF */
        jnz opportunistic_sysret_failed
 
        /* nothing to check for RSP */
 
-       cmpq $__USER_DS,(SS-ARGOFFSET)(%rsp)    /* SS must match SYSRET */
+       cmpq $__USER_DS,SS(%rsp)        /* SS must match SYSRET */
        jne opportunistic_sysret_failed
 
        /*
@@ -864,7 +869,7 @@ retint_signal:
 ENTRY(retint_kernel)
        cmpl $0,PER_CPU_VAR(__preempt_count)
        jnz  retint_restore_args
-       bt   $9,EFLAGS-ARGOFFSET(%rsp)  /* interrupts off? */
+       bt   $9,EFLAGS(%rsp)    /* interrupts off? */
        jnc  retint_restore_args
        call preempt_schedule_irq
        jmp exit_intr
@@ -1279,15 +1284,13 @@ ENTRY(paranoid_exit)
        DISABLE_INTERRUPTS(CLBR_NONE)
        TRACE_IRQS_OFF_DEBUG
        testl %ebx,%ebx                         /* swapgs needed? */
-       jnz paranoid_restore
-       TRACE_IRQS_IRETQ 0
+       jnz paranoid_exit_no_swapgs
+       TRACE_IRQS_IRETQ
        SWAPGS_UNSAFE_STACK
-       RESTORE_EXTRA_REGS
-       RESTORE_C_REGS
-       REMOVE_PT_GPREGS_FROM_STACK 8
-       INTERRUPT_RETURN
-paranoid_restore:
-       TRACE_IRQS_IRETQ_DEBUG 0
+       jmp paranoid_exit_restore
+paranoid_exit_no_swapgs:
+       TRACE_IRQS_IRETQ_DEBUG
+paranoid_exit_restore:
        RESTORE_EXTRA_REGS
        RESTORE_C_REGS
        REMOVE_PT_GPREGS_FROM_STACK 8