> -----Original Message----- > From: Hu, Robert <robert.hu@xxxxxxxxx> > Sent: Friday, August 19, 2022 4:15 PM > To: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx>; Dave Hansen > <dave.hansen@xxxxxxxxxxxxxxx>; Lutomirski, Andy <luto@xxxxxxxxxx>; Peter > Zijlstra <peterz@xxxxxxxxxxxxx> > Cc: x86@xxxxxxxxxx; Kostya Serebryany <kcc@xxxxxxxxxx>; Andrey Ryabinin > <ryabinin.a.a@xxxxxxxxx>; Andrey Konovalov <andreyknvl@xxxxxxxxx>; > Alexander Potapenko <glider@xxxxxxxxxx>; Taras Madan > <tarasmadan@xxxxxxxxxx>; Dmitry Vyukov <dvyukov@xxxxxxxxxx>; H . J . > Lu <hjl.tools@xxxxxxxxx>; Andi Kleen <ak@xxxxxxxxxxxxxxx>; Edgecombe, > Rick P <rick.p.edgecombe@xxxxxxxxx>; linux-mm@xxxxxxxxx; linux- > kernel@xxxxxxxxxxxxxxx; Zhang, Weihong <weihong.zhang@xxxxxxxxx> > Subject: RE: [PATCHv6 09/11] selftests/x86/lam: Add mmap and SYSCALL test > cases for linear-address masking > > > -----Original Message----- > > From: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > > Sent: Monday, August 15, 2022 12:18 > > To: Dave Hansen <dave.hansen@xxxxxxxxxxxxxxx>; Lutomirski, Andy > > <luto@xxxxxxxxxx>; Peter Zijlstra <peterz@xxxxxxxxxxxxx> > > Cc: x86@xxxxxxxxxx; Kostya Serebryany <kcc@xxxxxxxxxx>; Andrey > > Ryabinin <ryabinin.a.a@xxxxxxxxx>; Andrey Konovalov > > <andreyknvl@xxxxxxxxx>; Alexander Potapenko <glider@xxxxxxxxxx>; > Taras > > Madan <tarasmadan@xxxxxxxxxx>; Dmitry Vyukov > <dvyukov@xxxxxxxxxx>; H . > > J . Lu <hjl.tools@xxxxxxxxx>; Andi Kleen <ak@xxxxxxxxxxxxxxx>; > > Edgecombe, Rick P <rick.p.edgecombe@xxxxxxxxx>; linux-mm@xxxxxxxxx; > > linux- kernel@xxxxxxxxxxxxxxx; Zhang, Weihong > <weihong.zhang@xxxxxxxxx>; Kirill A . > > Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > > Subject: [PATCHv6 09/11] selftests/x86/lam: Add mmap and SYSCALL test > > cases for linear-address masking > > > > From: Weihong Zhang <weihong.zhang@xxxxxxxxx> > > > > 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@xxxxxxxxx> > > Signed-off-by: Kirill A. Shutemov <kirill.shutemov@xxxxxxxxxxxxxxx> > > --- > > tools/testing/selftests/x86/lam.c | 135 > > +++++++++++++++++++++++++++++- > > 1 file changed, 132 insertions(+), 3 deletions(-) > > > > diff --git a/tools/testing/selftests/x86/lam.c > > b/tools/testing/selftests/x86/lam.c > > index 4c6c6dbf7db6..e9e92ab7fea8 100644 > > --- a/tools/testing/selftests/x86/lam.c > > +++ b/tools/testing/selftests/x86/lam.c > > @@ -7,6 +7,7 @@ > > #include <signal.h> > > #include <setjmp.h> > > #include <sys/mman.h> > > +#include <sys/utsname.h> > > #include <sys/wait.h> > > #include <inttypes.h> > > > > @@ -27,11 +28,18 @@ > > /* Specified test function bits */ > > #define FUNC_MALLOC 0x1 > > #define FUNC_BITS 0x2 > > +#define FUNC_MMAP 0x4 > > +#define FUNC_SYSCALL 0x8 > > > > -#define TEST_MASK 0x3 > > +#define TEST_MASK 0xf > > + > > +#define LOW_ADDR (0x1UL << 30) > > +#define HIGH_ADDR (0x3UL << 48) > > > > #define MALLOC_LEN 32 > > > > +#define PAGE_SIZE (4 << 10) > > + > > struct testcases { > > unsigned int later; > > int expected; /* 2: SIGSEGV Error; 1: other errors */ @@ -47,6 +55,7 > > @@ jmp_buf segv_env; static void segv_handler(int sig) { > > ksft_print_msg("Get segmentation fault(%d).", sig); > > + > > siglongjmp(segv_env, 1); > > } > > > > @@ -59,6 +68,16 @@ static inline int cpu_has_lam(void) > > return (cpuinfo[0] & (1 << 26)); > > } > > > > +/* Check 5-level page table feature in CPUID.(EAX=07H, > > +ECX=00H):ECX.[bit 16] */ static inline int cpu_has_la57(void) { > > + unsigned int cpuinfo[4]; > > + > > + __cpuid_count(0x7, 0, cpuinfo[0], cpuinfo[1], cpuinfo[2], > > +cpuinfo[3]); > > + > > + return (cpuinfo[2] & (1 << 16)); > > +} > > + > > /* > > * Set tagged address and read back untag mask. > > * check if the untagged mask is expected. > > @@ -204,6 +223,68 @@ static int handle_malloc(struct testcases *test) > > return ret; > > } > > > > +static int handle_mmap(struct testcases *test) { > > + void *ptr; > > + unsigned int flags = MAP_PRIVATE | MAP_ANONYMOUS | > MAP_FIXED; > > + int ret = 0; > > + > > + if (test->later == 0 && test->lam != 0) > > + if (set_lam(test->lam) != 0) > > + return 1; > > + > > + ptr = mmap((void *)test->addr, PAGE_SIZE, PROT_READ | > > PROT_WRITE, > > + flags, -1, 0); > > + if (ptr == MAP_FAILED) { > > + if (test->addr == HIGH_ADDR) > > + if (!cpu_has_la57()) > > + return 3; /* unsupport LA57 */ > > + return 1; > > + } > > + > > + if (test->later != 0 && test->lam != 0) > > + if (set_lam(test->lam) != 0) > > + ret = 1; > > + > > + if (ret == 0) { > > + if (sigsetjmp(segv_env, 1) == 0) { > > + signal(SIGSEGV, segv_handler); > > + ret = handle_lam_test(ptr, test->lam); > > + } else { > > + ret = 2; > > + } > > + } > > + > > + munmap(ptr, PAGE_SIZE); > > + return ret; > > +} > > + > > +static int handle_syscall(struct testcases *test) { > > + struct utsname unme, *pu; > > + int ret = 0; > > + > > + if (test->later == 0 && test->lam != 0) > > + if (set_lam(test->lam) != 0) > > + return 1; > > + > > + if (sigsetjmp(segv_env, 1) == 0) { > > + signal(SIGSEGV, segv_handler); > > + pu = (struct utsname *)get_metadata((uint64_t)&unme, > test- > > >lam); > > + ret = uname(pu); > > + if (ret < 0) > > + ret = 1; > > + } else { > > + ret = 2; > > + } > > + > > + if (test->later != 0 && test->lam != 0) > > + if (set_lam(test->lam) != -1 && ret == 0) > > + ret = 1; > > + > > + return ret; > > +} > > + > > static int fork_test(struct testcases *test) { > > int ret, child_ret; > > @@ -259,7 +340,6 @@ static struct testcases malloc_cases[] = { > > }, > > }; > > > > - > > static struct testcases bits_cases[] = { > > { > > .test_func = handle_max_bits, > > @@ -267,11 +347,54 @@ static struct testcases bits_cases[] = { > > }, > > }; > > > > +static struct testcases syscall_cases[] = { > > + { > > + .later = 0, > > + .lam = LAM_U57_BITS, > > + .test_func = handle_syscall, > > + .msg = "SYSCALL: LAM_U57. syscall with metadata\n", > > + }, > > + { > > + .later = 1, > > + .expected = 1, > > + .lam = LAM_U57_BITS, > > + .test_func = handle_syscall, > > + .msg = "SYSCALL:[Negtive] Disable LAM. Dereferencing > pointer > [Hu, Robert] > Trivial, Negtive --> Negative. > Thanks, will fix the typo. > > with metadata.\n", > > + }, > > +}; > > + > > +static struct testcases mmap_cases[] = { > [Hu, Robert] > Can mmap also have negative case? > Mmap just get a pointer. under U57 mode, negative case for mmap can refer to malloc cases. > > + { > > + .later = 1, > > + .expected = 0, > > + .lam = LAM_U57_BITS, > > + .addr = HIGH_ADDR, > > + .test_func = handle_mmap, > > + .msg = "MMAP: First mmap high address, then set > > LAM_U57.\n", > > + }, > > + { > > + .later = 0, > > + .expected = 0, > > + .lam = LAM_U57_BITS, > > + .addr = HIGH_ADDR, > > + .test_func = handle_mmap, > > + .msg = "MMAP: First LAM_U57, then High address.\n", > > + }, > > + { > > + .later = 0, > > + .expected = 0, > > + .lam = LAM_U57_BITS, > > + .addr = LOW_ADDR, > > + .test_func = handle_mmap, > > + .msg = "MMAP: First LAM_U57, then Low address.\n", > > + }, > > +}; > > + > > static void cmd_help(void) > > { > > printf("usage: lam [-h] [-t test list]\n"); > > printf("\t-t test list: run tests specified in the test list, > > default:0x%x\n", TEST_MASK); > > - printf("\t\t0x1:malloc; 0x2:max_bits;\n"); > > + printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall.\n"); > > printf("\t-h: help\n"); > > } > > > > @@ -311,6 +434,12 @@ int main(int argc, char **argv) > > if (tests & FUNC_BITS) > > run_test(bits_cases, ARRAY_SIZE(bits_cases)); > > > > + if (tests & FUNC_MMAP) > > + run_test(mmap_cases, ARRAY_SIZE(mmap_cases)); > > + > > + if (tests & FUNC_SYSCALL) > > + run_test(syscall_cases, ARRAY_SIZE(syscall_cases)); > > + > > ksft_set_plan(tests_cnt); > > > > return ksft_exit_pass(); > > -- > > 2.35.1