mirror of
https://github.com/torvalds/linux.git
synced 2026-05-12 16:18:45 +02:00
selftests/rseq: Expand for optimized RSEQ ABI v2
Update the selftests so they are executed for legacy (32 bytes RSEQ region)
and optimized RSEQ ABI v2 mode.
Fixes: d6200245c7 ("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
This commit is contained in:
parent
99428157dc
commit
e744060076
|
|
@ -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 $@
|
||||
|
|
|
|||
17
tools/testing/selftests/rseq/check_optimized.c
Normal file
17
tools/testing/selftests/rseq/check_optimized.c
Normal file
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
14
tools/testing/selftests/rseq/run_timeslice_test.sh
Executable file
14
tools/testing/selftests/rseq/run_timeslice_test.sh
Executable file
|
|
@ -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
|
||||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user