Re: [patch 06/10] selftests/rseq: Make registration flexible for legacy and optimized mode
Dmitry Vyukov <[email protected]>
| Newsgroups | org.kernel.vger.linux-man,dev.linux.lists.regressions,org.kernel.vger.linux-kernel |
|---|---|
| Message-ID | <CACT4Y+Z-KnUe2DUPUT7omLjqETNXQwOP3CxpsHua5yG3=dqbAA@mail.gmail.com> |
On Wed, 29 Apr 2026 at 01:34, Thomas Gleixner <[email protected]> wrote: > > rseq_register_current_thread() either uses the glibc registered RSEQ region > or registers it's own region with the legacy size of 32 bytes. > > That worked so far, but becomes a problem when the kernel implements a > distinction between legacy and performance optimized behavior based on the > registration size as that does not allow to test both modes with the self > test suite. > > Add two arguments to the function. One to enforce that the registration is > not using libc provided mode and one to tell the registration to use the > legacy size and not the kernel advertised size. > > Rename it and make the original one a inline wrapper which preserves the > existing behavior. > > Fixes: 566d8015f7ee ("rseq: Avoid CPU/MM CID updates when no event pending") > Signed-off-by: Thomas Gleixner <[email protected]> > Cc: [email protected] Reviewed-by: Dmitry Vyukov <[email protected]> > --- > tools/testing/selftests/rseq/rseq-abi.h | 7 ++++- > tools/testing/selftests/rseq/rseq.c | 39 ++++++++++++++------------------ > tools/testing/selftests/rseq/rseq.h | 8 +++++- > 3 files changed, 31 insertions(+), 23 deletions(-) > > --- a/tools/testing/selftests/rseq/rseq-abi.h > +++ b/tools/testing/selftests/rseq/rseq-abi.h > @@ -192,9 +192,14 @@ struct rseq_abi { > struct rseq_abi_slice_ctrl slice_ctrl; > > /* > + * Place holder to push the size above 32 bytes. > + */ > + __u8 __reserved; > + > + /* > * Flexible array member at end of structure, after last feature field. > */ > char end[]; > -} __attribute__((aligned(4 * sizeof(__u64)))); > +} __attribute__((aligned(256))); > > #endif /* _RSEQ_ABI_H */ > --- a/tools/testing/selftests/rseq/rseq.c > +++ b/tools/testing/selftests/rseq/rseq.c > @@ -56,6 +56,7 @@ ptrdiff_t rseq_offset; > * unsuccessful. > */ > unsigned int rseq_size = -1U; > +static unsigned int rseq_alloc_size; > > /* Flags used during rseq registration. */ > unsigned int rseq_flags; > @@ -115,29 +116,17 @@ bool rseq_available(void) > } > } > > -/* The rseq areas need to be at least 32 bytes. */ > -static > -unsigned int get_rseq_min_alloc_size(void) > -{ > - unsigned int alloc_size = rseq_size; > - > - if (alloc_size < ORIG_RSEQ_ALLOC_SIZE) > - alloc_size = ORIG_RSEQ_ALLOC_SIZE; > - return alloc_size; > -} > - > /* > * Return the feature size supported by the kernel. > * > * Depending on the value returned by getauxval(AT_RSEQ_FEATURE_SIZE): > * > - * 0: Return ORIG_RSEQ_FEATURE_SIZE (20) > + * 0: Return ORIG_RSEQ_FEATURE_SIZE (20) > * > 0: Return the value from getauxval(AT_RSEQ_FEATURE_SIZE). > * > * It should never return a value below ORIG_RSEQ_FEATURE_SIZE. > */ > -static > -unsigned int get_rseq_kernel_feature_size(void) > +static unsigned int get_rseq_kernel_feature_size(void) > { > unsigned long auxv_rseq_feature_size, auxv_rseq_align; > > @@ -152,15 +141,24 @@ unsigned int get_rseq_kernel_feature_siz > return ORIG_RSEQ_FEATURE_SIZE; > } > > -int rseq_register_current_thread(void) > +int __rseq_register_current_thread(bool nolibc, bool legacy) > { > + unsigned int size; > int rc; > > if (!rseq_ownership) { > /* Treat libc's ownership as a successful registration. */ > - return 0; > + return nolibc ? -EBUSY : 0; > } > - rc = sys_rseq(&__rseq.abi, get_rseq_min_alloc_size(), 0, RSEQ_SIG); > + > + /* The minimal allocation size is 32, which is the legacy allocation size */ > + size = get_rseq_kernel_feature_size(); > + if (legacy || size < ORIG_RSEQ_ALLOC_SIZE) > + rseq_alloc_size = ORIG_RSEQ_ALLOC_SIZE; > + else > + rseq_alloc_size = size; > + > + rc = sys_rseq(&__rseq.abi, rseq_alloc_size, 0, RSEQ_SIG); > if (rc) { > /* > * After at least one thread has registered successfully > @@ -179,9 +177,8 @@ int rseq_register_current_thread(void) > * The first thread to register sets the rseq_size to mimic the libc > * behavior. > */ > - if (RSEQ_READ_ONCE(rseq_size) == 0) { > - RSEQ_WRITE_ONCE(rseq_size, get_rseq_kernel_feature_size()); > - } > + if (RSEQ_READ_ONCE(rseq_size) == 0) > + RSEQ_WRITE_ONCE(rseq_size, size); > > return 0; > } > @@ -194,7 +191,7 @@ int rseq_unregister_current_thread(void) > /* Treat libc's ownership as a successful unregistration. */ > return 0; > } > - rc = sys_rseq(&__rseq.abi, get_rseq_min_alloc_size(), RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG); > + rc = sys_rseq(&__rseq.abi, rseq_alloc_size, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG); > if (rc) > return -1; > return 0; > --- a/tools/testing/selftests/rseq/rseq.h > +++ b/tools/testing/selftests/rseq/rseq.h > @@ -8,6 +8,7 @@ > #ifndef RSEQ_H > #define RSEQ_H > > +#include <assert.h> > #include <stdint.h> > #include <stdbool.h> > #include <pthread.h> > @@ -142,7 +143,12 @@ static inline struct rseq_abi *rseq_get_ > * succeed. A restartable sequence executed from a non-registered > * thread will always fail. > */ > -int rseq_register_current_thread(void); > +int __rseq_register_current_thread(bool nolibc, bool legacy); > + > +static inline int rseq_register_current_thread(void) > +{ > + return __rseq_register_current_thread(false, false); > +} > > /* > * Unregister rseq for current thread. >