Skip to content

Commit 40f6852

Browse files
ChangSeokBaeIngo Molnar
authored andcommitted
selftests/x86/xstate: Refactor context switching test
The existing context switching and ptrace tests in amx.c are not specific to dynamic states, making them reusable for general xstate testing. As a first step, move the context switching test to xstate.c. Refactor the test code to allow specifying which xstate component being tested. To decouple the test from dynamic states, remove the permission request code. In fact, The permission request inside the test wrapper was redundant. Additionally, replace fatal_error() with ksft_exit_fail_msg() for consistency in error handling. Expected output: $ amx_64 ... [RUN] AMX Tile data: check context switches, 10 iterations, 5 threads. [OK] No incorrect case was found. Signed-off-by: Chang S. Bae <[email protected]> Signed-off-by: Ingo Molnar <[email protected]> Link: https://lore.kernel.org/r/[email protected]
1 parent 3fcb4d6 commit 40f6852

File tree

4 files changed

+204
-164
lines changed

4 files changed

+204
-164
lines changed

tools/testing/selftests/x86/Makefile

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -132,3 +132,5 @@ $(OUTPUT)/check_initial_reg_state_64: CFLAGS += -Wl,-ereal_start -static
132132

133133
$(OUTPUT)/nx_stack_32: CFLAGS += -Wl,-z,noexecstack
134134
$(OUTPUT)/nx_stack_64: CFLAGS += -Wl,-z,noexecstack
135+
136+
$(OUTPUT)/amx_64: EXTRA_FILES += xstate.c

tools/testing/selftests/x86/amx.c

Lines changed: 2 additions & 164 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
#define _GNU_SOURCE
44
#include <err.h>
55
#include <errno.h>
6-
#include <pthread.h>
76
#include <setjmp.h>
87
#include <stdio.h>
98
#include <string.h>
@@ -434,14 +433,6 @@ static inline bool __validate_tiledata_regs(struct xsave_buffer *xbuf1)
434433
return true;
435434
}
436435

437-
static inline void validate_tiledata_regs_same(struct xsave_buffer *xbuf)
438-
{
439-
int ret = __validate_tiledata_regs(xbuf);
440-
441-
if (ret != 0)
442-
fatal_error("TILEDATA registers changed");
443-
}
444-
445436
static inline void validate_tiledata_regs_changed(struct xsave_buffer *xbuf)
446437
{
447438
int ret = __validate_tiledata_regs(xbuf);
@@ -498,158 +489,6 @@ static void test_fork(void)
498489
_exit(0);
499490
}
500491

