]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
selftests/rseq: Expand for optimized RSEQ ABI v2
authorThomas Gleixner <tglx@kernel.org>
Sat, 25 Apr 2026 12:48:23 +0000 (14:48 +0200)
committerPeter Zijlstra <peterz@infradead.org>
Wed, 6 May 2026 15:41:08 +0000 (17:41 +0200)
Update the selftests so they are executed for legacy (32 bytes RSEQ region)
and optimized RSEQ ABI v2 mode.

Fixes: d6200245c75e ("rseq: Allow registering RSEQ with slice extension")
Signed-off-by: Thomas Gleixner <tglx@kernel.org>
Signed-off-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Reviewed-by: Dmitry Vyukov <dvyukov@google.com>
Tested-by: Dmitry Vyukov <dvyukov@google.com>
Link: https://patch.msgid.link/20260428224428.009121296%40kernel.org
Cc: stable@vger.kernel.org
tools/testing/selftests/rseq/Makefile
tools/testing/selftests/rseq/check_optimized.c [new file with mode: 0644]
tools/testing/selftests/rseq/param_test.c
tools/testing/selftests/rseq/run_param_test.sh
tools/testing/selftests/rseq/run_timeslice_test.sh [new file with mode: 0755]
tools/testing/selftests/rseq/slice_test.c

index 0293a2f17f51152d4a41399bf21c1e29d1edb727..50d69e22ee7a67880eabc64bea1736467a791aa3 100644 (file)
@@ -15,7 +15,7 @@ LDLIBS += -lpthread -ldl
 OVERRIDE_TARGETS = 1
 
 TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_mm_cid_test \
-                param_test_benchmark param_test_mm_cid_benchmark slice_test
+                param_test_benchmark param_test_mm_cid_benchmark
 
 TEST_GEN_PROGS_EXTENDED = librseq.so \
        param_test \
@@ -23,9 +23,11 @@ TEST_GEN_PROGS_EXTENDED = librseq.so \
        param_test_mm_cid \
        param_test_mm_cid_compare_twice \
        syscall_errors_test \
-       legacy_check
+       legacy_check \
+       slice_test \
+       check_optimized
 
-TEST_PROGS = run_param_test.sh run_syscall_errors_test.sh run_legacy_check.sh
+TEST_PROGS = run_param_test.sh run_syscall_errors_test.sh run_legacy_check.sh run_timeslice_test.sh
 
 TEST_FILES := settings
 
@@ -66,3 +68,6 @@ $(OUTPUT)/syscall_errors_test: syscall_errors_test.c $(TEST_GEN_PROGS_EXTENDED)
 
 $(OUTPUT)/slice_test: slice_test.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h
        $(CC) $(CFLAGS) $< $(LDLIBS) -lrseq -o $@
+
+$(OUTPUT)/check_optimized: check_optimized.c $(TEST_GEN_PROGS_EXTENDED) rseq.h rseq-*.h
+       $(CC) $(CFLAGS) $< $(LDLIBS) -lrseq -o $@
diff --git a/tools/testing/selftests/rseq/check_optimized.c b/tools/testing/selftests/rseq/check_optimized.c
new file mode 100644 (file)
index 0000000..a13e3f2
--- /dev/null
@@ -0,0 +1,17 @@
+// SPDX-License-Identifier: LGPL-2.1
+#define _GNU_SOURCE
+#include <assert.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/time.h>
+
+#include "rseq.h"
+
+int main(int argc, char **argv)
+{
+       if (__rseq_register_current_thread(true, false))
+               return -1;
+       return 0;
+}
index 05d03e679e060834f4d6c13f0fbb60da7e3059b7..e1e98dbabe4bcf18b458bc2b9c9bdde55139c028 100644 (file)
@@ -38,7 +38,7 @@ static int opt_modulo, verbose;
 static int opt_yield, opt_signal, opt_sleep,
                opt_disable_rseq, opt_threads = 200,
                opt_disable_mod = 0, opt_test = 's';
-
+static bool opt_rseq_legacy;
 static long long opt_reps = 5000;
 
 static __thread __attribute__((tls_model("initial-exec")))
@@ -281,9 +281,12 @@ unsigned int yield_mod_cnt, nr_abort;
        } \
 }
 
+#define rseq_no_glibc                  true
+
 #else
 
 #define printf_verbose(fmt, ...)
+#define rseq_no_glibc                  false
 
 #endif /* BENCHMARK */
 
