Skip to content

Commit e678769

Browse files
weihongzhansendc
authored andcommitted
selftests/x86/lam: Add mmap and SYSCALL test cases for linear-address masking
Add mmap and SYSCALL test cases. SYSCALL test cases: - LAM supports set metadata in high bits 62:57 (LAM_U57) of a user pointer, pass the pointer to SYSCALL, SYSCALL can dereference the pointer and return correct result. - Disable LAM, pass a pointer with metadata in high bits to SYSCALL, SYSCALL returns -1 (EFAULT). MMAP test cases: - Enable LAM_U57, MMAP with low address (below bits 47), set metadata in high bits of the address, dereference the address should be allowed. - Enable LAM_U57, MMAP with high address (above bits 47), set metadata in high bits of the address, dereference the address should be allowed. 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-14-kirill.shutemov%40linux.intel.com
1 parent 3de9745 commit e678769

1 file changed

Lines changed: 140 additions & 4 deletions

File tree

  • tools/testing/selftests/x86

tools/testing/selftests/x86/lam.c

Lines changed: 140 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
#include <signal.h>
88
#include <setjmp.h>
99
#include <sys/mman.h>
10+
#include <sys/utsname.h>
1011
#include <sys/wait.h>
1112
#include <inttypes.h>
1213

@@ -29,11 +30,18 @@
2930
/* Specified test function bits */
3031
#define FUNC_MALLOC 0x1
3132
#define FUNC_BITS 0x2
33+
#define FUNC_MMAP 0x4
34+
#define FUNC_SYSCALL 0x8
3235

33-
#define TEST_MASK 0x3
36+
#define TEST_MASK 0xf
37+
38+
#define LOW_ADDR (0x1UL << 30)
39+
#define HIGH_ADDR (0x3UL << 48)
3440

3541
#define MALLOC_LEN 32
3642

43+
#define PAGE_SIZE (4 << 10)
44+
3745
struct testcases {
3846
unsigned int later;
3947
int expected; /* 2: SIGSEGV Error; 1: other errors */
@@ -49,6 +57,7 @@ jmp_buf segv_env;
4957
static void segv_handler(int sig)
5058
{
5159
ksft_print_msg("Get segmentation fault(%d).", sig);
60+
5261
siglongjmp(segv_env, 1);
5362
}
5463

@@ -61,6 +70,16 @@ static inline int cpu_has_lam(void)
6170
return (cpuinfo[0] & (1 << 26));
6271
}
6372

73+
/* Check 5-level page table feature in CPUID.(EAX=07H, ECX=00H):ECX.[bit 16] */
74+
static inline int cpu_has_la57(void)
75+
{
76+
unsigned int cpuinfo[4];
77+
78+
__cpuid_count(0x7, 0, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
79+
80+
return (cpuinfo[2] & (1 << 16));
81+
}
82+
6483
/*
6584
* Set tagged address and read back untag mask.
6685
* check if the untagged mask is expected.
@@ -213,6 +232,68 @@ static int handle_malloc(struct testcases *test)
213232
return ret;
214233
}
215234

235+
static int handle_mmap(struct testcases *test)
236+
{
237+
void *ptr;
238+
unsigned int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
239+
int ret = 0;
240+
241+
if (test->later == 0 && test->lam != 0)
242+
if (set_lam(test->lam) != 0)
243+
return 1;
244+
245+
ptr = mmap((void *)test->addr, PAGE_SIZE, PROT_READ | PROT_WRITE,
246+
flags, -1, 0);
247+
if (ptr == MAP_FAILED) {
248+
if (test->addr == HIGH_ADDR)
249+
if (!cpu_has_la57())
250+
return 3; /* unsupport LA57 */
251+
return 1;
252+
}
253+
254+
if (test->later != 0 && test->lam != 0)
255+
if (set_lam(test->lam) != 0)
256+
ret = 1;
257+
258+
if (ret == 0) {
259+
if (sigsetjmp(segv_env, 1) == 0) {
260+
signal(SIGSEGV, segv_handler);
261+
ret = handle_lam_test(ptr, test->lam);
262+
} else {
263+
ret = 2;
264+
}
265+
}
266+
267+
munmap(ptr, PAGE_SIZE);
268+
return ret;
269+
}
270+
271+
static int handle_syscall(struct testcases *test)
272+
{
273+
struct utsname unme, *pu;
274+
int ret = 0;
275+
276+
if (test->later == 0 && test->lam != 0)
277+
if (set_lam(test->lam) != 0)
278+
return 1;
279+
280+
if (sigsetjmp(segv_env, 1) == 0) {
281+
signal(SIGSEGV, segv_handler);
282+
pu = (struct utsname *)set_metadata((uint64_t)&unme, test->lam);
283+
ret = uname(pu);
284+
if (ret < 0)
285+
ret = 1;
286+
} else {
287+
ret = 2;
288+
}
289+
290+
if (test->later != 0 && test->lam != 0)
291+
if (set_lam(test->lam) != -1 && ret == 0)
292+
ret = 1;
293+
294+
return ret;
295+
}
296+
216297
static int fork_test(struct testcases *test)
217298
{
218299
int ret, child_ret;
@@ -241,13 +322,20 @@ static void run_test(struct testcases *test, int count)
241322
struct testcases *t = test + i;
242323

243324
/* fork a process to run test case */
325+
tests_cnt++;
244326
ret = fork_test(t);
327+
328+
/* return 3 is not support LA57, the case should be skipped */
329+
if (ret == 3) {
330+
ksft_test_result_skip(t->msg);
331+
continue;
332+
}
333+
245334
if (ret != 0)
246335
ret = (t->expected == ret);
247336
else
248337
ret = !(t->expected);
249338

250-
tests_cnt++;
251339
ksft_test_result(ret, t->msg);
252340
}
253341
}
@@ -268,19 +356,61 @@ static struct testcases malloc_cases[] = {
268356
},
269357
};
270358

