Skip to content

Commit 5eee2b1

Browse files
Thomas Gleixnergregkh
authored andcommitted
selftests/rseq: Make registration flexible for legacy and optimized mode
commit d97cb2e upstream. 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: 566d801 ("rseq: Avoid CPU/MM CID updates when no event pending") 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/20260428224427.677889423%40kernel.org Cc: stable@vger.kernel.org Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent b833460 commit 5eee2b1

3 files changed

Lines changed: 31 additions & 23 deletions

File tree

tools/testing/selftests/rseq/rseq-abi.h

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,10 +191,15 @@ struct rseq_abi {
191191
*/
192192
struct rseq_abi_slice_ctrl slice_ctrl;
193193

194+
/*
195+
* Place holder to push the size above 32 bytes.
196+
*/
197+
__u8 __reserved;
198+
194199
/*
195200
* Flexible array member at end of structure, after last feature field.
196201
*/
197202
char end[];
198-
} __attribute__((aligned(4 * sizeof(__u64))));
203+
} __attribute__((aligned(256)));
199204

200205
#endif /* _RSEQ_ABI_H */

tools/testing/selftests/rseq/rseq.c

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ ptrdiff_t rseq_offset;
5656
* unsuccessful.
5757
*/
5858
unsigned int rseq_size = -1U;
59+
static unsigned int rseq_alloc_size;
5960

6061
/* Flags used during rseq registration. */
6162
unsigned int rseq_flags;
@@ -115,29 +116,17 @@ bool rseq_available(void)
115116
}
116117
}
117118

118-
/* The rseq areas need to be at least 32 bytes. */
119-
static
120-
unsigned int get_rseq_min_alloc_size(void)
121-
{
122-
unsigned int alloc_size = rseq_size;
123-
124-
if (alloc_size < ORIG_RSEQ_ALLOC_SIZE)
125-
alloc_size = ORIG_RSEQ_ALLOC_SIZE;
126-
return alloc_size;
127-
}
128-
129119
/*
130120
* Return the feature size supported by the kernel.
131121
*
132122
* Depending on the value returned by getauxval(AT_RSEQ_FEATURE_SIZE):
133123
*
134-
* 0: Return ORIG_RSEQ_FEATURE_SIZE (20)
124+
* 0: Return ORIG_RSEQ_FEATURE_SIZE (20)
135125
* > 0: Return the value from getauxval(AT_RSEQ_FEATURE_SIZE).
136126
*
137127
* It should never return a value below ORIG_RSEQ_FEATURE_SIZE.
138128
*/
139-
static
140-
unsigned int get_rseq_kernel_feature_size(void)
129+
static unsigned int get_rseq_kernel_feature_size(void)
141130
{
142131
unsigned long auxv_rseq_feature_size, auxv_rseq_align;
143132

@@ -152,15 +141,24 @@ unsigned int get_rseq_kernel_feature_size(void)
152141
return ORIG_RSEQ_FEATURE_SIZE;
153142
}
154143

155-
int rseq_register_current_thread(void)
144+
int __rseq_register_current_thread(bool nolibc, bool legacy)
156145
{
146+
unsigned int size;
157147
int rc;
158148

159149
if (!rseq_ownership) {
160150
/* Treat libc's ownership as a successful registration. */
161-
return 0;
151+
return nolibc ? -EBUSY : 0;
162152
}
163-
rc = sys_rseq(&__rseq.abi, get_rseq_min_alloc_size(), 0, RSEQ_SIG);
153+
154+
/* The minimal allocation size is 32, which is the legacy allocation size */
155+
size = get_rseq_kernel_feature_size();
156+
if (legacy || size < ORIG_RSEQ_ALLOC_SIZE)
157+
rseq_alloc_size = ORIG_RSEQ_ALLOC_SIZE;
158+
else
159+
rseq_alloc_size = size;
160+
161+
rc = sys_rseq(&__rseq.abi, rseq_alloc_size, 0, RSEQ_SIG);
164162
if (rc) {
165163
/*
166164
* After at least one thread has registered successfully
@@ -179,9 +177,8 @@ int rseq_register_current_thread(void)
179177
* The first thread to register sets the rseq_size to mimic the libc
180178
* behavior.
181179
*/
182-
if (RSEQ_READ_ONCE(rseq_size) == 0) {
183-
RSEQ_WRITE_ONCE(rseq_size, get_rseq_kernel_feature_size());
184-
}
180+
if (RSEQ_READ_ONCE(rseq_size) == 0)
181+
RSEQ_WRITE_ONCE(rseq_size, size);
185182

186183
return 0;
187184
}
@@ -194,7 +191,7 @@ int rseq_unregister_current_thread(void)
194191
/* Treat libc's ownership as a successful unregistration. */
195192
return 0;
196193
}
197-
rc = sys_rseq(&__rseq.abi, get_rseq_min_alloc_size(), RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
194+
rc = sys_rseq(&__rseq.abi, rseq_alloc_size, RSEQ_ABI_FLAG_UNREGISTER, RSEQ_SIG);
198195
if (rc)
199196
return -1;
200197
return 0;

tools/testing/selftests/rseq/rseq.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
#ifndef RSEQ_H
99
#define RSEQ_H
1010

11+
#include <assert.h>
1112
#include <stdint.h>
1213
#include <stdbool.h>
1314
#include <pthread.h>
@@ -142,7 +143,12 @@ static inline struct rseq_abi *rseq_get_abi(void)
142143
* succeed. A restartable sequence executed from a non-registered
143144
* thread will always fail.
144145
*/
145-
int rseq_register_current_thread(void);
146+
int __rseq_register_current_thread(bool nolibc, bool legacy);
147+
148+
static inline int rseq_register_current_thread(void)
149+
{
150+
return __rseq_register_current_thread(false, false);
151+
}
146152

147153
/*
148154
* Unregister rseq for current thread.

0 commit comments

Comments
 (0)