Re: [patch 10/10] selftests/rseq: Expand for optimized RSEQ ABI v2

Dmitry Vyukov
2026-04-29T09:35:49Z

On Wed, 29 Apr 2026 at 01:34, Thomas Gleixner <tglx@kernel.org> wrote:
>
> 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>
> Cc: stable@vger.kernel.org

Reviewed-by: Dmitry Vyukov <dvyukov@google.com>

> ---
> tools/testing/selftests/rseq/Makefile | 7 ++-
> tools/testing/selftests/rseq/check_optimized.c | 17 +++++++++
> tools/testing/selftests/rseq/param_test.c | 22 +++++++----
> tools/testing/selftests/rseq/run_param_test.sh | 39 +++++++++++++++++++++
> tools/testing/selftests/rseq/run_timeslice_test.sh | 14 +++++++
> tools/testing/selftests/rseq/slice_test.c | 2 -
> 6 files changed, 89 insertions(+), 12 deletions(-)
>
> --- a/tools/testing/selftests/rseq/Makefile
> +++ b/tools/testing/selftests/rseq/Makefile
> @@ -17,11 +17,11 @@ OVERRIDE_TARGETS = 1
> TEST_GEN_PROGS = basic_test basic_percpu_ops_test basic_percpu_ops_mm_cid_test param_test \
> param_test_benchmark param_test_compare_twice param_test_mm_cid \
> param_test_mm_cid_benchmark param_test_mm_cid_compare_twice \
> - syscall_errors_test slice_test legacy_check
> + syscall_errors_test slice_test legacy_check check_optimized
>
> TEST_GEN_PROGS_EXTENDED = librseq.so
>
> -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
>
> @@ -62,3 +62,6 @@ include ../lib.mk
>
> $(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 $@
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/check_optimized.c
> @@ -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;
> +}
> --- a/tools/testing/selftests/rseq/param_test.c
> +++ b/tools/testing/selftests/rseq/param_test.c
> @@ -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")))
> @@ -481,7 +481,7 @@ void *test_percpu_spinlock_thread(void *
> long long i, reps;
>
> if (!opt_disable_rseq && thread_data->reg &&
> - rseq_register_current_thread())
> + __rseq_register_current_thread(true, opt_rseq_legacy))
> abort();
> reps = thread_data->reps;
> for (i = 0; i < reps; i++) {
> @@ -558,7 +558,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(true, opt_rseq_legacy))
> abort();
> reps = thread_data->reps;
> for (i = 0; i < reps; i++) {
> @@ -712,7 +712,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(true, opt_rseq_legacy))
> abort();
>
> reps = opt_reps;
> @@ -895,7 +895,7 @@ void *test_percpu_buffer_thread(void *ar
> 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(true, opt_rseq_legacy))
> abort();
>
> reps = opt_reps;
> @@ -1105,7 +1105,7 @@ void *test_percpu_memcpy_buffer_thread(v
> 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(true, opt_rseq_legacy))
> abort();
>
> reps = opt_reps;
> @@ -1258,7 +1258,7 @@ void *test_membarrier_worker_thread(void
> const int iters = opt_reps;
> int i;
>
> - if (rseq_register_current_thread()) {
> + if (__rseq_register_current_thread(true, opt_rseq_legacy)) {
> fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n",
> errno, strerror(errno));
> abort();
> @@ -1323,7 +1323,7 @@ void *test_membarrier_manager_thread(voi
> 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(true, opt_rseq_legacy)) {
> fprintf(stderr, "Error: rseq_register_current_thread(...) failed(%d): %s\n",
> errno, strerror(errno));
> abort();
> @@ -1475,6 +1475,7 @@ static void show_usage(int argc, char **
> 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 +1603,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 +1622,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(true, opt_rseq_legacy))
> goto error;
> if (!opt_disable_rseq && !rseq_validate_cpu_id()) {
> fprintf(stderr, "Error: cpu id getter unavailable\n");
> --- a/tools/testing/selftests/rseq/run_param_test.sh
> +++ b/tools/testing/selftests/rseq/run_param_test.sh
> @@ -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
>
> --- /dev/null
> +++ b/tools/testing/selftests/rseq/run_timeslice_test.sh
> @@ -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
> --- a/tools/testing/selftests/rseq/slice_test.c
> +++ b/tools/testing/selftests/rseq/slice_test.c
> @@ -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,
>