1 // SPDX-License-Identifier: GPL-2.0
6 #include <sys/syscall.h>
11 #include <sys/utsname.h>
19 #include <linux/io_uring.h>
20 #include "../kselftest.h"
23 # error This test is 64-bit only
26 /* LAM modes, these definitions were copied from kernel code */
28 #define LAM_U57_BITS 6
30 #define LAM_U57_MASK (0x3fULL << 57)
31 /* arch prctl for LAM */
32 #define ARCH_GET_UNTAG_MASK 0x4001
33 #define ARCH_ENABLE_TAGGED_ADDR 0x4002
34 #define ARCH_GET_MAX_TAG_BITS 0x4003
35 #define ARCH_FORCE_TAGGED_SVA 0x4004
37 /* Specified test function bits */
38 #define FUNC_MALLOC 0x1
41 #define FUNC_SYSCALL 0x8
42 #define FUNC_URING 0x10
43 #define FUNC_INHERITE 0x20
44 #define FUNC_PASID 0x40
46 #define TEST_MASK 0x7f
48 #define LOW_ADDR (0x1UL << 30)
49 #define HIGH_ADDR (0x3UL << 48)
53 #define PAGE_SIZE (4 << 10)
55 #define STACK_SIZE 65536
57 #define barrier() ({ \
58 __asm__ __volatile__("" : : : "memory"); \
61 #define URING_QUEUE_SZ 1
62 #define URING_BLOCK_SZ 2048
64 /* Pasid test define */
65 #define LAM_CMD_BIT 0x1
66 #define PAS_CMD_BIT 0x2
67 #define SVA_CMD_BIT 0x4
69 #define PAS_CMD(cmd1, cmd2, cmd3) (((cmd3) << 8) | ((cmd2) << 4) | ((cmd1) << 0))
73 int expected
; /* 2: SIGSEGV Error; 1: other errors */
77 int (*test_func
)(struct testcases
*test
);
81 /* Used by CQ of uring, source file handler and file's size */
85 struct iovec iovecs
[];
88 struct io_uring_queue
{
91 unsigned int *ring_mask
;
92 unsigned int *ring_entries
;
96 struct io_uring_cqe
*cqes
;
97 struct io_uring_sqe
*sqes
;
104 struct io_uring_queue sq_ring
;
105 struct io_uring_queue cq_ring
;
111 static void segv_handler(int sig
)
113 ksft_print_msg("Get segmentation fault(%d).", sig
);
115 siglongjmp(segv_env
, 1);
118 static inline int cpu_has_lam(void)
120 unsigned int cpuinfo
[4];
122 __cpuid_count(0x7, 1, cpuinfo
[0], cpuinfo
[1], cpuinfo
[2], cpuinfo
[3]);
124 return (cpuinfo
[0] & (1 << 26));
127 /* Check 5-level page table feature in CPUID.(EAX=07H, ECX=00H):ECX.[bit 16] */
128 static inline int cpu_has_la57(void)
130 unsigned int cpuinfo
[4];
132 __cpuid_count(0x7, 0, cpuinfo
[0], cpuinfo
[1], cpuinfo
[2], cpuinfo
[3]);
134 return (cpuinfo
[2] & (1 << 16));
138 * Set tagged address and read back untag mask.
139 * check if the untagged mask is expected.
142 * 0: Set LAM mode successfully
143 * others: failed to set LAM
145 static int set_lam(unsigned long lam
)
150 if (lam
!= LAM_U57_BITS
&& lam
!= LAM_NONE
)
153 /* Skip check return */
154 syscall(SYS_arch_prctl
, ARCH_ENABLE_TAGGED_ADDR
, lam
);
156 /* Get untagged mask */
157 syscall(SYS_arch_prctl
, ARCH_GET_UNTAG_MASK
, &ptr
);
159 /* Check mask returned is expected */
160 if (lam
== LAM_U57_BITS
)
161 ret
= (ptr
!= ~(LAM_U57_MASK
));
162 else if (lam
== LAM_NONE
)
163 ret
= (ptr
!= -1ULL);
168 static unsigned long get_default_tag_bits(void)
176 perror("Fork failed.");
177 } else if (pid
== 0) {
178 /* Set LAM mode in child process */
179 if (set_lam(LAM_U57_BITS
) == 0)
186 lam
= WEXITSTATUS(ret
);
193 * Set tagged address and read back untag mask.
194 * check if the untag mask is expected.
196 static int get_lam(void)
200 /* Get untagged mask */
201 if (syscall(SYS_arch_prctl
, ARCH_GET_UNTAG_MASK
, &ptr
) == -1)
204 /* Check mask returned is expected */
205 if (ptr
== ~(LAM_U57_MASK
))
207 else if (ptr
== -1ULL)
214 /* According to LAM mode, set metadata in high bits */
215 static uint64_t set_metadata(uint64_t src
, unsigned long lam
)
222 case LAM_U57_BITS
: /* Set metadata in bits 62:57 */
223 /* Get a random non-zero value as metadata */
224 metadata
= (rand() % ((1UL << LAM_U57_BITS
) - 1) + 1) << 57;
225 metadata
|= (src
& ~(LAM_U57_MASK
));
236 * Set metadata in user pointer, compare new pointer with original pointer.
237 * both pointers should point to the same address.
240 * 0: value on the pointer with metadate and value on original are same
243 static int handle_lam_test(void *src
, unsigned int lam
)
247 strcpy((char *)src
, "USER POINTER");
249 ptr
= (char *)set_metadata((uint64_t)src
, lam
);
253 /* Copy a string into the pointer with metadata */
254 strcpy((char *)ptr
, "METADATA POINTER");
256 return (!!strcmp((char *)src
, (char *)ptr
));
260 int handle_max_bits(struct testcases
*test
)
262 unsigned long exp_bits
= get_default_tag_bits();
263 unsigned long bits
= 0;
265 if (exp_bits
!= LAM_NONE
)
266 exp_bits
= LAM_U57_BITS
;
268 /* Get LAM max tag bits */
269 if (syscall(SYS_arch_prctl
, ARCH_GET_MAX_TAG_BITS
, &bits
) == -1)
272 return (exp_bits
!= bits
);
276 * Test lam feature through dereference pointer get from malloc.
277 * @return 0: Pass test. 1: Get failure during test 2: Get SIGSEGV
279 static int handle_malloc(struct testcases
*test
)
284 if (test
->later
== 0 && test
->lam
!= 0)
285 if (set_lam(test
->lam
) == -1)
288 ptr
= (char *)malloc(MALLOC_LEN
);
290 perror("malloc() failure\n");
294 /* Set signal handler */
295 if (sigsetjmp(segv_env
, 1) == 0) {
296 signal(SIGSEGV
, segv_handler
);
297 ret
= handle_lam_test(ptr
, test
->lam
);
302 if (test
->later
!= 0 && test
->lam
!= 0)
303 if (set_lam(test
->lam
) == -1 && ret
== 0)
311 static int handle_mmap(struct testcases
*test
)
314 unsigned int flags
= MAP_PRIVATE
| MAP_ANONYMOUS
| MAP_FIXED
;
317 if (test
->later
== 0 && test
->lam
!= 0)
318 if (set_lam(test
->lam
) != 0)
321 ptr
= mmap((void *)test
->addr
, PAGE_SIZE
, PROT_READ
| PROT_WRITE
,
323 if (ptr
== MAP_FAILED
) {
324 if (test
->addr
== HIGH_ADDR
)
326 return 3; /* unsupport LA57 */
330 if (test
->later
!= 0 && test
->lam
!= 0)
331 if (set_lam(test
->lam
) != 0)
335 if (sigsetjmp(segv_env
, 1) == 0) {
336 signal(SIGSEGV
, segv_handler
);
337 ret
= handle_lam_test(ptr
, test
->lam
);
343 munmap(ptr
, PAGE_SIZE
);
347 static int handle_syscall(struct testcases
*test
)
349 struct utsname unme
, *pu
;
352 if (test
->later
== 0 && test
->lam
!= 0)
353 if (set_lam(test
->lam
) != 0)
356 if (sigsetjmp(segv_env
, 1) == 0) {
357 signal(SIGSEGV
, segv_handler
);
358 pu
= (struct utsname
*)set_metadata((uint64_t)&unme
, test
->lam
);
366 if (test
->later
!= 0 && test
->lam
!= 0)
367 if (set_lam(test
->lam
) != -1 && ret
== 0)
373 int sys_uring_setup(unsigned int entries
, struct io_uring_params
*p
)
375 return (int)syscall(__NR_io_uring_setup
, entries
, p
);
378 int sys_uring_enter(int fd
, unsigned int to
, unsigned int min
, unsigned int flags
)
380 return (int)syscall(__NR_io_uring_enter
, fd
, to
, min
, flags
, NULL
, 0);
383 /* Init submission queue and completion queue */
384 int mmap_io_uring(struct io_uring_params p
, struct io_ring
*s
)
386 struct io_uring_queue
*sring
= &s
->sq_ring
;
387 struct io_uring_queue
*cring
= &s
->cq_ring
;
389 sring
->ring_sz
= p
.sq_off
.array
+ p
.sq_entries
* sizeof(unsigned int);
390 cring
->ring_sz
= p
.cq_off
.cqes
+ p
.cq_entries
* sizeof(struct io_uring_cqe
);
392 if (p
.features
& IORING_FEAT_SINGLE_MMAP
) {
393 if (cring
->ring_sz
> sring
->ring_sz
)
394 sring
->ring_sz
= cring
->ring_sz
;
396 cring
->ring_sz
= sring
->ring_sz
;
399 void *sq_ptr
= mmap(0, sring
->ring_sz
, PROT_READ
| PROT_WRITE
,
400 MAP_SHARED
| MAP_POPULATE
, s
->ring_fd
,
403 if (sq_ptr
== MAP_FAILED
) {
404 perror("sub-queue!");
408 void *cq_ptr
= sq_ptr
;
410 if (!(p
.features
& IORING_FEAT_SINGLE_MMAP
)) {
411 cq_ptr
= mmap(0, cring
->ring_sz
, PROT_READ
| PROT_WRITE
,
412 MAP_SHARED
| MAP_POPULATE
, s
->ring_fd
,
414 if (cq_ptr
== MAP_FAILED
) {
415 perror("cpl-queue!");
416 munmap(sq_ptr
, sring
->ring_sz
);
421 sring
->head
= sq_ptr
+ p
.sq_off
.head
;
422 sring
->tail
= sq_ptr
+ p
.sq_off
.tail
;
423 sring
->ring_mask
= sq_ptr
+ p
.sq_off
.ring_mask
;
424 sring
->ring_entries
= sq_ptr
+ p
.sq_off
.ring_entries
;
425 sring
->flags
= sq_ptr
+ p
.sq_off
.flags
;
426 sring
->array
= sq_ptr
+ p
.sq_off
.array
;
428 /* Map a queue as mem map */
429 s
->sq_ring
.queue
.sqes
= mmap(0, p
.sq_entries
* sizeof(struct io_uring_sqe
),
430 PROT_READ
| PROT_WRITE
, MAP_SHARED
| MAP_POPULATE
,
431 s
->ring_fd
, IORING_OFF_SQES
);
432 if (s
->sq_ring
.queue
.sqes
== MAP_FAILED
) {
433 munmap(sq_ptr
, sring
->ring_sz
);
434 if (sq_ptr
!= cq_ptr
) {
435 ksft_print_msg("failed to mmap uring queue!");
436 munmap(cq_ptr
, cring
->ring_sz
);
441 cring
->head
= cq_ptr
+ p
.cq_off
.head
;
442 cring
->tail
= cq_ptr
+ p
.cq_off
.tail
;
443 cring
->ring_mask
= cq_ptr
+ p
.cq_off
.ring_mask
;
444 cring
->ring_entries
= cq_ptr
+ p
.cq_off
.ring_entries
;
445 cring
->queue
.cqes
= cq_ptr
+ p
.cq_off
.cqes
;
450 /* Init io_uring queues */
451 int setup_io_uring(struct io_ring
*s
)
453 struct io_uring_params para
;
455 memset(¶
, 0, sizeof(para
));
456 s
->ring_fd
= sys_uring_setup(URING_QUEUE_SZ
, ¶
);
460 return mmap_io_uring(para
, s
);
464 * Get data from completion queue. the data buffer saved the file data
465 * return 0: success; others: error;
467 int handle_uring_cq(struct io_ring
*s
)
469 struct file_io
*fi
= NULL
;
470 struct io_uring_queue
*cring
= &s
->cq_ring
;
471 struct io_uring_cqe
*cqe
;
479 if (head
== *cring
->tail
)
482 cqe
= &cring
->queue
.cqes
[head
& *s
->cq_ring
.ring_mask
];
483 fi
= (struct file_io
*)cqe
->user_data
;
487 int blocks
= (int)(fi
->file_sz
+ URING_BLOCK_SZ
- 1) / URING_BLOCK_SZ
;
489 for (int i
= 0; i
< blocks
; i
++)
490 len
+= fi
->iovecs
[i
].iov_len
;
498 return (len
!= fi
->file_sz
);
502 * Submit squeue. specify via IORING_OP_READV.
503 * the buffer need to be set metadata according to LAM mode
505 int handle_uring_sq(struct io_ring
*ring
, struct file_io
*fi
, unsigned long lam
)
507 int file_fd
= fi
->file_fd
;
508 struct io_uring_queue
*sring
= &ring
->sq_ring
;
509 unsigned int index
= 0, cur_block
= 0, tail
= 0, next_tail
= 0;
510 struct io_uring_sqe
*sqe
;
512 off_t remain
= fi
->file_sz
;
513 int blocks
= (int)(remain
+ URING_BLOCK_SZ
- 1) / URING_BLOCK_SZ
;
516 off_t bytes
= remain
;
519 if (bytes
> URING_BLOCK_SZ
)
520 bytes
= URING_BLOCK_SZ
;
522 fi
->iovecs
[cur_block
].iov_len
= bytes
;
524 if (posix_memalign(&buf
, URING_BLOCK_SZ
, URING_BLOCK_SZ
))
527 fi
->iovecs
[cur_block
].iov_base
= (void *)set_metadata((uint64_t)buf
, lam
);
532 next_tail
= *sring
->tail
;
538 index
= tail
& *ring
->sq_ring
.ring_mask
;
540 sqe
= &ring
->sq_ring
.queue
.sqes
[index
];
543 sqe
->opcode
= IORING_OP_READV
;
544 sqe
->addr
= (unsigned long)fi
->iovecs
;
547 sqe
->user_data
= (uint64_t)fi
;
549 sring
->array
[index
] = index
;
552 if (*sring
->tail
!= tail
) {
557 if (sys_uring_enter(ring
->ring_fd
, 1, 1, IORING_ENTER_GETEVENTS
) < 0)
564 * Test LAM in async I/O and io_uring, read current binery through io_uring
565 * Set metadata in pointers to iovecs buffer.
567 int do_uring(unsigned long lam
)
569 struct io_ring
*ring
;
573 char path
[PATH_MAX
] = {0};
575 /* get current process path */
576 if (readlink("/proc/self/exe", path
, PATH_MAX
- 1) <= 0)
579 int file_fd
= open(path
, O_RDONLY
);
584 if (fstat(file_fd
, &st
) < 0)
587 off_t file_sz
= st
.st_size
;
589 int blocks
= (int)(file_sz
+ URING_BLOCK_SZ
- 1) / URING_BLOCK_SZ
;
591 fi
= malloc(sizeof(*fi
) + sizeof(struct iovec
) * blocks
);
595 fi
->file_sz
= file_sz
;
596 fi
->file_fd
= file_fd
;
598 ring
= malloc(sizeof(*ring
));
602 memset(ring
, 0, sizeof(struct io_ring
));
604 if (setup_io_uring(ring
))
607 if (handle_uring_sq(ring
, fi
, lam
))
610 ret
= handle_uring_cq(ring
);
615 for (int i
= 0; i
< blocks
; i
++) {
616 if (fi
->iovecs
[i
].iov_base
) {
617 uint64_t addr
= ((uint64_t)fi
->iovecs
[i
].iov_base
);
620 case LAM_U57_BITS
: /* Clear bits 62:57 */
621 addr
= (addr
& ~(LAM_U57_MASK
));
625 fi
->iovecs
[i
].iov_base
= NULL
;
634 int handle_uring(struct testcases
*test
)
638 if (test
->later
== 0 && test
->lam
!= 0)
639 if (set_lam(test
->lam
) != 0)
642 if (sigsetjmp(segv_env
, 1) == 0) {
643 signal(SIGSEGV
, segv_handler
);
644 ret
= do_uring(test
->lam
);
652 static int fork_test(struct testcases
*test
)
659 perror("Fork failed.");
661 } else if (pid
== 0) {
662 ret
= test
->test_func(test
);
666 ret
= WEXITSTATUS(child_ret
);
672 static int handle_execve(struct testcases
*test
)
680 perror("Fork failed.");
682 } else if (pid
== 0) {
683 char path
[PATH_MAX
] = {0};
685 /* Set LAM mode in parent process */
686 if (set_lam(lam
) != 0)
689 /* Get current binary's path and the binary was run by execve */
690 if (readlink("/proc/self/exe", path
, PATH_MAX
- 1) <= 0)
693 /* run binary to get LAM mode and return to parent process */
694 if (execlp(path
, path
, "-t 0x0", NULL
) < 0) {
695 perror("error on exec");
700 ret
= WEXITSTATUS(child_ret
);
708 static int handle_inheritance(struct testcases
*test
)
714 /* Set LAM mode in parent process */
715 if (set_lam(lam
) != 0)
720 perror("Fork failed.");
722 } else if (pid
== 0) {
723 /* Set LAM mode in parent process */
724 int child_lam
= get_lam();
729 ret
= WEXITSTATUS(child_ret
);
738 static int thread_fn_get_lam(void *arg
)
743 static int thread_fn_set_lam(void *arg
)
745 struct testcases
*test
= arg
;
747 return set_lam(test
->lam
);
750 static int handle_thread(struct testcases
*test
)
752 char stack
[STACK_SIZE
];
757 /* Set LAM mode in parent process */
760 if (set_lam(lam
) != 0)
764 pid
= clone(thread_fn_get_lam
, stack
+ STACK_SIZE
,
765 SIGCHLD
| CLONE_FILES
| CLONE_FS
| CLONE_VM
, NULL
);
767 perror("Clone failed.");
771 waitpid(pid
, &child_ret
, 0);
772 ret
= WEXITSTATUS(child_ret
);
778 if (set_lam(test
->lam
) != 0)
785 static int handle_thread_enable(struct testcases
*test
)
787 char stack
[STACK_SIZE
];
792 pid
= clone(thread_fn_set_lam
, stack
+ STACK_SIZE
,
793 SIGCHLD
| CLONE_FILES
| CLONE_FS
| CLONE_VM
, test
);
795 perror("Clone failed.");
799 waitpid(pid
, &child_ret
, 0);
800 ret
= WEXITSTATUS(child_ret
);
807 static void run_test(struct testcases
*test
, int count
)
811 for (i
= 0; i
< count
; i
++) {
812 struct testcases
*t
= test
+ i
;
814 /* fork a process to run test case */
818 /* return 3 is not support LA57, the case should be skipped */
820 ksft_test_result_skip("%s", t
->msg
);
825 ret
= (t
->expected
== ret
);
827 ret
= !(t
->expected
);
829 ksft_test_result(ret
, "%s", t
->msg
);
833 static struct testcases uring_cases
[] = {
837 .test_func
= handle_uring
,
838 .msg
= "URING: LAM_U57. Dereferencing pointer with metadata\n",
844 .test_func
= handle_uring
,
845 .msg
= "URING:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
849 static struct testcases malloc_cases
[] = {
853 .test_func
= handle_malloc
,
854 .msg
= "MALLOC: LAM_U57. Dereferencing pointer with metadata\n",
860 .test_func
= handle_malloc
,
861 .msg
= "MALLOC:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
865 static struct testcases bits_cases
[] = {
867 .test_func
= handle_max_bits
,
868 .msg
= "BITS: Check default tag bits\n",
872 static struct testcases syscall_cases
[] = {
876 .test_func
= handle_syscall
,
877 .msg
= "SYSCALL: LAM_U57. syscall with metadata\n",
883 .test_func
= handle_syscall
,
884 .msg
= "SYSCALL:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
888 static struct testcases mmap_cases
[] = {
894 .test_func
= handle_mmap
,
895 .msg
= "MMAP: First mmap high address, then set LAM_U57.\n",
902 .test_func
= handle_mmap
,
903 .msg
= "MMAP: First LAM_U57, then High address.\n",
910 .test_func
= handle_mmap
,
911 .msg
= "MMAP: First LAM_U57, then Low address.\n",
915 static struct testcases inheritance_cases
[] = {
919 .test_func
= handle_inheritance
,
920 .msg
= "FORK: LAM_U57, child process should get LAM mode same as parent\n",
925 .test_func
= handle_thread
,
926 .msg
= "THREAD: LAM_U57, child thread should get LAM mode same as parent\n",
931 .test_func
= handle_thread_enable
,
932 .msg
= "THREAD: [NEGATIVE] Enable LAM in child.\n",
938 .test_func
= handle_thread
,
939 .msg
= "THREAD: [NEGATIVE] Enable LAM in parent after thread created.\n",
944 .test_func
= handle_execve
,
945 .msg
= "EXECVE: LAM_U57, child process should get disabled LAM mode\n",
949 static void cmd_help(void)
951 printf("usage: lam [-h] [-t test list]\n");
952 printf("\t-t test list: run tests specified in the test list, default:0x%x\n", TEST_MASK
);
953 printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall; 0x10:io_uring; 0x20:inherit;\n");
954 printf("\t-h: help\n");
957 /* Check for file existence */
958 uint8_t file_Exists(const char *fileName
)
962 uint8_t ret
= (stat(fileName
, &buffer
) == 0);
967 /* Sysfs idxd files */
968 const char *dsa_configs
[] = {
969 "echo 1 > /sys/bus/dsa/devices/dsa0/wq0.1/group_id",
970 "echo shared > /sys/bus/dsa/devices/dsa0/wq0.1/mode",
971 "echo 10 > /sys/bus/dsa/devices/dsa0/wq0.1/priority",
972 "echo 16 > /sys/bus/dsa/devices/dsa0/wq0.1/size",
973 "echo 15 > /sys/bus/dsa/devices/dsa0/wq0.1/threshold",
974 "echo user > /sys/bus/dsa/devices/dsa0/wq0.1/type",
975 "echo MyApp1 > /sys/bus/dsa/devices/dsa0/wq0.1/name",
976 "echo 1 > /sys/bus/dsa/devices/dsa0/engine0.1/group_id",
977 "echo dsa0 > /sys/bus/dsa/drivers/idxd/bind",
978 /* bind files and devices, generated a device file in /dev */
979 "echo wq0.1 > /sys/bus/dsa/drivers/user/bind",
982 /* DSA device file */
983 const char *dsaDeviceFile
= "/dev/dsa/wq0.1";
985 const char *dsaPasidEnable
= "/sys/bus/dsa/devices/dsa0/pasid_enabled";
988 * DSA depends on kernel cmdline "intel_iommu=on,sm_on"
989 * return pasid_enabled (0: disable 1:enable)
991 int Check_DSA_Kernel_Setting(void)
993 char command
[256] = "";
998 snprintf(command
, sizeof(command
) - 1, "cat %s", dsaPasidEnable
);
1000 FILE *cmd
= popen(command
, "r");
1003 while (fgets(buf
, sizeof(buf
) - 1, cmd
) != NULL
);
1006 rv
= strtol(buf
, &ptr
, 16);
1013 * Config DSA's sysfs files as shared DSA's WQ.
1014 * Generated a device file /dev/dsa/wq0.1
1015 * Return: 0 OK; 1 Failed; 3 Skip(SVA disabled).
1017 int Dsa_Init_Sysfs(void)
1019 uint len
= ARRAY_SIZE(dsa_configs
);
1020 const char **p
= dsa_configs
;
1022 if (file_Exists(dsaDeviceFile
) == 1)
1025 /* check the idxd driver */
1026 if (file_Exists(dsaPasidEnable
) != 1) {
1027 printf("Please make sure idxd driver was loaded\n");
1031 /* Check SVA feature */
1032 if (Check_DSA_Kernel_Setting() != 1) {
1033 printf("Please enable SVA.(Add intel_iommu=on,sm_on in kernel cmdline)\n");
1037 /* Check the idxd device file on /dev/dsa/ */
1038 for (int i
= 0; i
< len
; i
++) {
1043 /* After config, /dev/dsa/wq0.1 should be generated */
1044 return (file_Exists(dsaDeviceFile
) != 1);
1048 * Open DSA device file, triger API: iommu_sva_alloc_pasid
1050 void *allocate_dsa_pasid(void)
1055 fd
= open(dsaDeviceFile
, O_RDWR
);
1061 wq
= mmap(NULL
, 0x1000, PROT_WRITE
,
1062 MAP_SHARED
| MAP_POPULATE
, fd
, 0);
1063 if (wq
== MAP_FAILED
)
1069 int set_force_svm(void)
1073 ret
= syscall(SYS_arch_prctl
, ARCH_FORCE_TAGGED_SVA
);
1078 int handle_pasid(struct testcases
*test
)
1080 uint tmp
= test
->cmd
;
1085 ret
= Dsa_Init_Sysfs();
1089 for (int i
= 0; i
< 3; i
++) {
1093 /* run set lam mode*/
1094 if ((runed
& 0x1) == 0) {
1095 err
= set_lam(LAM_U57_BITS
);
1096 runed
= runed
| 0x1;
1099 } else if (tmp
& 0x4) {
1101 if ((runed
& 0x4) == 0) {
1102 err
= set_force_svm();
1103 runed
= runed
| 0x4;
1106 } else if (tmp
& 0x2) {
1107 /* run allocate pasid */
1108 if ((runed
& 0x2) == 0) {
1109 runed
= runed
| 0x2;
1110 wq
= allocate_dsa_pasid();
1111 if (wq
== MAP_FAILED
)
1124 if (wq
!= MAP_FAILED
&& wq
!= NULL
)
1125 if (munmap(wq
, 0x1000))
1126 printf("munmap failed %d\n", errno
);
1135 * Pasid test depends on idxd and SVA, kernel should enable iommu and sm.
1136 * command line(intel_iommu=on,sm_on)
1138 static struct testcases pasid_cases
[] = {
1141 .cmd
= PAS_CMD(LAM_CMD_BIT
, PAS_CMD_BIT
, SVA_CMD_BIT
),
1142 .test_func
= handle_pasid
,
1143 .msg
= "PASID: [Negative] Execute LAM, PASID, SVA in sequence\n",
1147 .cmd
= PAS_CMD(LAM_CMD_BIT
, SVA_CMD_BIT
, PAS_CMD_BIT
),
1148 .test_func
= handle_pasid
,
1149 .msg
= "PASID: Execute LAM, SVA, PASID in sequence\n",
1153 .cmd
= PAS_CMD(PAS_CMD_BIT
, LAM_CMD_BIT
, SVA_CMD_BIT
),
1154 .test_func
= handle_pasid
,
1155 .msg
= "PASID: [Negative] Execute PASID, LAM, SVA in sequence\n",
1159 .cmd
= PAS_CMD(PAS_CMD_BIT
, SVA_CMD_BIT
, LAM_CMD_BIT
),
1160 .test_func
= handle_pasid
,
1161 .msg
= "PASID: Execute PASID, SVA, LAM in sequence\n",
1165 .cmd
= PAS_CMD(SVA_CMD_BIT
, LAM_CMD_BIT
, PAS_CMD_BIT
),
1166 .test_func
= handle_pasid
,
1167 .msg
= "PASID: Execute SVA, LAM, PASID in sequence\n",
1171 .cmd
= PAS_CMD(SVA_CMD_BIT
, PAS_CMD_BIT
, LAM_CMD_BIT
),
1172 .test_func
= handle_pasid
,
1173 .msg
= "PASID: Execute SVA, PASID, LAM in sequence\n",
1177 int main(int argc
, char **argv
)
1180 unsigned int tests
= TEST_MASK
;
1184 if (!cpu_has_lam()) {
1185 ksft_print_msg("Unsupported LAM feature!\n");
1189 while ((c
= getopt(argc
, argv
, "ht:")) != -1) {
1192 tests
= strtoul(optarg
, NULL
, 16);
1193 if (tests
&& !(tests
& TEST_MASK
)) {
1194 ksft_print_msg("Invalid argument!\n");
1202 ksft_print_msg("Invalid argument\n");
1208 * When tests is 0, it is not a real test case;
1209 * the option used by test case(execve) to check the lam mode in
1210 * process generated by execve, the process read back lam mode and
1211 * check with lam mode in parent process.
1216 /* Run test cases */
1217 if (tests
& FUNC_MALLOC
)
1218 run_test(malloc_cases
, ARRAY_SIZE(malloc_cases
));
1220 if (tests
& FUNC_BITS
)
1221 run_test(bits_cases
, ARRAY_SIZE(bits_cases
));
1223 if (tests
& FUNC_MMAP
)
1224 run_test(mmap_cases
, ARRAY_SIZE(mmap_cases
));
1226 if (tests
& FUNC_SYSCALL
)
1227 run_test(syscall_cases
, ARRAY_SIZE(syscall_cases
));
1229 if (tests
& FUNC_URING
)
1230 run_test(uring_cases
, ARRAY_SIZE(uring_cases
));
1232 if (tests
& FUNC_INHERITE
)
1233 run_test(inheritance_cases
, ARRAY_SIZE(inheritance_cases
));
1235 if (tests
& FUNC_PASID
)
1236 run_test(pasid_cases
, ARRAY_SIZE(pasid_cases
));
1238 ksft_set_plan(tests_cnt
);