271-
272359
static struct testcases bits_cases[] = {
273360
{
274361
.test_func = handle_max_bits,
275362
.msg = "BITS: Check default tag bits\n",
276363
},
277364
};
278365

366+
static struct testcases syscall_cases[] = {
367+
{
368+
.later = 0,
369+
.lam = LAM_U57_BITS,
370+
.test_func = handle_syscall,
371+
.msg = "SYSCALL: LAM_U57. syscall with metadata\n",
372+
},
373+
{
374+
.later = 1,
375+
.expected = 1,
376+
.lam = LAM_U57_BITS,
377+
.test_func = handle_syscall,
378+
.msg = "SYSCALL:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
379+
},
380+
};
381+
382+
static struct testcases mmap_cases[] = {
383+
{
384+
.later = 1,
385+
.expected = 0,
386+
.lam = LAM_U57_BITS,
387+
.addr = HIGH_ADDR,
388+
.test_func = handle_mmap,
389+
.msg = "MMAP: First mmap high address, then set LAM_U57.\n",
390+
},
391+
{
392+
.later = 0,
393+
.expected = 0,
394+
.lam = LAM_U57_BITS,
395+
.addr = HIGH_ADDR,
396+
.test_func = handle_mmap,
397+
.msg = "MMAP: First LAM_U57, then High address.\n",
398+
},
399+
{
400+
.later = 0,
401+
.expected = 0,
402+
.lam = LAM_U57_BITS,
403+
.addr = LOW_ADDR,
404+
.test_func = handle_mmap,
405+
.msg = "MMAP: First LAM_U57, then Low address.\n",
406+
},
407+
};
408+
279409
static void cmd_help(void)
280410
{
281411
printf("usage: lam [-h] [-t test list]\n");
282412
printf("\t-t test list: run tests specified in the test list, default:0x%x\n", TEST_MASK);
283-
printf("\t\t0x1:malloc; 0x2:max_bits;\n");
413+
printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall.\n");
284414
printf("\t-h: help\n");
285415
}
286416

@@ -320,6 +450,12 @@ int main(int argc, char **argv)
320450
if (tests & FUNC_BITS)
321451
run_test(bits_cases, ARRAY_SIZE(bits_cases));
322452

453+
if (tests & FUNC_MMAP)
454+
run_test(mmap_cases, ARRAY_SIZE(mmap_cases));
455+
456+
if (tests & FUNC_SYSCALL)
457+
run_test(syscall_cases, ARRAY_SIZE(syscall_cases));
458+
323459
ksft_set_plan(tests_cnt);
324460

325461
return ksft_exit_pass();

0 commit comments

Comments
 (0)