The following commit has been merged into the x86/urgent branch of tip:

Commit-ID:     d1721250f3ffed9afba3e1fb729947cec64c5a8a
Gitweb:        
https://git.kernel.org/tip/d1721250f3ffed9afba3e1fb729947cec64c5a8a
Author:        Andy Lutomirski <[email protected]>
AuthorDate:    Fri, 26 Jun 2020 10:21:12 -07:00
Committer:     Thomas Gleixner <[email protected]>
CommitterDate: Wed, 01 Jul 2020 10:00:25 +02:00

x86/entry: Move SYSENTER's regs->sp and regs->flags fixups into C

The SYSENTER asm (32-bit and compat) contains fixups for regs->sp and
regs->flags.  Move the fixups into C and fix some comments while at it.

This is a valid cleanup all by itself, and it also simplifies the
subsequent patch that will fix Xen PV SYSENTER.

Signed-off-by: Andy Lutomirski <[email protected]>
Signed-off-by: Thomas Gleixner <[email protected]>
Link: 
https://lkml.kernel.org/r/fe62bef67eda7fac75b8f3dbafccf571dc4ece6b.1593191971.git.l...@kernel.org

---
 arch/x86/entry/common.c          | 12 ++++++++++++
 arch/x86/entry/entry_32.S        |  5 ++---
 arch/x86/entry/entry_64_compat.S | 11 +++++------
 3 files changed, 19 insertions(+), 9 deletions(-)

diff --git a/arch/x86/entry/common.c b/arch/x86/entry/common.c
index ed8ccc8..f392a8b 100644
--- a/arch/x86/entry/common.c
+++ b/arch/x86/entry/common.c
@@ -522,6 +522,18 @@ __visible noinstr long do_fast_syscall_32(struct pt_regs 
*regs)
                (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) 
== 0;
 #endif
 }
+
+/* Returns 0 to return using IRET or 1 to return using SYSEXIT/SYSRETL. */
+__visible noinstr long do_SYSENTER_32(struct pt_regs *regs)
+{
+       /* SYSENTER loses RSP, but the vDSO saved it in RBP. */
+       regs->sp = regs->bp;
+
+       /* SYSENTER clobbers EFLAGS.IF.  Assume it was set in usermode. */
+       regs->flags |= X86_EFLAGS_IF;
+
+       return do_fast_syscall_32(regs);
+}
 #endif
 
 SYSCALL_DEFINE0(ni_syscall)
diff --git a/arch/x86/entry/entry_32.S b/arch/x86/entry/entry_32.S
index 024d7d2..2d0bd5d 100644
--- a/arch/x86/entry/entry_32.S
+++ b/arch/x86/entry/entry_32.S
@@ -933,9 +933,8 @@ SYM_FUNC_START(entry_SYSENTER_32)
 
 .Lsysenter_past_esp:
        pushl   $__USER_DS              /* pt_regs->ss */
-       pushl   %ebp                    /* pt_regs->sp (stashed in bp) */
+       pushl   $0                      /* pt_regs->sp (placeholder) */
        pushfl                          /* pt_regs->flags (except IF = 0) */
-       orl     $X86_EFLAGS_IF, (%esp)  /* Fix IF */
        pushl   $__USER_CS              /* pt_regs->cs */
        pushl   $0                      /* pt_regs->ip = 0 (placeholder) */
        pushl   %eax                    /* pt_regs->orig_ax */
@@ -965,7 +964,7 @@ SYM_FUNC_START(entry_SYSENTER_32)
 .Lsysenter_flags_fixed:
 
        movl    %esp, %eax
-       call    do_fast_syscall_32
+       call    do_SYSENTER_32
        /* XEN PV guests always use IRET path */
        ALTERNATIVE "testl %eax, %eax; jz .Lsyscall_32_done", \
                    "jmp .Lsyscall_32_done", X86_FEATURE_XENPV
diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S
index 0f974ae..7b9d815 100644
--- a/arch/x86/entry/entry_64_compat.S
+++ b/arch/x86/entry/entry_64_compat.S
@@ -68,16 +68,15 @@ SYM_CODE_START(entry_SYSENTER_compat)
 
        /* Construct struct pt_regs on stack */
        pushq   $__USER32_DS            /* pt_regs->ss */
-       pushq   %rbp                    /* pt_regs->sp (stashed in bp) */
+       pushq   $0                      /* pt_regs->sp = 0 (placeholder) */
 
        /*
         * Push flags.  This is nasty.  First, interrupts are currently
-        * off, but we need pt_regs->flags to have IF set.  Second, even
-        * if TF was set when SYSENTER started, it's clear by now.  We fix
-        * that later using TIF_SINGLESTEP.
+        * off, but we need pt_regs->flags to have IF set.  Second, if TS
+        * was set in usermode, it's still set, and we're singlestepping
+        * through this code.  do_SYSENTER_32() will fix up IF.
         */
        pushfq                          /* pt_regs->flags (except IF = 0) */
-       orl     $X86_EFLAGS_IF, (%rsp)  /* Fix saved flags */
        pushq   $__USER32_CS            /* pt_regs->cs */
        pushq   $0                      /* pt_regs->ip = 0 (placeholder) */
        pushq   %rax                    /* pt_regs->orig_ax */
@@ -135,7 +134,7 @@ SYM_CODE_START(entry_SYSENTER_compat)
 .Lsysenter_flags_fixed:
 
        movq    %rsp, %rdi
-       call    do_fast_syscall_32
+       call    do_SYSENTER_32
        /* XEN PV guests always use IRET path */
        ALTERNATIVE "testl %eax, %eax; jz 
swapgs_restore_regs_and_return_to_usermode", \
                    "jmp swapgs_restore_regs_and_return_to_usermode", 
X86_FEATURE_XENPV

Reply via email to