Skip to content

Commit e075d9f

Browse files
ChangSeokBaeIngo Molnar
authored andcommitted
selftests/x86/xstate: Introduce signal ABI test
With the refactored test cases, another xstate exposure to userspace is through signal delivery. While amx.c includes signal-related scenarios, its primary focus is on xstate permission management, which is largely specific to dynamic states. The remaining gap is testing xstate preservation and restoration across signal delivery. The kernel defines an ABI for presenting xstate in the signal frame, closely resembling the hardware XSAVE format, where xstate modification is also possible. Introduce a new test case to verify xstate preservation across signal delivery and return, that is ensuring ABI compatibility by: - Loading xstate before raising a signal. - Verifying correct exposure in the signal frame - Modifying xstate in the signal frame before returning. - Checking the state restoration upon signal return. Integrate this test into the AMX test suite as an initial usage site. Expected output: $ amx_64 ... [RUN] AMX Tile data: load xstate and raise SIGUSR1 [OK] 'magic1' is valid [OK] 'xfeatures' in SW reserved area is valid [OK] 'xfeatures' in XSAVE header is valid [OK] xstate delivery was successful [OK] 'magic2' is valid [RUN] AMX Tile data: load new xstate from sighandler and check it after sigreturn [OK] xstate was restored correctly Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com> Signed-off-by: Ingo Molnar <mingo@kernel.org> Link: https://lore.kernel.org/r/20250226010731.2456-7-chang.seok.bae@intel.com
1 parent 7cb2fbe commit e075d9f

File tree

3 files changed

+111
-0
lines changed

3 files changed

+111
-0
lines changed

tools/testing/selftests/x86/amx.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -510,6 +510,8 @@ int main(void)
510510

511511
test_ptrace(XFEATURE_XTILEDATA);
512512

513+
test_signal(XFEATURE_XTILEDATA);
514+
513515
clearhandler(SIGILL);
514516
free_stashed_xsave();
515517

tools/testing/selftests/x86/xstate.c

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,11 @@ static inline uint64_t xgetbv(uint32_t index)
2121
return eax + ((uint64_t)edx << 32);
2222
}
2323

24+
static inline uint64_t get_xstatebv(struct xsave_buffer *xbuf)
25+
{
26+
return *(uint64_t *)(&xbuf->header);
27+
}
28+
2429
static struct xstate_info xstate;
2530

2631
struct futex_info {
@@ -325,3 +330,106 @@ void test_ptrace(uint32_t feature_num)
325330
if (!WIFEXITED(status) || WEXITSTATUS(status))
326331
ksft_exit_fail_msg("ptracee exit error\n");
327332
}
333+
334+
/*
335+
* Test signal delivery for the ABI compatibility.
336+
* See the ABI format: arch/x86/include/uapi/asm/sigcontext.h
337+
*/
338+
339+
/*
340+
* Avoid using printf() in signal handlers as it is not
341+
* async-signal-safe.
342+
*/
343+
#define SIGNAL_BUF_LEN 1000
344+
static char signal_message_buffer[SIGNAL_BUF_LEN];
345+
static void sig_print(char *msg)
346+
{
347+
int left = SIGNAL_BUF_LEN - strlen(signal_message_buffer) - 1;
348+
349+
strncat(signal_message_buffer, msg, left);
350+
}
351+
352+
static struct xsave_buffer *stashed_xbuf;
353+
354+
static void validate_sigfpstate(int sig, siginfo_t *si, void *ctx_void)
355+
{
356+
ucontext_t *ctx = (ucontext_t *)ctx_void;
357+
void *xbuf = ctx->uc_mcontext.fpregs;
358+
struct _fpx_sw_bytes *sw_bytes;
359+
uint32_t magic2;
360+
361+
/* Reset the signal message buffer: */
362+
signal_message_buffer[0] = '\0';
363+
364+
sw_bytes = get_fpx_sw_bytes(xbuf);
365+
if (sw_bytes->magic1 == FP_XSTATE_MAGIC1)
366+
sig_print("[OK]\t'magic1' is valid\n");
367+
else
368+
sig_print("[FAIL]\t'magic1' is not valid\n");
369+
370+
if (get_fpx_sw_bytes_features(xbuf) & xstate.mask)
371+
sig_print("[OK]\t'xfeatures' in SW reserved area is valid\n");
372+
else
373+
sig_print("[FAIL]\t'xfeatures' in SW reserved area is not valid\n");
374+
375+
if (get_xstatebv(xbuf) & xstate.mask)
376+
sig_print("[OK]\t'xfeatures' in XSAVE header is valid\n");
377+
else
378+
sig_print("[FAIL]\t'xfeatures' in XSAVE hader is not valid\n");
379+
380+
if (validate_xstate_same(stashed_xbuf, xbuf))
381+
sig_print("[OK]\txstate delivery was successful\n");
382+
else
383+
sig_print("[FAIL]\txstate delivery was not successful\n");
384+
385+
magic2 = *(uint32_t *)(xbuf + sw_bytes->xstate_size);
386+
if (magic2 == FP_XSTATE_MAGIC2)
387+
sig_print("[OK]\t'magic2' is valid\n");
388+
else
389+
sig_print("[FAIL]\t'magic2' is not valid\n");
390+
391+
set_rand_data(&xstate, xbuf);
392+
copy_xstate(stashed_xbuf, xbuf);
393+
}
394+
395+
void test_signal(uint32_t feature_num)
396+
{
397+
bool valid_xstate;
398+
399+
xstate = get_xstate_info(feature_num);
400+
401+
/*
402+
* The signal handler will access this to verify xstate context
403+
* preservation.
404+
*/
405+
406+
stashed_xbuf = alloc_xbuf();
407+
if (!stashed_xbuf)
408+
ksft_exit_fail_msg("unable to allocate XSAVE buffer\n");
409+
410+
printf("[RUN]\t%s: load xstate and raise SIGUSR1\n", xstate.name);
411+
412+
sethandler(SIGUSR1, validate_sigfpstate, 0);
413+
414+
load_rand_xstate(&xstate, stashed_xbuf);
415+
416+
raise(SIGUSR1);
417+
418+
/*
419+
* Immediately record the test result, deferring printf() to
420+
* prevent unintended state contamination by that.
421+
*/
422+
valid_xstate = validate_xregs_same(stashed_xbuf);
423+
printf("%s", signal_message_buffer);
424+
425+
printf("[RUN]\t%s: load new xstate from sighandler and check it after sigreturn\n",
426+
xstate.name);
427+
428+
if (valid_xstate)
429+
printf("[OK]\txstate was restored correctly\n");
430+
else
431+
printf("[FAIL]\txstate restoration failed\n");
432+
433+
clearhandler(SIGUSR1);
434+
free(stashed_xbuf);
435+
}

tools/testing/selftests/x86/xstate.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -191,5 +191,6 @@ static inline void set_rand_data(struct xstate_info *xstate, struct xsave_buffer
191191

192192
void test_context_switch(uint32_t feature_num, uint32_t num_threads, uint32_t iterations);
193193
void test_ptrace(uint32_t feature_num);
194+
void test_signal(uint32_t feature_num);
194195

195196
#endif /* __SELFTESTS_X86_XSTATE_H */

0 commit comments

Comments
 (0)