@@ -481,7 +484,7 @@ void *test_percpu_spinlock_thread(void *arg)
        long long i, reps;
 
        if (!opt_disable_rseq && thread_data->reg &&
-           rseq_register_current_thread())
+           __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                abort();
        reps = thread_data->reps;
        for (i = 0; i < reps; i++) {
@@ -558,7 +561,7 @@ void *test_percpu_inc_thread(void *arg)
        long long i, reps;
 
        if (!opt_disable_rseq && thread_data->reg &&
-           rseq_register_current_thread())
+           __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                abort();
        reps = thread_data->reps;
        for (i = 0; i < reps; i++) {
@@ -712,7 +715,7 @@ void *test_percpu_list_thread(void *arg)
        long long i, reps;
        struct percpu_list *list = (struct percpu_list *)arg;
 
-       if (!opt_disable_rseq && rseq_register_current_thread())
+       if (!opt_disable_rseq && __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                abort();
 
        reps = opt_reps;
@@ -895,7 +898,7 @@ void *test_percpu_buffer_thread(void *arg)
        long long i, reps;
        struct percpu_buffer *buffer = (struct percpu_buffer *)arg;
 
-       if (!opt_disable_rseq && rseq_register_current_thread())
+       if (!opt_disable_rseq && __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                abort();
 
        reps = opt_reps;
@@ -1105,7 +1108,7 @@ void *test_percpu_memcpy_buffer_thread(void *arg)
        long long i, reps;
        struct percpu_memcpy_buffer *buffer = (struct percpu_memcpy_buffer *)arg;
 
-       if (!opt_disable_rseq && rseq_register_current_thread())
+       if (!opt_disable_rseq && __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                abort();
 
        reps = opt_reps;
@@ -1258,7 +1261,7 @@ void *test_membarrier_worker_thread(void *arg)
        const int iters = opt_reps;
        int i;
 
-       if (rseq_register_current_thread()) {
+       if (__rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy)) {
                fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n",
                        errno, strerror(errno));
                abort();
@@ -1323,7 +1326,7 @@ void *test_membarrier_manager_thread(void *arg)
        intptr_t expect_a = 0, expect_b = 0;
        int cpu_a = 0, cpu_b = 0;
 
-       if (rseq_register_current_thread()) {
+       if (__rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy)) {
                fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n",
                        errno, strerror(errno));
                abort();
@@ -1475,6 +1478,7 @@ static void show_usage(int argc, char **argv)
        printf("        [-D M] Disable rseq for each M threads\n");
        printf("        [-T test] Choose test: (s)pinlock, (l)ist, (b)uffer, (m)emcpy, (i)ncrement, membarrie(r)\n");
        printf("        [-M] Push into buffer and memcpy buffer with memory barriers.\n");
+       printf("        [-O] Test with optimized RSEQ\n");
        printf("        [-v] Verbose output.\n");
        printf("        [-h] Show this help.\n");
        printf("\n");
@@ -1602,6 +1606,9 @@ int main(int argc, char **argv)
                case 'M':
                        opt_mo = RSEQ_MO_RELEASE;
                        break;
+               case 'L':
+                       opt_rseq_legacy = true;
+                       break;
                default:
                        show_usage(argc, argv);
                        goto error;
@@ -1618,7 +1625,7 @@ int main(int argc, char **argv)
        if (set_signal_handler())
                goto error;
 
-       if (!opt_disable_rseq && rseq_register_current_thread())
+       if (!opt_disable_rseq && __rseq_register_current_thread(rseq_no_glibc, opt_rseq_legacy))
                goto error;
        if (!opt_disable_rseq && !rseq_validate_cpu_id()) {
                fprintf(stderr, "Error: cpu id getter unavailable\n");
index 8d31426ab41f22daa66d68c3ac150ee7bb26221d..69a3fa049929f3f89860990e69ebff88c6fc8566 100755 (executable)
@@ -34,6 +34,11 @@ REPS=1000
 SLOW_REPS=100
 NR_THREADS=$((6*${NR_CPUS}))
 
+# Prevent GLIBC from registering RSEQ so the selftest can run in legacy and
+# performance optimized mode.
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0"
+export GLIBC_TUNABLES
+
 function do_tests()
 {
        local i=0
@@ -103,6 +108,40 @@ function inject_blocking()
        NR_LOOPS=
 }
 
+echo "Testing in legacy RSEQ mode"
+echo "Yield injection (25%)"
+inject_blocking -m 4 -y -L
+
+echo "Yield injection (50%)"
+inject_blocking -m 2 -y -L
+
+echo "Yield injection (100%)"
+inject_blocking -m 1 -y -L
+
+echo "Kill injection (25%)"
+inject_blocking -m 4 -k -L
+
+echo "Kill injection (50%)"
+inject_blocking -m 2 -k -L
+
+echo "Kill injection (100%)"
+inject_blocking -m 1 -k -L
+
+echo "Sleep injection (1ms, 25%)"
+inject_blocking -m 4 -s 1 -L
+
+echo "Sleep injection (1ms, 50%)"
+inject_blocking -m 2 -s 1 -L
+
+echo "Sleep injection (1ms, 100%)"
+inject_blocking -m 1 -s 1 -L
+
+./check_optimized || {
+    echo "Skipping optimized RSEQ mode test. Not supported";
+    exit 0
+}
+
+echo "Testing in optimized RSEQ mode"
 echo "Yield injection (25%)"
 inject_blocking -m 4 -y
 
diff --git a/tools/testing/selftests/rseq/run_timeslice_test.sh b/tools/testing/selftests/rseq/run_timeslice_test.sh
new file mode 100755 (executable)
index 0000000..551ebed
--- /dev/null
@@ -0,0 +1,14 @@
+#!/bin/bash
+# SPDX-License-Identifier: GPL-2.0+
+
+# Prevent GLIBC from registering RSEQ so the selftest can run in legacy
+# and performance optimized mode.
+GLIBC_TUNABLES="${GLIBC_TUNABLES:-}:glibc.pthread.rseq=0"
+export GLIBC_TUNABLES
+
+./check_optimized || {
+    echo "Skipping optimized RSEQ mode test. Not supported";
+    exit 0
+}
+
+./slice_test
index 77e668ff74d7f0660a55c92921835e9eda4a6759..e402d4440bc27f4f086bfcab109112dc966fd0b2 100644 (file)
@@ -124,7 +124,7 @@ FIXTURE_SETUP(slice_ext)
 {
        cpu_set_t affinity;
 
-       if (rseq_register_current_thread())
+       if (__rseq_register_current_thread(true, false))
                SKIP(return, "RSEQ not supported\n");
 
        if (prctl(PR_RSEQ_SLICE_EXTENSION, PR_RSEQ_SLICE_EXTENSION_SET,