@@ -255,34 +255,30 @@ __visible noinstr bool do_fast_syscall_32(struct pt_regs *regs)
255
255
if (!__do_fast_syscall_32 (regs ))
256
256
return false;
257
257
258
- #ifdef CONFIG_X86_64
259
258
/*
260
- * Opportunistic SYSRETL: if possible, try to return using SYSRETL.
261
- * SYSRETL is available on all 64-bit CPUs, so we don't need to
262
- * bother with SYSEXIT.
263
- *
264
- * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
265
- * because the ECX fixup above will ensure that this is essentially
266
- * never the case.
259
+ * Check that the register state is valid for using SYSRETL/SYSEXIT
260
+ * to exit to userspace. Otherwise use the slower but fully capable
261
+ * IRET exit path.
267
262
*/
268
- return regs -> cs == __USER32_CS && regs -> ss == __USER_DS &&
269
- regs -> ip == landing_pad &&
270
- (regs -> flags & (X86_EFLAGS_RF | X86_EFLAGS_TF )) == 0 ;
271
- #else
272
- /*
273
- * Opportunistic SYSEXIT: if possible, try to return using SYSEXIT.
274
- *
275
- * Unlike 64-bit opportunistic SYSRET, we can't check that CX == IP,
276
- * because the ECX fixup above will ensure that this is essentially
277
- * never the case.
278
- *
279
- * We don't allow syscalls at all from VM86 mode, but we still
280
- * need to check VM, because we might be returning from sys_vm86.
281
- */
282
- return regs -> cs == __USER_CS && regs -> ss == __USER_DS &&
283
- regs -> ip == landing_pad &&
284
- (regs -> flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM )) == 0 ;
285
- #endif
263
+
264
+ /* XEN PV guests always use the IRET path */
265
+ if (cpu_feature_enabled (X86_FEATURE_XENPV ))
266
+ return false;
267
+
268
+ /* EIP must point to the VDSO landing pad */
269
+ if (unlikely (regs -> ip != landing_pad ))
270
+ return false;
271
+
272
+ /* CS and SS must match the values set in MSR_STAR */
273
+ if (unlikely (regs -> cs != __USER32_CS || regs -> ss != __USER_DS ))
274
+ return false;
275
+
276
+ /* If the TF, RF, or VM flags are set, use IRET */
277
+ if (unlikely (regs -> flags & (X86_EFLAGS_RF | X86_EFLAGS_TF | X86_EFLAGS_VM )))
278
+ return false;
279
+
280
+ /* Use SYSRETL/SYSEXIT to exit to userspace */
281
+ return true;
286
282
}
287
283
288
284
/* Returns true to return using SYSEXIT/SYSRETL, or false to use IRET */
0 commit comments