lam.c 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371
  1. // SPDX-License-Identifier: GPL-2.0
  2. #define _GNU_SOURCE
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <sys/syscall.h>
  7. #include <sys/ioctl.h>
  8. #include <time.h>
  9. #include <signal.h>
  10. #include <setjmp.h>
  11. #include <sys/mman.h>
  12. #include <sys/utsname.h>
  13. #include <sys/wait.h>
  14. #include <sys/stat.h>
  15. #include <fcntl.h>
  16. #include <inttypes.h>
  17. #include <sched.h>
  18. #include <sys/uio.h>
  19. #include <linux/io_uring.h>
  20. #include "kselftest.h"
  21. #ifndef __x86_64__
  22. # error This test is 64-bit only
  23. #endif
  24. /* LAM modes, these definitions were copied from kernel code */
  25. #define LAM_NONE 0
  26. #define LAM_U57_BITS 6
  27. #define LAM_U57_MASK (0x3fULL << 57)
  28. /* arch prctl for LAM */
  29. #define ARCH_GET_UNTAG_MASK 0x4001
  30. #define ARCH_ENABLE_TAGGED_ADDR 0x4002
  31. #define ARCH_GET_MAX_TAG_BITS 0x4003
  32. #define ARCH_FORCE_TAGGED_SVA 0x4004
  33. /* Specified test function bits */
  34. #define FUNC_MALLOC 0x1
  35. #define FUNC_BITS 0x2
  36. #define FUNC_MMAP 0x4
  37. #define FUNC_SYSCALL 0x8
  38. #define FUNC_URING 0x10
  39. #define FUNC_INHERITE 0x20
  40. #define FUNC_PASID 0x40
  41. /* get_user() pointer test cases */
  42. #define GET_USER_USER 0
  43. #define GET_USER_KERNEL_TOP 1
  44. #define GET_USER_KERNEL_BOT 2
  45. #define GET_USER_KERNEL 3
  46. #define TEST_MASK 0x7f
  47. #define L5_SIGN_EXT_MASK (0xFFUL << 56)
  48. #define L4_SIGN_EXT_MASK (0x1FFFFUL << 47)
  49. #define LOW_ADDR (0x1UL << 30)
  50. #define HIGH_ADDR (0x3UL << 48)
  51. #define MALLOC_LEN 32
  52. #define PAGE_SIZE (4 << 10)
  53. #define STACK_SIZE 65536
  54. #define barrier() ({ \
  55. __asm__ __volatile__("" : : : "memory"); \
  56. })
  57. #define URING_QUEUE_SZ 1
  58. #define URING_BLOCK_SZ 2048
  59. /* Pasid test define */
  60. #define LAM_CMD_BIT 0x1
  61. #define PAS_CMD_BIT 0x2
  62. #define SVA_CMD_BIT 0x4
  63. #define PAS_CMD(cmd1, cmd2, cmd3) (((cmd3) << 8) | ((cmd2) << 4) | ((cmd1) << 0))
  64. struct testcases {
  65. unsigned int later;
  66. int expected; /* 2: SIGSEGV Error; 1: other errors */
  67. unsigned long lam;
  68. uint64_t addr;
  69. uint64_t cmd;
  70. int (*test_func)(struct testcases *test);
  71. const char *msg;
  72. };
  73. /* Used by CQ of uring, source file handler and file's size */
  74. struct file_io {
  75. int file_fd;
  76. off_t file_sz;
  77. struct iovec iovecs[];
  78. };
  79. struct io_uring_queue {
  80. unsigned int *head;
  81. unsigned int *tail;
  82. unsigned int *ring_mask;
  83. unsigned int *ring_entries;
  84. unsigned int *flags;
  85. unsigned int *array;
  86. union {
  87. struct io_uring_cqe *cqes;
  88. struct io_uring_sqe *sqes;
  89. } queue;
  90. size_t ring_sz;
  91. };
  92. struct io_ring {
  93. int ring_fd;
  94. struct io_uring_queue sq_ring;
  95. struct io_uring_queue cq_ring;
  96. };
  97. int tests_cnt;
  98. jmp_buf segv_env;
  99. static void segv_handler(int sig)
  100. {
  101. ksft_print_msg("Get segmentation fault(%d).", sig);
  102. siglongjmp(segv_env, 1);
  103. }
  104. static inline int lam_is_available(void)
  105. {
  106. unsigned int cpuinfo[4];
  107. unsigned long bits = 0;
  108. int ret;
  109. __cpuid_count(0x7, 1, cpuinfo[0], cpuinfo[1], cpuinfo[2], cpuinfo[3]);
  110. /* Check if cpu supports LAM */
  111. if (!(cpuinfo[0] & (1 << 26))) {
  112. ksft_print_msg("LAM is not supported!\n");
  113. return 0;
  114. }
  115. /* Return 0 if CONFIG_ADDRESS_MASKING is not set */
  116. ret = syscall(SYS_arch_prctl, ARCH_GET_MAX_TAG_BITS, &bits);
  117. if (ret) {
  118. ksft_print_msg("LAM is disabled in the kernel!\n");
  119. return 0;
  120. }
  121. return 1;
  122. }
  123. static inline int la57_enabled(void)
  124. {
  125. int ret;
  126. void *p;
  127. p = mmap((void *)HIGH_ADDR, PAGE_SIZE, PROT_READ | PROT_WRITE,
  128. MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  129. ret = p == MAP_FAILED ? 0 : 1;
  130. munmap(p, PAGE_SIZE);
  131. return ret;
  132. }
  133. /*
  134. * Set tagged address and read back untag mask.
  135. * check if the untagged mask is expected.
  136. *
  137. * @return:
  138. * 0: Set LAM mode successfully
  139. * others: failed to set LAM
  140. */
  141. static int set_lam(unsigned long lam)
  142. {
  143. int ret = 0;
  144. uint64_t ptr = 0;
  145. if (lam != LAM_U57_BITS && lam != LAM_NONE)
  146. return -1;
  147. /* Skip check return */
  148. syscall(SYS_arch_prctl, ARCH_ENABLE_TAGGED_ADDR, lam);
  149. /* Get untagged mask */
  150. syscall(SYS_arch_prctl, ARCH_GET_UNTAG_MASK, &ptr);
  151. /* Check mask returned is expected */
  152. if (lam == LAM_U57_BITS)
  153. ret = (ptr != ~(LAM_U57_MASK));
  154. else if (lam == LAM_NONE)
  155. ret = (ptr != -1ULL);
  156. return ret;
  157. }
  158. static unsigned long get_default_tag_bits(void)
  159. {
  160. pid_t pid;
  161. int lam = LAM_NONE;
  162. int ret = 0;
  163. pid = fork();
  164. if (pid < 0) {
  165. perror("Fork failed.");
  166. } else if (pid == 0) {
  167. /* Set LAM mode in child process */
  168. if (set_lam(LAM_U57_BITS) == 0)
  169. lam = LAM_U57_BITS;
  170. else
  171. lam = LAM_NONE;
  172. exit(lam);
  173. } else {
  174. wait(&ret);
  175. lam = WEXITSTATUS(ret);
  176. }
  177. return lam;
  178. }
  179. /*
  180. * Set tagged address and read back untag mask.
  181. * check if the untag mask is expected.
  182. */
  183. static int get_lam(void)
  184. {
  185. uint64_t ptr = 0;
  186. int ret = -1;
  187. /* Get untagged mask */
  188. if (syscall(SYS_arch_prctl, ARCH_GET_UNTAG_MASK, &ptr) == -1)
  189. return -1;
  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. return ret;
  196. }
  197. /* According to LAM mode, set metadata in high bits */
  198. static uint64_t set_metadata(uint64_t src, unsigned long lam)
  199. {
  200. uint64_t metadata;
  201. srand(time(NULL));
  202. switch (lam) {
  203. case LAM_U57_BITS: /* Set metadata in bits 62:57 */
  204. /* Get a random non-zero value as metadata */
  205. metadata = (rand() % ((1UL << LAM_U57_BITS) - 1) + 1) << 57;
  206. metadata |= (src & ~(LAM_U57_MASK));
  207. break;
  208. default:
  209. metadata = src;
  210. break;
  211. }
  212. return metadata;
  213. }
  214. /*
  215. * Set metadata in user pointer, compare new pointer with original pointer.
  216. * both pointers should point to the same address.
  217. *
  218. * @return:
  219. * 0: value on the pointer with metadata and value on original are same
  220. * 1: not same.
  221. */
  222. static int handle_lam_test(void *src, unsigned int lam)
  223. {
  224. char *ptr;
  225. strcpy((char *)src, "USER POINTER");
  226. ptr = (char *)set_metadata((uint64_t)src, lam);
  227. if (src == ptr)
  228. return 0;
  229. /* Copy a string into the pointer with metadata */
  230. strcpy((char *)ptr, "METADATA POINTER");
  231. return (!!strcmp((char *)src, (char *)ptr));
  232. }
  233. int handle_max_bits(struct testcases *test)
  234. {
  235. unsigned long exp_bits = get_default_tag_bits();
  236. unsigned long bits = 0;
  237. if (exp_bits != LAM_NONE)
  238. exp_bits = LAM_U57_BITS;
  239. /* Get LAM max tag bits */
  240. if (syscall(SYS_arch_prctl, ARCH_GET_MAX_TAG_BITS, &bits) == -1)
  241. return 1;
  242. return (exp_bits != bits);
  243. }
  244. /*
  245. * Test lam feature through dereference pointer get from malloc.
  246. * @return 0: Pass test. 1: Get failure during test 2: Get SIGSEGV
  247. */
  248. static int handle_malloc(struct testcases *test)
  249. {
  250. char *ptr = NULL;
  251. int ret = 0;
  252. if (test->later == 0 && test->lam != 0)
  253. if (set_lam(test->lam) == -1)
  254. return 1;
  255. ptr = (char *)malloc(MALLOC_LEN);
  256. if (ptr == NULL) {
  257. perror("malloc() failure\n");
  258. return 1;
  259. }
  260. /* Set signal handler */
  261. if (sigsetjmp(segv_env, 1) == 0) {
  262. signal(SIGSEGV, segv_handler);
  263. ret = handle_lam_test(ptr, test->lam);
  264. } else {
  265. ret = 2;
  266. }
  267. if (test->later != 0 && test->lam != 0)
  268. if (set_lam(test->lam) == -1 && ret == 0)
  269. ret = 1;
  270. free(ptr);
  271. return ret;
  272. }
  273. static int handle_mmap(struct testcases *test)
  274. {
  275. void *ptr;
  276. unsigned int flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED;
  277. int ret = 0;
  278. if (test->later == 0 && test->lam != 0)
  279. if (set_lam(test->lam) != 0)
  280. return 1;
  281. ptr = mmap((void *)test->addr, PAGE_SIZE, PROT_READ | PROT_WRITE,
  282. flags, -1, 0);
  283. if (ptr == MAP_FAILED) {
  284. if (test->addr == HIGH_ADDR)
  285. if (!la57_enabled())
  286. return 3; /* unsupport LA57 */
  287. return 1;
  288. }
  289. if (test->later != 0 && test->lam != 0)
  290. if (set_lam(test->lam) != 0)
  291. ret = 1;
  292. if (ret == 0) {
  293. if (sigsetjmp(segv_env, 1) == 0) {
  294. signal(SIGSEGV, segv_handler);
  295. ret = handle_lam_test(ptr, test->lam);
  296. } else {
  297. ret = 2;
  298. }
  299. }
  300. munmap(ptr, PAGE_SIZE);
  301. return ret;
  302. }
  303. static int handle_syscall(struct testcases *test)
  304. {
  305. struct utsname unme, *pu;
  306. int ret = 0;
  307. if (test->later == 0 && test->lam != 0)
  308. if (set_lam(test->lam) != 0)
  309. return 1;
  310. if (sigsetjmp(segv_env, 1) == 0) {
  311. signal(SIGSEGV, segv_handler);
  312. pu = (struct utsname *)set_metadata((uint64_t)&unme, test->lam);
  313. ret = uname(pu);
  314. if (ret < 0)
  315. ret = 1;
  316. } else {
  317. ret = 2;
  318. }
  319. if (test->later != 0 && test->lam != 0)
  320. if (set_lam(test->lam) != -1 && ret == 0)
  321. ret = 1;
  322. return ret;
  323. }
  324. static int get_user_syscall(struct testcases *test)
  325. {
  326. uint64_t ptr_address, bitmask;
  327. int fd, ret = 0;
  328. void *ptr;
  329. if (la57_enabled()) {
  330. bitmask = L5_SIGN_EXT_MASK;
  331. ptr_address = HIGH_ADDR;
  332. } else {
  333. bitmask = L4_SIGN_EXT_MASK;
  334. ptr_address = LOW_ADDR;
  335. }
  336. ptr = mmap((void *)ptr_address, PAGE_SIZE, PROT_READ | PROT_WRITE,
  337. MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
  338. if (ptr == MAP_FAILED) {
  339. perror("failed to map byte to pass into get_user");
  340. return 1;
  341. }
  342. if (set_lam(test->lam) != 0) {
  343. ret = 2;
  344. goto error;
  345. }
  346. fd = memfd_create("lam_ioctl", 0);
  347. if (fd == -1) {
  348. munmap(ptr, PAGE_SIZE);
  349. exit(EXIT_FAILURE);
  350. }
  351. switch (test->later) {
  352. case GET_USER_USER:
  353. /* Control group - properly tagged user pointer */
  354. ptr = (void *)set_metadata((uint64_t)ptr, test->lam);
  355. break;
  356. case GET_USER_KERNEL_TOP:
  357. /* Kernel address with top bit cleared */
  358. bitmask &= (bitmask >> 1);
  359. ptr = (void *)((uint64_t)ptr | bitmask);
  360. break;
  361. case GET_USER_KERNEL_BOT:
  362. /* Kernel address with bottom sign-extension bit cleared */
  363. bitmask &= (bitmask << 1);
  364. ptr = (void *)((uint64_t)ptr | bitmask);
  365. break;
  366. case GET_USER_KERNEL:
  367. /* Try to pass a kernel address */
  368. ptr = (void *)((uint64_t)ptr | bitmask);
  369. break;
  370. default:
  371. printf("Invalid test case value passed!\n");
  372. break;
  373. }
  374. /*
  375. * Use FIOASYNC ioctl because it utilizes get_user() internally and is
  376. * very non-invasive to the system. Pass differently tagged pointers to
  377. * get_user() in order to verify that valid user pointers are going
  378. * through and invalid kernel/non-canonical pointers are not.
  379. */
  380. if (ioctl(fd, FIOASYNC, ptr) != 0)
  381. ret = 1;
  382. close(fd);
  383. error:
  384. munmap(ptr, PAGE_SIZE);
  385. return ret;
  386. }
  387. int sys_uring_setup(unsigned int entries, struct io_uring_params *p)
  388. {
  389. return (int)syscall(__NR_io_uring_setup, entries, p);
  390. }
  391. int sys_uring_enter(int fd, unsigned int to, unsigned int min, unsigned int flags)
  392. {
  393. return (int)syscall(__NR_io_uring_enter, fd, to, min, flags, NULL, 0);
  394. }
  395. /* Init submission queue and completion queue */
  396. int mmap_io_uring(struct io_uring_params p, struct io_ring *s)
  397. {
  398. struct io_uring_queue *sring = &s->sq_ring;
  399. struct io_uring_queue *cring = &s->cq_ring;
  400. sring->ring_sz = p.sq_off.array + p.sq_entries * sizeof(unsigned int);
  401. cring->ring_sz = p.cq_off.cqes + p.cq_entries * sizeof(struct io_uring_cqe);
  402. if (p.features & IORING_FEAT_SINGLE_MMAP) {
  403. if (cring->ring_sz > sring->ring_sz)
  404. sring->ring_sz = cring->ring_sz;
  405. cring->ring_sz = sring->ring_sz;
  406. }
  407. void *sq_ptr = mmap(0, sring->ring_sz, PROT_READ | PROT_WRITE,
  408. MAP_SHARED | MAP_POPULATE, s->ring_fd,
  409. IORING_OFF_SQ_RING);
  410. if (sq_ptr == MAP_FAILED) {
  411. perror("sub-queue!");
  412. return 1;
  413. }
  414. void *cq_ptr = sq_ptr;
  415. if (!(p.features & IORING_FEAT_SINGLE_MMAP)) {
  416. cq_ptr = mmap(0, cring->ring_sz, PROT_READ | PROT_WRITE,
  417. MAP_SHARED | MAP_POPULATE, s->ring_fd,
  418. IORING_OFF_CQ_RING);
  419. if (cq_ptr == MAP_FAILED) {
  420. perror("cpl-queue!");
  421. munmap(sq_ptr, sring->ring_sz);
  422. return 1;
  423. }
  424. }
  425. sring->head = sq_ptr + p.sq_off.head;
  426. sring->tail = sq_ptr + p.sq_off.tail;
  427. sring->ring_mask = sq_ptr + p.sq_off.ring_mask;
  428. sring->ring_entries = sq_ptr + p.sq_off.ring_entries;
  429. sring->flags = sq_ptr + p.sq_off.flags;
  430. sring->array = sq_ptr + p.sq_off.array;
  431. /* Map a queue as mem map */
  432. s->sq_ring.queue.sqes = mmap(0, p.sq_entries * sizeof(struct io_uring_sqe),
  433. PROT_READ | PROT_WRITE, MAP_SHARED | MAP_POPULATE,
  434. s->ring_fd, IORING_OFF_SQES);
  435. if (s->sq_ring.queue.sqes == MAP_FAILED) {
  436. munmap(sq_ptr, sring->ring_sz);
  437. if (sq_ptr != cq_ptr) {
  438. ksft_print_msg("failed to mmap uring queue!");
  439. munmap(cq_ptr, cring->ring_sz);
  440. return 1;
  441. }
  442. }
  443. cring->head = cq_ptr + p.cq_off.head;
  444. cring->tail = cq_ptr + p.cq_off.tail;
  445. cring->ring_mask = cq_ptr + p.cq_off.ring_mask;
  446. cring->ring_entries = cq_ptr + p.cq_off.ring_entries;
  447. cring->queue.cqes = cq_ptr + p.cq_off.cqes;
  448. return 0;
  449. }
  450. /* Init io_uring queues */
  451. int setup_io_uring(struct io_ring *s)
  452. {
  453. struct io_uring_params para;
  454. memset(&para, 0, sizeof(para));
  455. s->ring_fd = sys_uring_setup(URING_QUEUE_SZ, &para);
  456. if (s->ring_fd < 0)
  457. return 1;
  458. return mmap_io_uring(para, s);
  459. }
  460. /*
  461. * Get data from completion queue. the data buffer saved the file data
  462. * return 0: success; others: error;
  463. */
  464. int handle_uring_cq(struct io_ring *s)
  465. {
  466. struct file_io *fi = NULL;
  467. struct io_uring_queue *cring = &s->cq_ring;
  468. struct io_uring_cqe *cqe;
  469. unsigned int head;
  470. off_t len = 0;
  471. head = *cring->head;
  472. do {
  473. barrier();
  474. if (head == *cring->tail)
  475. break;
  476. /* Get the entry */
  477. cqe = &cring->queue.cqes[head & *s->cq_ring.ring_mask];
  478. fi = (struct file_io *)cqe->user_data;
  479. if (cqe->res < 0)
  480. break;
  481. int blocks = (int)(fi->file_sz + URING_BLOCK_SZ - 1) / URING_BLOCK_SZ;
  482. for (int i = 0; i < blocks; i++)
  483. len += fi->iovecs[i].iov_len;
  484. head++;
  485. } while (1);
  486. *cring->head = head;
  487. barrier();
  488. return (len != fi->file_sz);
  489. }
  490. /*
  491. * Submit squeue. specify via IORING_OP_READV.
  492. * the buffer need to be set metadata according to LAM mode
  493. */
  494. int handle_uring_sq(struct io_ring *ring, struct file_io *fi, unsigned long lam)
  495. {
  496. int file_fd = fi->file_fd;
  497. struct io_uring_queue *sring = &ring->sq_ring;
  498. unsigned int index = 0, cur_block = 0, tail = 0, next_tail = 0;
  499. struct io_uring_sqe *sqe;
  500. off_t remain = fi->file_sz;
  501. int blocks = (int)(remain + URING_BLOCK_SZ - 1) / URING_BLOCK_SZ;
  502. while (remain) {
  503. off_t bytes = remain;
  504. void *buf;
  505. if (bytes > URING_BLOCK_SZ)
  506. bytes = URING_BLOCK_SZ;
  507. fi->iovecs[cur_block].iov_len = bytes;
  508. if (posix_memalign(&buf, URING_BLOCK_SZ, URING_BLOCK_SZ))
  509. return 1;
  510. fi->iovecs[cur_block].iov_base = (void *)set_metadata((uint64_t)buf, lam);
  511. remain -= bytes;
  512. cur_block++;
  513. }
  514. next_tail = *sring->tail;
  515. tail = next_tail;
  516. next_tail++;
  517. barrier();
  518. index = tail & *ring->sq_ring.ring_mask;
  519. sqe = &ring->sq_ring.queue.sqes[index];
  520. sqe->fd = file_fd;
  521. sqe->flags = 0;
  522. sqe->opcode = IORING_OP_READV;
  523. sqe->addr = (unsigned long)fi->iovecs;
  524. sqe->len = blocks;
  525. sqe->off = 0;
  526. sqe->user_data = (uint64_t)fi;
  527. sring->array[index] = index;
  528. tail = next_tail;
  529. if (*sring->tail != tail) {
  530. *sring->tail = tail;
  531. barrier();
  532. }
  533. if (sys_uring_enter(ring->ring_fd, 1, 1, IORING_ENTER_GETEVENTS) < 0)
  534. return 1;
  535. return 0;
  536. }
  537. /*
  538. * Test LAM in async I/O and io_uring, read current binery through io_uring
  539. * Set metadata in pointers to iovecs buffer.
  540. */
  541. int do_uring(unsigned long lam)
  542. {
  543. struct io_ring *ring;
  544. struct file_io *fi;
  545. struct stat st;
  546. int ret = 1;
  547. char path[PATH_MAX] = {0};
  548. /* get current process path */
  549. if (readlink("/proc/self/exe", path, PATH_MAX - 1) <= 0)
  550. return 1;
  551. int file_fd = open(path, O_RDONLY);
  552. if (file_fd < 0)
  553. return 1;
  554. if (fstat(file_fd, &st) < 0)
  555. goto cleanup;
  556. off_t file_sz = st.st_size;
  557. int blocks = (int)(file_sz + URING_BLOCK_SZ - 1) / URING_BLOCK_SZ;
  558. fi = malloc(sizeof(*fi) + sizeof(struct iovec) * blocks);
  559. if (!fi)
  560. goto cleanup;
  561. fi->file_sz = file_sz;
  562. fi->file_fd = file_fd;
  563. ring = malloc(sizeof(*ring));
  564. if (!ring) {
  565. free(fi);
  566. goto cleanup;
  567. }
  568. memset(ring, 0, sizeof(struct io_ring));
  569. if (setup_io_uring(ring))
  570. goto out;
  571. if (handle_uring_sq(ring, fi, lam))
  572. goto out;
  573. ret = handle_uring_cq(ring);
  574. out:
  575. free(ring);
  576. for (int i = 0; i < blocks; i++) {
  577. if (fi->iovecs[i].iov_base) {
  578. uint64_t addr = ((uint64_t)fi->iovecs[i].iov_base);
  579. switch (lam) {
  580. case LAM_U57_BITS: /* Clear bits 62:57 */
  581. addr = (addr & ~(LAM_U57_MASK));
  582. break;
  583. }
  584. free((void *)addr);
  585. fi->iovecs[i].iov_base = NULL;
  586. }
  587. }
  588. free(fi);
  589. cleanup:
  590. close(file_fd);
  591. return ret;
  592. }
  593. int handle_uring(struct testcases *test)
  594. {
  595. int ret = 0;
  596. if (test->later == 0 && test->lam != 0)
  597. if (set_lam(test->lam) != 0)
  598. return 1;
  599. if (sigsetjmp(segv_env, 1) == 0) {
  600. signal(SIGSEGV, segv_handler);
  601. ret = do_uring(test->lam);
  602. } else {
  603. ret = 2;
  604. }
  605. return ret;
  606. }
  607. static int fork_test(struct testcases *test)
  608. {
  609. int ret, child_ret;
  610. pid_t pid;
  611. pid = fork();
  612. if (pid < 0) {
  613. perror("Fork failed.");
  614. ret = 1;
  615. } else if (pid == 0) {
  616. ret = test->test_func(test);
  617. exit(ret);
  618. } else {
  619. wait(&child_ret);
  620. ret = WEXITSTATUS(child_ret);
  621. }
  622. return ret;
  623. }
  624. static int handle_execve(struct testcases *test)
  625. {
  626. int ret, child_ret;
  627. int lam = test->lam;
  628. pid_t pid;
  629. pid = fork();
  630. if (pid < 0) {
  631. perror("Fork failed.");
  632. ret = 1;
  633. } else if (pid == 0) {
  634. char path[PATH_MAX] = {0};
  635. /* Set LAM mode in parent process */
  636. if (set_lam(lam) != 0)
  637. return 1;
  638. /* Get current binary's path and the binary was run by execve */
  639. if (readlink("/proc/self/exe", path, PATH_MAX - 1) <= 0)
  640. exit(-1);
  641. /* run binary to get LAM mode and return to parent process */
  642. if (execlp(path, path, "-t 0x0", NULL) < 0) {
  643. perror("error on exec");
  644. exit(-1);
  645. }
  646. } else {
  647. wait(&child_ret);
  648. ret = WEXITSTATUS(child_ret);
  649. if (ret != LAM_NONE)
  650. return 1;
  651. }
  652. return 0;
  653. }
  654. static int handle_inheritance(struct testcases *test)
  655. {
  656. int ret, child_ret;
  657. int lam = test->lam;
  658. pid_t pid;
  659. /* Set LAM mode in parent process */
  660. if (set_lam(lam) != 0)
  661. return 1;
  662. pid = fork();
  663. if (pid < 0) {
  664. perror("Fork failed.");
  665. return 1;
  666. } else if (pid == 0) {
  667. /* Set LAM mode in parent process */
  668. int child_lam = get_lam();
  669. exit(child_lam);
  670. } else {
  671. wait(&child_ret);
  672. ret = WEXITSTATUS(child_ret);
  673. if (lam != ret)
  674. return 1;
  675. }
  676. return 0;
  677. }
  678. static int thread_fn_get_lam(void *arg)
  679. {
  680. return get_lam();
  681. }
  682. static int thread_fn_set_lam(void *arg)
  683. {
  684. struct testcases *test = arg;
  685. return set_lam(test->lam);
  686. }
  687. static int handle_thread(struct testcases *test)
  688. {
  689. char stack[STACK_SIZE];
  690. int ret, child_ret;
  691. int lam = 0;
  692. pid_t pid;
  693. /* Set LAM mode in parent process */
  694. if (!test->later) {
  695. lam = test->lam;
  696. if (set_lam(lam) != 0)
  697. return 1;
  698. }
  699. pid = clone(thread_fn_get_lam, stack + STACK_SIZE,
  700. SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM, NULL);
  701. if (pid < 0) {
  702. perror("Clone failed.");
  703. return 1;
  704. }
  705. waitpid(pid, &child_ret, 0);
  706. ret = WEXITSTATUS(child_ret);
  707. if (lam != ret)
  708. return 1;
  709. if (test->later) {
  710. if (set_lam(test->lam) != 0)
  711. return 1;
  712. }
  713. return 0;
  714. }
  715. static int handle_thread_enable(struct testcases *test)
  716. {
  717. char stack[STACK_SIZE];
  718. int ret, child_ret;
  719. int lam = test->lam;
  720. pid_t pid;
  721. pid = clone(thread_fn_set_lam, stack + STACK_SIZE,
  722. SIGCHLD | CLONE_FILES | CLONE_FS | CLONE_VM, test);
  723. if (pid < 0) {
  724. perror("Clone failed.");
  725. return 1;
  726. }
  727. waitpid(pid, &child_ret, 0);
  728. ret = WEXITSTATUS(child_ret);
  729. if (lam != ret)
  730. return 1;
  731. return 0;
  732. }
  733. static void run_test(struct testcases *test, int count)
  734. {
  735. int i, ret = 0;
  736. for (i = 0; i < count; i++) {
  737. struct testcases *t = test + i;
  738. /* fork a process to run test case */
  739. tests_cnt++;
  740. ret = fork_test(t);
  741. /* return 3 is not support LA57, the case should be skipped */
  742. if (ret == 3) {
  743. ksft_test_result_skip("%s", t->msg);
  744. continue;
  745. }
  746. if (ret != 0)
  747. ret = (t->expected == ret);
  748. else
  749. ret = !(t->expected);
  750. ksft_test_result(ret, "%s", t->msg);
  751. }
  752. }
  753. static struct testcases uring_cases[] = {
  754. {
  755. .later = 0,
  756. .lam = LAM_U57_BITS,
  757. .test_func = handle_uring,
  758. .msg = "URING: LAM_U57. Dereferencing pointer with metadata\n",
  759. },
  760. {
  761. .later = 1,
  762. .expected = 1,
  763. .lam = LAM_U57_BITS,
  764. .test_func = handle_uring,
  765. .msg = "URING:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
  766. },
  767. };
  768. static struct testcases malloc_cases[] = {
  769. {
  770. .later = 0,
  771. .lam = LAM_U57_BITS,
  772. .test_func = handle_malloc,
  773. .msg = "MALLOC: LAM_U57. Dereferencing pointer with metadata\n",
  774. },
  775. {
  776. .later = 1,
  777. .expected = 2,
  778. .lam = LAM_U57_BITS,
  779. .test_func = handle_malloc,
  780. .msg = "MALLOC:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
  781. },
  782. };
  783. static struct testcases bits_cases[] = {
  784. {
  785. .test_func = handle_max_bits,
  786. .msg = "BITS: Check default tag bits\n",
  787. },
  788. };
  789. static struct testcases syscall_cases[] = {
  790. {
  791. .later = 0,
  792. .lam = LAM_U57_BITS,
  793. .test_func = handle_syscall,
  794. .msg = "SYSCALL: LAM_U57. syscall with metadata\n",
  795. },
  796. {
  797. .later = 1,
  798. .expected = 1,
  799. .lam = LAM_U57_BITS,
  800. .test_func = handle_syscall,
  801. .msg = "SYSCALL:[Negative] Disable LAM. Dereferencing pointer with metadata.\n",
  802. },
  803. {
  804. .later = GET_USER_USER,
  805. .lam = LAM_U57_BITS,
  806. .test_func = get_user_syscall,
  807. .msg = "GET_USER: get_user() and pass a properly tagged user pointer.\n",
  808. },
  809. {
  810. .later = GET_USER_KERNEL_TOP,
  811. .expected = 1,
  812. .lam = LAM_U57_BITS,
  813. .test_func = get_user_syscall,
  814. .msg = "GET_USER:[Negative] get_user() with a kernel pointer and the top bit cleared.\n",
  815. },
  816. {
  817. .later = GET_USER_KERNEL_BOT,
  818. .expected = 1,
  819. .lam = LAM_U57_BITS,
  820. .test_func = get_user_syscall,
  821. .msg = "GET_USER:[Negative] get_user() with a kernel pointer and the bottom sign-extension bit cleared.\n",
  822. },
  823. {
  824. .later = GET_USER_KERNEL,
  825. .expected = 1,
  826. .lam = LAM_U57_BITS,
  827. .test_func = get_user_syscall,
  828. .msg = "GET_USER:[Negative] get_user() and pass a kernel pointer.\n",
  829. },
  830. };
  831. static struct testcases mmap_cases[] = {
  832. {
  833. .later = 1,
  834. .expected = 0,
  835. .lam = LAM_U57_BITS,
  836. .addr = HIGH_ADDR,
  837. .test_func = handle_mmap,
  838. .msg = "MMAP: First mmap high address, then set LAM_U57.\n",
  839. },
  840. {
  841. .later = 0,
  842. .expected = 0,
  843. .lam = LAM_U57_BITS,
  844. .addr = HIGH_ADDR,
  845. .test_func = handle_mmap,
  846. .msg = "MMAP: First LAM_U57, then High address.\n",
  847. },
  848. {
  849. .later = 0,
  850. .expected = 0,
  851. .lam = LAM_U57_BITS,
  852. .addr = LOW_ADDR,
  853. .test_func = handle_mmap,
  854. .msg = "MMAP: First LAM_U57, then Low address.\n",
  855. },
  856. };
  857. static struct testcases inheritance_cases[] = {
  858. {
  859. .expected = 0,
  860. .lam = LAM_U57_BITS,
  861. .test_func = handle_inheritance,
  862. .msg = "FORK: LAM_U57, child process should get LAM mode same as parent\n",
  863. },
  864. {
  865. .expected = 0,
  866. .lam = LAM_U57_BITS,
  867. .test_func = handle_thread,
  868. .msg = "THREAD: LAM_U57, child thread should get LAM mode same as parent\n",
  869. },
  870. {
  871. .expected = 1,
  872. .lam = LAM_U57_BITS,
  873. .test_func = handle_thread_enable,
  874. .msg = "THREAD: [NEGATIVE] Enable LAM in child.\n",
  875. },
  876. {
  877. .expected = 1,
  878. .later = 1,
  879. .lam = LAM_U57_BITS,
  880. .test_func = handle_thread,
  881. .msg = "THREAD: [NEGATIVE] Enable LAM in parent after thread created.\n",
  882. },
  883. {
  884. .expected = 0,
  885. .lam = LAM_U57_BITS,
  886. .test_func = handle_execve,
  887. .msg = "EXECVE: LAM_U57, child process should get disabled LAM mode\n",
  888. },
  889. };
  890. static void cmd_help(void)
  891. {
  892. printf("usage: lam [-h] [-t test list]\n");
  893. printf("\t-t test list: run tests specified in the test list, default:0x%x\n", TEST_MASK);
  894. printf("\t\t0x1:malloc; 0x2:max_bits; 0x4:mmap; 0x8:syscall; 0x10:io_uring; 0x20:inherit;\n");
  895. printf("\t-h: help\n");
  896. }
  897. /* Check for file existence */
  898. uint8_t file_Exists(const char *fileName)
  899. {
  900. struct stat buffer;
  901. uint8_t ret = (stat(fileName, &buffer) == 0);
  902. return ret;
  903. }
  904. /* Sysfs idxd files */
  905. const char *dsa_configs[] = {
  906. "echo 1 > /sys/bus/dsa/devices/dsa0/wq0.1/group_id",
  907. "echo shared > /sys/bus/dsa/devices/dsa0/wq0.1/mode",
  908. "echo 10 > /sys/bus/dsa/devices/dsa0/wq0.1/priority",
  909. "echo 16 > /sys/bus/dsa/devices/dsa0/wq0.1/size",
  910. "echo 15 > /sys/bus/dsa/devices/dsa0/wq0.1/threshold",
  911. "echo user > /sys/bus/dsa/devices/dsa0/wq0.1/type",
  912. "echo MyApp1 > /sys/bus/dsa/devices/dsa0/wq0.1/name",
  913. "echo 1 > /sys/bus/dsa/devices/dsa0/engine0.1/group_id",
  914. "echo dsa0 > /sys/bus/dsa/drivers/idxd/bind",
  915. /* bind files and devices, generated a device file in /dev */
  916. "echo wq0.1 > /sys/bus/dsa/drivers/user/bind",
  917. };
  918. /* DSA device file */
  919. const char *dsaDeviceFile = "/dev/dsa/wq0.1";
  920. /* file for io*/
  921. const char *dsaPasidEnable = "/sys/bus/dsa/devices/dsa0/pasid_enabled";
  922. /*
  923. * DSA depends on kernel cmdline "intel_iommu=on,sm_on"
  924. * return pasid_enabled (0: disable 1:enable)
  925. */
  926. int Check_DSA_Kernel_Setting(void)
  927. {
  928. char command[256] = "";
  929. char buf[256] = "";
  930. char *ptr;
  931. int rv = -1;
  932. snprintf(command, sizeof(command) - 1, "cat %s", dsaPasidEnable);
  933. FILE *cmd = popen(command, "r");
  934. if (cmd) {
  935. while (fgets(buf, sizeof(buf) - 1, cmd) != NULL);
  936. pclose(cmd);
  937. rv = strtol(buf, &ptr, 16);
  938. }
  939. return rv;
  940. }
  941. /*
  942. * Config DSA's sysfs files as shared DSA's WQ.
  943. * Generated a device file /dev/dsa/wq0.1
  944. * Return: 0 OK; 1 Failed; 3 Skip(SVA disabled).
  945. */
  946. int Dsa_Init_Sysfs(void)
  947. {
  948. uint len = ARRAY_SIZE(dsa_configs);
  949. const char **p = dsa_configs;
  950. if (file_Exists(dsaDeviceFile) == 1)
  951. return 0;
  952. /* check the idxd driver */
  953. if (file_Exists(dsaPasidEnable) != 1) {
  954. printf("Please make sure idxd driver was loaded\n");
  955. return 3;
  956. }
  957. /* Check SVA feature */
  958. if (Check_DSA_Kernel_Setting() != 1) {
  959. printf("Please enable SVA.(Add intel_iommu=on,sm_on in kernel cmdline)\n");
  960. return 3;
  961. }
  962. /* Check the idxd device file on /dev/dsa/ */
  963. for (int i = 0; i < len; i++) {
  964. if (system(p[i]))
  965. return 1;
  966. }
  967. /* After config, /dev/dsa/wq0.1 should be generated */
  968. return (file_Exists(dsaDeviceFile) != 1);
  969. }
  970. /*
  971. * Open DSA device file, triger API: iommu_sva_alloc_pasid
  972. */
  973. void *allocate_dsa_pasid(void)
  974. {
  975. int fd;
  976. void *wq;
  977. fd = open(dsaDeviceFile, O_RDWR);
  978. if (fd < 0) {
  979. perror("open");
  980. return MAP_FAILED;
  981. }
  982. wq = mmap(NULL, 0x1000, PROT_WRITE,
  983. MAP_SHARED | MAP_POPULATE, fd, 0);
  984. close(fd);
  985. if (wq == MAP_FAILED)
  986. perror("mmap");
  987. return wq;
  988. }
  989. int set_force_svm(void)
  990. {
  991. int ret = 0;
  992. ret = syscall(SYS_arch_prctl, ARCH_FORCE_TAGGED_SVA);
  993. return ret;
  994. }
  995. int handle_pasid(struct testcases *test)
  996. {
  997. uint tmp = test->cmd;
  998. uint runed = 0x0;
  999. int ret = 0;
  1000. void *wq = NULL;
  1001. ret = Dsa_Init_Sysfs();
  1002. if (ret != 0)
  1003. return ret;
  1004. for (int i = 0; i < 3; i++) {
  1005. int err = 0;
  1006. if (tmp & 0x1) {
  1007. /* run set lam mode*/
  1008. if ((runed & 0x1) == 0) {
  1009. err = set_lam(LAM_U57_BITS);
  1010. runed = runed | 0x1;
  1011. } else
  1012. err = 1;
  1013. } else if (tmp & 0x4) {
  1014. /* run force svm */
  1015. if ((runed & 0x4) == 0) {
  1016. err = set_force_svm();
  1017. runed = runed | 0x4;
  1018. } else
  1019. err = 1;
  1020. } else if (tmp & 0x2) {
  1021. /* run allocate pasid */
  1022. if ((runed & 0x2) == 0) {
  1023. runed = runed | 0x2;
  1024. wq = allocate_dsa_pasid();
  1025. if (wq == MAP_FAILED)
  1026. err = 1;
  1027. } else
  1028. err = 1;
  1029. }
  1030. ret = ret + err;
  1031. if (ret > 0)
  1032. break;
  1033. tmp = tmp >> 4;
  1034. }
  1035. if (wq != MAP_FAILED && wq != NULL)
  1036. if (munmap(wq, 0x1000))
  1037. printf("munmap failed %d\n", errno);
  1038. if (runed != 0x7)
  1039. ret = 1;
  1040. return (ret != 0);
  1041. }
  1042. /*
  1043. * Pasid test depends on idxd and SVA, kernel should enable iommu and sm.
  1044. * command line(intel_iommu=on,sm_on)
  1045. */
  1046. static struct testcases pasid_cases[] = {
  1047. {
  1048. .expected = 1,
  1049. .cmd = PAS_CMD(LAM_CMD_BIT, PAS_CMD_BIT, SVA_CMD_BIT),
  1050. .test_func = handle_pasid,
  1051. .msg = "PASID: [Negative] Execute LAM, PASID, SVA in sequence\n",
  1052. },
  1053. {
  1054. .expected = 0,
  1055. .cmd = PAS_CMD(LAM_CMD_BIT, SVA_CMD_BIT, PAS_CMD_BIT),
  1056. .test_func = handle_pasid,
  1057. .msg = "PASID: Execute LAM, SVA, PASID in sequence\n",
  1058. },
  1059. {
  1060. .expected = 1,
  1061. .cmd = PAS_CMD(PAS_CMD_BIT, LAM_CMD_BIT, SVA_CMD_BIT),
  1062. .test_func = handle_pasid,
  1063. .msg = "PASID: [Negative] Execute PASID, LAM, SVA in sequence\n",
  1064. },
  1065. {
  1066. .expected = 0,
  1067. .cmd = PAS_CMD(PAS_CMD_BIT, SVA_CMD_BIT, LAM_CMD_BIT),
  1068. .test_func = handle_pasid,
  1069. .msg = "PASID: Execute PASID, SVA, LAM in sequence\n",
  1070. },
  1071. {
  1072. .expected = 0,
  1073. .cmd = PAS_CMD(SVA_CMD_BIT, LAM_CMD_BIT, PAS_CMD_BIT),
  1074. .test_func = handle_pasid,
  1075. .msg = "PASID: Execute SVA, LAM, PASID in sequence\n",
  1076. },
  1077. {
  1078. .expected = 0,
  1079. .cmd = PAS_CMD(SVA_CMD_BIT, PAS_CMD_BIT, LAM_CMD_BIT),
  1080. .test_func = handle_pasid,
  1081. .msg = "PASID: Execute SVA, PASID, LAM in sequence\n",
  1082. },
  1083. };
  1084. int main(int argc, char **argv)
  1085. {
  1086. int c = 0;
  1087. unsigned int tests = TEST_MASK;
  1088. tests_cnt = 0;
  1089. if (!lam_is_available())
  1090. return KSFT_SKIP;
  1091. while ((c = getopt(argc, argv, "ht:")) != -1) {
  1092. switch (c) {
  1093. case 't':
  1094. tests = strtoul(optarg, NULL, 16);
  1095. if (tests && !(tests & TEST_MASK)) {
  1096. ksft_print_msg("Invalid argument!\n");
  1097. return -1;
  1098. }
  1099. break;
  1100. case 'h':
  1101. cmd_help();
  1102. return 0;
  1103. default:
  1104. ksft_print_msg("Invalid argument\n");
  1105. return -1;
  1106. }
  1107. }
  1108. /*
  1109. * When tests is 0, it is not a real test case;
  1110. * the option used by test case(execve) to check the lam mode in
  1111. * process generated by execve, the process read back lam mode and
  1112. * check with lam mode in parent process.
  1113. */
  1114. if (!tests)
  1115. return (get_lam());
  1116. /* Run test cases */
  1117. if (tests & FUNC_MALLOC)
  1118. run_test(malloc_cases, ARRAY_SIZE(malloc_cases));
  1119. if (tests & FUNC_BITS)
  1120. run_test(bits_cases, ARRAY_SIZE(bits_cases));
  1121. if (tests & FUNC_MMAP)
  1122. run_test(mmap_cases, ARRAY_SIZE(mmap_cases));
  1123. if (tests & FUNC_SYSCALL)
  1124. run_test(syscall_cases, ARRAY_SIZE(syscall_cases));
  1125. if (tests & FUNC_URING)
  1126. run_test(uring_cases, ARRAY_SIZE(uring_cases));
  1127. if (tests & FUNC_INHERITE)
  1128. run_test(inheritance_cases, ARRAY_SIZE(inheritance_cases));
  1129. if (tests & FUNC_PASID)
  1130. run_test(pasid_cases, ARRAY_SIZE(pasid_cases));
  1131. ksft_set_plan(tests_cnt);
  1132. ksft_exit_pass();
  1133. }