Skip to content

Commit 833c12c

Browse files
weihongzhansendc
authored andcommitted
selftests/x86/lam: Add inherit test cases for linear-address masking
LAM is enabled per-thread and gets inherited on fork(2)/clone(2). exec() reverts LAM status to the default disabled state. There are two test scenarios: - Fork test cases: These cases were used to test the inheritance of LAM for per-thread, Child process generated by fork() should inherit LAM feature from parent process, Child process can get the LAM mode same as parent process. - Execve test cases: Processes generated by execve() are different from processes generated by fork(), these processes revert LAM status to disabled status. Signed-off-by: Weihong Zhang <weihong.zhang@intel.com> Signed-off-by: Kirill A. Shutemov <kirill.shutemov@linux.intel.com> Signed-off-by: Dave Hansen <dave.hansen@linux.intel.com> Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org> Link: https://lore.kernel.org/all/20230312112612.31869-16-kirill.shutemov%40linux.intel.com
1 parent 72fd6d7 commit 833c12c

1 file changed

Lines changed: 121 additions & 4 deletions

File tree

  • tools/testing/selftests/x86

tools/testing/selftests/x86/lam.c

Lines changed: 121 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,9 @@
3737
#define FUNC_MMAP 0x4
3838
#define FUNC_SYSCALL 0x8
3939
#define FUNC_URING 0x10
40+
#define FUNC_INHERITE 0x20
4041

41-
#define TEST_MASK 0x1f
42+
#define TEST_MASK 0x3f
4243

4344
#define LOW_ADDR (0x1UL << 30)
4445
#define HIGH_ADDR (0x3UL << 48)
@@ -174,6 +175,28 @@ static unsigned long get_default_tag_bits(void)
174175
return lam;
175176
}
176177

178+
/*
179+
* Set tagged address and read back untag mask.
180+
* check if the untag mask is expected.
181+
*/
182+
static int get_lam(void)
183+
{
184+
uint64_t ptr = 0;
185+
int ret = -1;
186+
/* Get untagged mask */
187+
if (syscall(SYS_arch_prctl, ARCH_GET_UNTAG_MASK, &ptr) == -1)
188+
return -1;
189+
190+
/* Check mask returned is expected */
191+
if (ptr == ~(LAM_U57_MASK))
192+
ret = LAM_U57_BITS;
193+
else if (ptr == -1ULL)
194+
ret = LAM_NONE;
195+
196+
197+
return ret;
198+
}
199+
177200
/* According to LAM mode, set metadata in high bits */
178201
static uint64_t set_metadata(uint64_t src, unsigned long lam)
179202
{
@@ -581,7 +604,7 @@ int do_uring(unsigned long lam)
581604

582605
switch (lam) {
583606
case LAM_U57_BITS: /* Clear bits 62:57 */
584-
addr = (addr & ~(0x3fULL << 57));
607+
addr = (addr & ~(LAM_U57_MASK));
585608
break;
586609
}
587610
free((void *)addr);
@@ -632,6 +655,72 @@ static int fork_test(struct testcases *test)
632655
return ret;
633656
}
634657

658+
static int handle_execve(struct testcases *test)
659+
{
660+
int ret, child_ret;
661+
int lam = test->lam;
662+
pid_t pid;
663+
664+
pid = fork();
665+
if (pid < 0) {
666+
perror("Fork failed.");
667+
ret = 1;
668+
} else if (pid == 0) {
669+
char path[PATH_MAX];
670+
671+
/* Set LAM mode in parent process */
672+
if (set_lam(lam) != 0)
673+
return 1;
674+
675+
/* Get current binary's path and the binary was run by execve */
676+
if (readlink("/proc/self/exe", path, PATH_MAX) <= 0)
677+
exit(-1);
678+
679+
/* run binary to get LAM mode and return to parent process */
680+
if (execlp(path, path, "-t 0x0", NULL) < 0) {
681+
perror("error on exec");
682+
exit(-1);
683+
}
684+
} else {
685+
wait(&child_ret);
686+
ret = WEXITSTATUS(child_ret);
687+
if (ret != LAM_NONE)
688+
return 1;
689+
}
690+
691+
return 0;
692+
}
693+
694+
static int handle_inheritance(struct testcases *test)
695+
{
696+
int ret, child_ret;
697+
int lam = test->lam;
698+
pid_t pid;
699+
700+
/* Set LAM mode in parent process */
701+
if (set_lam(lam) != 0)
702+
return 1;
703+
704+
pid = fork();
705+
if (pid < 0) {
706+
perror("Fork failed.");
707+
return 1;
708+
} else if (pid == 0) {
709+
/* Set LAM mode in parent process */
710+
int child_lam = get_lam();
711+
712+
exit(child_lam);
713+
} else {
714+
wait(&child_ret);
715+
ret = WEXITSTATUS(child_ret);
716+
717+
if (lam != ret)
718+
return 1;
719+
}
720+
721+
return 0;
722+
}
723+
635724
static void run_test(struct testcases *test, int count)
636725
{
637726
int i, ret = 0;
@@ -740,11 +829,26 @@ static struct testcases mmap_cases[] = {
740829
},
741830
};
742831

832+
static struct testcases inheritance_cases[] = {
833+
{
834+
.expected = 0,
835+
.lam = LAM_U57_BITS,
836+
.test_func = handle_inheritance,
837+
.msg = "FORK: LAM_U57, child process should get LAM mode same as parent\n",
838+
},
839+
{
840+
.expected = 0,
841+
.lam = LAM_U57_BITS,
842+
.test_func = handle_execve,
843+
.msg = "EXECVE: LAM_U57, child process should get disabled LAM mode\n",
844+
},
845+
};
846+
743847
static void cmd_help(void)
744848
{
745849
printf("usage: lam [-h] [-t test list]\n");
746850
printf("\t-t test list: run tests specified in the test list, default:0x%x\n", TEST_MASK);
747-
printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall; 0x10:io_uring.\n");
851+
printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall; 0x10:io_uring; 0x20:inherit;\n");
748852
printf("\t-h: help\n");
749853
}
750854

@@ -764,7 +868,7 @@ int main(int argc, char **argv)
764868
switch (c) {
765869
case 't':
766870
tests = strtoul(optarg, NULL, 16);
767-
if (!(tests & TEST_MASK)) {
871+
if (tests && !(tests & TEST_MASK)) {
768872
ksft_print_msg("Invalid argument!\n");
769873
return -1;
770874
}
@@ -778,6 +882,16 @@ int main(int argc, char **argv)
778882
}
779883
}
780884

885+
/*
886+
* When tests is 0, it is not a real test case;
887+
* the option used by test case(execve) to check the lam mode in
888+
* process generated by execve, the process read back lam mode and
889+
* check with lam mode in parent process.
890+
*/
891+
if (!tests)
892+
return (get_lam());
893+
894+
/* Run test cases */
781895
if (tests & FUNC_MALLOC)
782896
run_test(malloc_cases, ARRAY_SIZE(malloc_cases));
783897

@@ -793,6 +907,9 @@ int main(int argc, char **argv)
793907
if (tests & FUNC_URING)
794908
run_test(uring_cases, ARRAY_SIZE(uring_cases));
795909

910+
if (tests & FUNC_INHERITE)
911+
run_test(inheritance_cases, ARRAY_SIZE(inheritance_cases));
912+
796913
ksft_set_plan(tests_cnt);
797914

798915
return ksft_exit_pass();

0 commit comments

Comments
 (0)