x86/entry/32: Clean up syscall fast exit tests
authorBrian Gerst <brgerst@gmail.com>
Wed, 11 Oct 2023 22:43:51 +0000 (18:43 -0400)
committerIngo Molnar <mingo@kernel.org>
Fri, 13 Oct 2023 11:05:28 +0000 (13:05 +0200)
Merge compat and native code and clarify comments.

No change in functionality expected.

Signed-off-by: Brian Gerst <brgerst@gmail.com>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Uros Bizjak <ubizjak@gmail.com>
Link: https://lore.kernel.org/r/20231011224351.130935-4-brgerst@gmail.com
arch/x86/entry/common.c

index 4c7154d097c11eb42f80d8cef48c3bdfa1452779..d813160b14d85172c307b9436a6703ab9b6b1768 100644 (file)
@@ -255,34 +255,30 @@ __visible noinstr bool do_fast_syscall_32(struct pt_regs *regs)
        if (!__do_fast_syscall_32(regs))
                return false;
 
-#ifdef CONFIG_X86_64
        /*
-        * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
-        * SYSRETL is available on all 64-bit CPUs, so we don't need to
-        * bother with SYSEXIT.
-        *
-        * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
-        * because the ECX fixup above will ensure that this is essentially
-        * never the case.
+        * Check that the register state is valid for using SYSRETL/SYSEXIT
+        * to exit to userspace.  Otherwise use the slower but fully capable
+        * IRET exit path.
         */
-       return regs->cs == __USER32_CS && regs->ss == __USER_DS &&
-               regs->ip == landing_pad &&
-               (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF)) == 0;
-#else
-       /*
-        * Opportunistic SYSEXIT: if possible, try to return using SYSEXIT.
-        *
-        * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
-        * because the ECX fixup above will ensure that this is essentially
-        * never the case.
-        *
-        * We don't allow syscalls at all from VM86 mode, but we still
-        * need to check VM, because we might be returning from sys_vm86.
-        */
-       return regs->cs == __USER_CS && regs->ss == __USER_DS &&
-               regs->ip == landing_pad &&
-               (regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)) == 0;
-#endif
+
+       /* XEN PV guests always use the IRET path */
+       if (cpu_feature_enabled(X86_FEATURE_XENPV))
+               return false;
+
+       /* EIP must point to the VDSO landing pad */
+       if (unlikely(regs->ip != landing_pad))
+               return false;
+
+       /* CS and SS must match the values set in MSR_STAR */
+       if (unlikely(regs->cs != __USER32_CS || regs->ss != __USER_DS))
+               return false;
+
+       /* If the TF, RF, or VM flags are set, use IRET */
+       if (unlikely(regs->flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM)))
+               return false;
+
+       /* Use SYSRETL/SYSEXIT to exit to userspace */
+       return true;
 }
 
 /* Returns true to return using SYSEXIT/SYSRETL, or false to use IRET */