When run on a non-FRED system, test the opportunistic SYSRET fast-path. Make sure the %rcx/%r11 clobbering behavior is consistent.
When run on a FRED system, test that %rcx/%r11 are preserved when invoking syscall.
This is similar to what test_syscall_rcx_r11_consistent() is doing, but with addition it's done via the SIGUSR2 signal handler.
Link: https://lore.kernel.org/lkml/8770815f-0f23-d0c5-e56a-d401827842c9@zytor.com Suggested-by: H. Peter Anvin (Intel) hpa@zytor.com Signed-off-by: Ammar Faizi ammarfaizi2@gnuweeb.org ---
On Wed, 25 Jan 2023 00:39:26 -0800, "H. Peter Anvin" wrote:
/* Set IP and CX to match so that SYSRET can happen. */ ctx->uc_mcontext.gregs[REG_RIP] = rip; ctx->uc_mcontext.gregs[REG_RCX] = rip;
It would be interesting to have the syscall handler try both with and without this (so it would end up doing both IRET and SYSCALL on legacy.) Perhaps SIGUSR1 versus SIGUSR2...
tools/testing/selftests/x86/sysret_rip.c | 37 ++++++++++++++++++++++++ 1 file changed, 37 insertions(+)
diff --git a/tools/testing/selftests/x86/sysret_rip.c b/tools/testing/selftests/x86/sysret_rip.c index d45b7f0147cd25ad..a1e5ec6f08bcd523 100644 --- a/tools/testing/selftests/x86/sysret_rip.c +++ b/tools/testing/selftests/x86/sysret_rip.c @@ -275,6 +275,28 @@ static void test_syscall_rcx_r11_consistent(void) do_syscall(__NR_getppid, 0, 0, 0, 0, 0, 0); }
+static unsigned long usr2_rcx; +static unsigned long usr2_r11; + +static void sigusr2(int sig, siginfo_t *info, void *ctx_void) +{ + ucontext_t *ctx = (ucontext_t*)ctx_void; + + usr2_r11 = ctx->uc_mcontext.gregs[REG_R11]; + usr2_rcx = ctx->uc_mcontext.gregs[REG_RCX]; + + check_regs_result(ctx->uc_mcontext.gregs[REG_R11], + ctx->uc_mcontext.gregs[REG_RCX], + ctx->uc_mcontext.gregs[REG_RBX]); +} + +static void test_sysret_consistent(void) +{ + printf("[RUN]\ttest_sysret_consistent\n"); + __raise(SIGUSR2); + printf("[OK]\tRCX = %#lx; R11 = %#lx\n", usr2_rcx, usr2_r11); +} + int main() { int i; @@ -292,6 +314,21 @@ int main() for (i = 47; i < 64; i++) test_sigreturn_to(1UL<<i);
+ /* + * + * When run on a non-FRED system, test the SYSRET path. Make + * sure the %rcx/%r11 clobbering behavior is consistent. + * + * When run on a FRED system, test that %rcx/%r11 are preserved + * when invoking syscall. + * + * This is similar to test_syscall_rcx_r11_consistent(), but via + * a signal handler. + */ + sethandler(SIGUSR2, sigusr2, 0); + for (i = 0; i < 32; i++) + test_sysret_consistent(); + clearhandler(SIGUSR1);
sethandler(SIGSEGV, sigsegv_for_fallthrough, 0);