501-
/* Context switching test */
502-
503-
static struct _ctxtswtest_cfg {
504-
unsigned int iterations;
505-
unsigned int num_threads;
506-
} ctxtswtest_config;
507-
508-
struct futex_info {
509-
pthread_t thread;
510-
int nr;
511-
pthread_mutex_t mutex;
512-
struct futex_info *next;
513-
};
514-
515-
static void *check_tiledata(void *info)
516-
{
517-
struct futex_info *finfo = (struct futex_info *)info;
518-
struct xsave_buffer *xbuf;
519-
int i;
520-
521-
xbuf = alloc_xbuf();
522-
if (!xbuf)
523-
fatal_error("unable to allocate XSAVE buffer");
524-
525-
/*
526-
* Load random data into 'xbuf' and then restore
527-
* it to the tile registers themselves.
528-
*/
529-
load_rand_tiledata(xbuf);
530-
for (i = 0; i < ctxtswtest_config.iterations; i++) {
531-
pthread_mutex_lock(&finfo->mutex);
532-
533-
/*
534-
* Ensure the register values have not
535-
* diverged from those recorded in 'xbuf'.
536-
*/
537-
validate_tiledata_regs_same(xbuf);
538-
539-
/* Load new, random values into xbuf and registers */
540-
load_rand_tiledata(xbuf);
541-
542-
/*
543-
* The last thread's last unlock will be for
544-
* thread 0's mutex. However, thread 0 will
545-
* have already exited the loop and the mutex
546-
* will already be unlocked.
547-
*
548-
* Because this is not an ERRORCHECK mutex,
549-
* that inconsistency will be silently ignored.
550-
*/
551-
pthread_mutex_unlock(&finfo->next->mutex);
552-
}
553-
554-
free(xbuf);
555-
/*
556-
* Return this thread's finfo, which is
557-
* a unique value for this thread.
558-
*/
559-
return finfo;
560-
}
561-
562-
static int create_threads(int num, struct futex_info *finfo)
563-
{
564-
int i;
565-
566-
for (i = 0; i < num; i++) {
567-
int next_nr;
568-
569-
finfo[i].nr = i;
570-
/*
571-
* Thread 'i' will wait on this mutex to
572-
* be unlocked. Lock it immediately after
573-
* initialization:
574-
*/
575-
pthread_mutex_init(&finfo[i].mutex, NULL);
576-
pthread_mutex_lock(&finfo[i].mutex);
577-
578-
next_nr = (i + 1) % num;
579-
finfo[i].next = &finfo[next_nr];
580-
581-
if (pthread_create(&finfo[i].thread, NULL, check_tiledata, &finfo[i]))
582-
fatal_error("pthread_create()");
583-
}
584-
return 0;
585-
}
586-
587-
static void affinitize_cpu0(void)
588-
{
589-
cpu_set_t cpuset;
590-
591-
CPU_ZERO(&cpuset);
592-
CPU_SET(0, &cpuset);
593-
594-
if (sched_setaffinity(0, sizeof(cpuset), &cpuset) != 0)
595-
fatal_error("sched_setaffinity to CPU 0");
596-
}
597-
598-
static void test_context_switch(void)
599-
{
600-
struct futex_info *finfo;
601-
int i;
602-
603-
/* Affinitize to one CPU to force context switches */
604-
affinitize_cpu0();
605-
606-
req_xtiledata_perm();
607-
608-
printf("[RUN]\tCheck tiledata context switches, %d iterations, %d threads.\n",
609-
ctxtswtest_config.iterations,
610-
ctxtswtest_config.num_threads);
611-
612-
613-
finfo = malloc(sizeof(*finfo) * ctxtswtest_config.num_threads);
614-
if (!finfo)
615-
fatal_error("malloc()");
616-
617-
create_threads(ctxtswtest_config.num_threads, finfo);
618-
619-
/*
620-
* This thread wakes up thread 0
621-
* Thread 0 will wake up 1
622-
* Thread 1 will wake up 2
623-
* ...
624-
* the last thread will wake up 0
625-
*
626-
* ... this will repeat for the configured
627-
* number of iterations.
628-
*/
629-
pthread_mutex_unlock(&finfo[0].mutex);
630-
631-
/* Wait for all the threads to finish: */
632-
for (i = 0; i < ctxtswtest_config.num_threads; i++) {
633-
void *thread_retval;
634-
int rc;
635-
636-
rc = pthread_join(finfo[i].thread, &thread_retval);
637-
638-
if (rc)
639-
fatal_error("pthread_join() failed for thread %d err: %d\n",
640-
i, rc);
641-
642-
if (thread_retval != &finfo[i])
643-
fatal_error("unexpected thread retval for thread %d: %p\n",
644-
i, thread_retval);
645-
646-
}
647-
648-
printf("[OK]\tNo incorrect case was found.\n");
649-
650-
free(finfo);
651-
}
652-
653492
/* Ptrace test */
654493

655494
/*
@@ -745,6 +584,7 @@ static void test_ptrace(void)
745584

746585
int main(void)
747586
{
587+
const unsigned int ctxtsw_num_threads = 5, ctxtsw_iterations = 10;
748588
unsigned long features;
749589
long rc;
750590

@@ -772,9 +612,7 @@ int main(void)
772612

773613
test_fork();
774614

775-
ctxtswtest_config.iterations = 10;
776-
ctxtswtest_config.num_threads = 5;
777-
test_context_switch();
615+
test_context_switch(XFEATURE_XTILEDATA, ctxtsw_num_threads, ctxtsw_iterations);
778616

779617
test_ptrace();
780618

0 commit comments

Comments
 (0)