From: Lai Jiangshan <la...@linux.alibaba.com>

Directly copy pt_regs to kernel stack when .Lerror_bad_iret.
Directly switch to kernel stack when .Lerror_bad_iret.

We can see that entry_64.S do the following things back to back
when .Lerror_bad_iret:
  call fixup_bad_iret(), switch to sp0 stack with pt_regs copied
  call sync_regs(), switch to kernel stack with pt_regs copied

So we can do the all things together in fixup_bad_iret().

After this patch, fixup_bad_iret() is restored to the behavior before
7f2590a110b8("x86/entry/64: Use a per-CPU trampoline stack for IDT entries")

Signed-off-by: Lai Jiangshan <la...@linux.alibaba.com>
---
 arch/x86/entry/entry_64.S | 13 ++-----------
 arch/x86/kernel/traps.c   |  9 ++++-----
 2 files changed, 6 insertions(+), 16 deletions(-)

diff --git a/arch/x86/entry/entry_64.S b/arch/x86/entry/entry_64.S
index 1a7715430da3..911cfa0da637 100644
--- a/arch/x86/entry/entry_64.S
+++ b/arch/x86/entry/entry_64.S
@@ -965,16 +965,6 @@ SYM_CODE_START_LOCAL(error_entry)
        ENCODE_FRAME_POINTER 8
        ret
 
-.Lerror_entry_from_usermode_after_swapgs:
-       /* Put us onto the real thread stack. */
-       popq    %r12                            /* save return addr in %12 */
-       movq    %rsp, %rdi                      /* arg0 = pt_regs pointer */
-       call    sync_regs
-       movq    %rax, %rsp                      /* switch stack */
-       ENCODE_FRAME_POINTER
-       pushq   %r12
-       ret
-
 .Lerror_entry_done_lfence:
        FENCE_SWAPGS_KERNEL_ENTRY
 .Lerror_entry_done:
@@ -1028,7 +1018,8 @@ SYM_CODE_START_LOCAL(error_entry)
        mov     %rsp, %rdi
        call    fixup_bad_iret
        mov     %rax, %rsp
-       jmp     .Lerror_entry_from_usermode_after_swapgs
+       ENCODE_FRAME_POINTER 8
+       ret
 SYM_CODE_END(error_entry)
 
 SYM_CODE_START_LOCAL(error_return)
diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 1f66d2d1e998..852de6f1bf88 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -684,13 +684,12 @@ struct bad_iret_stack *fixup_bad_iret(struct 
bad_iret_stack *s)
        /*
         * This is called from entry_64.S early in handling a fault
         * caused by a bad iret to user mode.  To handle the fault
-        * correctly, we want to move our stack frame to where it would
-        * be had we entered directly on the entry stack (rather than
-        * just below the IRET frame) and we want to pretend that the
-        * exception came from the IRET target.
+        * correctly, we want to move our stack frame to kernel stack
+        * (rather than just below the IRET frame) and we want to
+        * pretend that the exception came from the IRET target.
         */
        struct bad_iret_stack tmp, *new_stack =
-               (struct bad_iret_stack 
*)__this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1;
+               (struct bad_iret_stack 
*)__this_cpu_read(cpu_current_top_of_stack) - 1;
 
        /* Copy the IRET target to the temporary storage. */
        __memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8);
-- 
2.19.1.6.gb485710b

Reply via email to