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
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+
3745struct testcases {
3846 unsigned int later ;
3947 int expected ; /* 2: SIGSEGV Error; 1: other errors */
@@ -49,6 +57,7 @@ jmp_buf segv_env;
4957static 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+
216297static 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-
272359static 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+
279409static 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