uffd-unit-tests.c 40 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Userfaultfd unit tests.
  4. *
  5. * Copyright (C) 2015-2023 Red Hat, Inc.
  6. */
  7. #include "uffd-common.h"
  8. #include "../../../../mm/gup_test.h"
  9. #ifdef __NR_userfaultfd
  10. /* The unit test doesn't need a large or random size, make it 32MB for now */
  11. #define UFFD_TEST_MEM_SIZE (32UL << 20)
  12. #define MEM_ANON BIT_ULL(0)
  13. #define MEM_SHMEM BIT_ULL(1)
  14. #define MEM_SHMEM_PRIVATE BIT_ULL(2)
  15. #define MEM_HUGETLB BIT_ULL(3)
  16. #define MEM_HUGETLB_PRIVATE BIT_ULL(4)
  17. #define MEM_ALL (MEM_ANON | MEM_SHMEM | MEM_SHMEM_PRIVATE | \
  18. MEM_HUGETLB | MEM_HUGETLB_PRIVATE)
  19. #define ALIGN_UP(x, align_to) \
  20. ((__typeof__(x))((((unsigned long)(x)) + ((align_to)-1)) & ~((align_to)-1)))
  21. struct mem_type {
  22. const char *name;
  23. unsigned int mem_flag;
  24. uffd_test_ops_t *mem_ops;
  25. bool shared;
  26. };
  27. typedef struct mem_type mem_type_t;
  28. mem_type_t mem_types[] = {
  29. {
  30. .name = "anon",
  31. .mem_flag = MEM_ANON,
  32. .mem_ops = &anon_uffd_test_ops,
  33. .shared = false,
  34. },
  35. {
  36. .name = "shmem",
  37. .mem_flag = MEM_SHMEM,
  38. .mem_ops = &shmem_uffd_test_ops,
  39. .shared = true,
  40. },
  41. {
  42. .name = "shmem-private",
  43. .mem_flag = MEM_SHMEM_PRIVATE,
  44. .mem_ops = &shmem_uffd_test_ops,
  45. .shared = false,
  46. },
  47. {
  48. .name = "hugetlb",
  49. .mem_flag = MEM_HUGETLB,
  50. .mem_ops = &hugetlb_uffd_test_ops,
  51. .shared = true,
  52. },
  53. {
  54. .name = "hugetlb-private",
  55. .mem_flag = MEM_HUGETLB_PRIVATE,
  56. .mem_ops = &hugetlb_uffd_test_ops,
  57. .shared = false,
  58. },
  59. };
  60. /* Arguments to be passed over to each uffd unit test */
  61. struct uffd_test_args {
  62. mem_type_t *mem_type;
  63. };
  64. typedef struct uffd_test_args uffd_test_args_t;
  65. /* Returns: UFFD_TEST_* */
  66. typedef void (*uffd_test_fn)(uffd_test_args_t *);
  67. typedef struct {
  68. const char *name;
  69. uffd_test_fn uffd_fn;
  70. unsigned int mem_targets;
  71. uint64_t uffd_feature_required;
  72. uffd_test_case_ops_t *test_case_ops;
  73. } uffd_test_case_t;
  74. static void uffd_test_report(void)
  75. {
  76. printf("Userfaults unit tests: pass=%u, skip=%u, fail=%u (total=%u)\n",
  77. ksft_get_pass_cnt(),
  78. ksft_get_xskip_cnt(),
  79. ksft_get_fail_cnt(),
  80. ksft_test_num());
  81. }
  82. static void uffd_test_pass(void)
  83. {
  84. printf("done\n");
  85. ksft_inc_pass_cnt();
  86. }
  87. #define uffd_test_start(...) do { \
  88. printf("Testing "); \
  89. printf(__VA_ARGS__); \
  90. printf("... "); \
  91. fflush(stdout); \
  92. } while (0)
  93. #define uffd_test_fail(...) do { \
  94. printf("failed [reason: "); \
  95. printf(__VA_ARGS__); \
  96. printf("]\n"); \
  97. ksft_inc_fail_cnt(); \
  98. } while (0)
  99. static void uffd_test_skip(const char *message)
  100. {
  101. printf("skipped [reason: %s]\n", message);
  102. ksft_inc_xskip_cnt();
  103. }
  104. /*
  105. * Returns 1 if specific userfaultfd supported, 0 otherwise. Note, we'll
  106. * return 1 even if some test failed as long as uffd supported, because in
  107. * that case we still want to proceed with the rest uffd unit tests.
  108. */
  109. static int test_uffd_api(bool use_dev)
  110. {
  111. struct uffdio_api uffdio_api;
  112. int uffd;
  113. uffd_test_start("UFFDIO_API (with %s)",
  114. use_dev ? "/dev/userfaultfd" : "syscall");
  115. if (use_dev)
  116. uffd = uffd_open_dev(UFFD_FLAGS);
  117. else
  118. uffd = uffd_open_sys(UFFD_FLAGS);
  119. if (uffd < 0) {
  120. uffd_test_skip("cannot open userfaultfd handle");
  121. return 0;
  122. }
  123. /* Test wrong UFFD_API */
  124. uffdio_api.api = 0xab;
  125. uffdio_api.features = 0;
  126. if (ioctl(uffd, UFFDIO_API, &uffdio_api) == 0) {
  127. uffd_test_fail("UFFDIO_API should fail with wrong api but didn't");
  128. goto out;
  129. }
  130. /* Test wrong feature bit */
  131. uffdio_api.api = UFFD_API;
  132. uffdio_api.features = BIT_ULL(63);
  133. if (ioctl(uffd, UFFDIO_API, &uffdio_api) == 0) {
  134. uffd_test_fail("UFFDIO_API should fail with wrong feature but didn't");
  135. goto out;
  136. }
  137. /* Test normal UFFDIO_API */
  138. uffdio_api.api = UFFD_API;
  139. uffdio_api.features = 0;
  140. if (ioctl(uffd, UFFDIO_API, &uffdio_api)) {
  141. uffd_test_fail("UFFDIO_API should succeed but failed");
  142. goto out;
  143. }
  144. /* Test double requests of UFFDIO_API with a random feature set */
  145. uffdio_api.features = BIT_ULL(0);
  146. if (ioctl(uffd, UFFDIO_API, &uffdio_api) == 0) {
  147. uffd_test_fail("UFFDIO_API should reject initialized uffd");
  148. goto out;
  149. }
  150. uffd_test_pass();
  151. out:
  152. close(uffd);
  153. /* We have a valid uffd handle */
  154. return 1;
  155. }
  156. /*
  157. * This function initializes the global variables. TODO: remove global
  158. * vars and then remove this.
  159. */
  160. static int
  161. uffd_setup_environment(uffd_test_args_t *args, uffd_test_case_t *test,
  162. mem_type_t *mem_type, const char **errmsg)
  163. {
  164. map_shared = mem_type->shared;
  165. uffd_test_ops = mem_type->mem_ops;
  166. uffd_test_case_ops = test->test_case_ops;
  167. if (mem_type->mem_flag & (MEM_HUGETLB_PRIVATE | MEM_HUGETLB))
  168. page_size = default_huge_page_size();
  169. else
  170. page_size = psize();
  171. nr_pages = UFFD_TEST_MEM_SIZE / page_size;
  172. /* TODO: remove this global var.. it's so ugly */
  173. nr_cpus = 1;
  174. /* Initialize test arguments */
  175. args->mem_type = mem_type;
  176. return uffd_test_ctx_init(test->uffd_feature_required, errmsg);
  177. }
  178. static bool uffd_feature_supported(uffd_test_case_t *test)
  179. {
  180. uint64_t features;
  181. if (uffd_get_features(&features))
  182. return false;
  183. return (features & test->uffd_feature_required) ==
  184. test->uffd_feature_required;
  185. }
  186. static int pagemap_open(void)
  187. {
  188. int fd = open("/proc/self/pagemap", O_RDONLY);
  189. if (fd < 0)
  190. err("open pagemap");
  191. return fd;
  192. }
  193. /* This macro let __LINE__ works in err() */
  194. #define pagemap_check_wp(value, wp) do { \
  195. if (!!(value & PM_UFFD_WP) != wp) \
  196. err("pagemap uffd-wp bit error: 0x%"PRIx64, value); \
  197. } while (0)
  198. typedef struct {
  199. int parent_uffd, child_uffd;
  200. } fork_event_args;
  201. static void *fork_event_consumer(void *data)
  202. {
  203. fork_event_args *args = data;
  204. struct uffd_msg msg = { 0 };
  205. ready_for_fork = true;
  206. /* Read until a full msg received */
  207. while (uffd_read_msg(args->parent_uffd, &msg));
  208. if (msg.event != UFFD_EVENT_FORK)
  209. err("wrong message: %u\n", msg.event);
  210. /* Just to be properly freed later */
  211. args->child_uffd = msg.arg.fork.ufd;
  212. return NULL;
  213. }
  214. typedef struct {
  215. int gup_fd;
  216. bool pinned;
  217. } pin_args;
  218. /*
  219. * Returns 0 if succeed, <0 for errors. pin_pages() needs to be paired
  220. * with unpin_pages(). Currently it needs to be RO longterm pin to satisfy
  221. * all needs of the test cases (e.g., trigger unshare, trigger fork() early
  222. * CoW, etc.).
  223. */
  224. static int pin_pages(pin_args *args, void *buffer, size_t size)
  225. {
  226. struct pin_longterm_test test = {
  227. .addr = (uintptr_t)buffer,
  228. .size = size,
  229. /* Read-only pins */
  230. .flags = 0,
  231. };
  232. if (args->pinned)
  233. err("already pinned");
  234. args->gup_fd = open("/sys/kernel/debug/gup_test", O_RDWR);
  235. if (args->gup_fd < 0)
  236. return -errno;
  237. if (ioctl(args->gup_fd, PIN_LONGTERM_TEST_START, &test)) {
  238. /* Even if gup_test existed, can be an old gup_test / kernel */
  239. close(args->gup_fd);
  240. return -errno;
  241. }
  242. args->pinned = true;
  243. return 0;
  244. }
  245. static void unpin_pages(pin_args *args)
  246. {
  247. if (!args->pinned)
  248. err("unpin without pin first");
  249. if (ioctl(args->gup_fd, PIN_LONGTERM_TEST_STOP))
  250. err("PIN_LONGTERM_TEST_STOP");
  251. close(args->gup_fd);
  252. args->pinned = false;
  253. }
  254. static int pagemap_test_fork(int uffd, bool with_event, bool test_pin)
  255. {
  256. fork_event_args args = { .parent_uffd = uffd, .child_uffd = -1 };
  257. pthread_t thread;
  258. pid_t child;
  259. uint64_t value;
  260. int fd, result;
  261. /* Prepare a thread to resolve EVENT_FORK */
  262. if (with_event) {
  263. ready_for_fork = false;
  264. if (pthread_create(&thread, NULL, fork_event_consumer, &args))
  265. err("pthread_create()");
  266. while (!ready_for_fork)
  267. ; /* Wait for the poll_thread to start executing before forking */
  268. }
  269. child = fork();
  270. if (!child) {
  271. /* Open the pagemap fd of the child itself */
  272. pin_args args = {};
  273. fd = pagemap_open();
  274. if (test_pin && pin_pages(&args, area_dst, page_size))
  275. /*
  276. * Normally when reach here we have pinned in
  277. * previous tests, so shouldn't fail anymore
  278. */
  279. err("pin page failed in child");
  280. value = pagemap_get_entry(fd, area_dst);
  281. /*
  282. * After fork(), we should handle uffd-wp bit differently:
  283. *
  284. * (1) when with EVENT_FORK, it should persist
  285. * (2) when without EVENT_FORK, it should be dropped
  286. */
  287. pagemap_check_wp(value, with_event);
  288. if (test_pin)
  289. unpin_pages(&args);
  290. /* Succeed */
  291. exit(0);
  292. }
  293. waitpid(child, &result, 0);
  294. if (with_event) {
  295. if (pthread_join(thread, NULL))
  296. err("pthread_join()");
  297. if (args.child_uffd < 0)
  298. err("Didn't receive child uffd");
  299. close(args.child_uffd);
  300. }
  301. return result;
  302. }
  303. static void uffd_wp_unpopulated_test(uffd_test_args_t *args)
  304. {
  305. uint64_t value;
  306. int pagemap_fd;
  307. if (uffd_register(uffd, area_dst, nr_pages * page_size,
  308. false, true, false))
  309. err("register failed");
  310. pagemap_fd = pagemap_open();
  311. /* Test applying pte marker to anon unpopulated */
  312. wp_range(uffd, (uint64_t)area_dst, page_size, true);
  313. value = pagemap_get_entry(pagemap_fd, area_dst);
  314. pagemap_check_wp(value, true);
  315. /* Test unprotect on anon pte marker */
  316. wp_range(uffd, (uint64_t)area_dst, page_size, false);
  317. value = pagemap_get_entry(pagemap_fd, area_dst);
  318. pagemap_check_wp(value, false);
  319. /* Test zap on anon marker */
  320. wp_range(uffd, (uint64_t)area_dst, page_size, true);
  321. if (madvise(area_dst, page_size, MADV_DONTNEED))
  322. err("madvise(MADV_DONTNEED) failed");
  323. value = pagemap_get_entry(pagemap_fd, area_dst);
  324. pagemap_check_wp(value, false);
  325. /* Test fault in after marker removed */
  326. *area_dst = 1;
  327. value = pagemap_get_entry(pagemap_fd, area_dst);
  328. pagemap_check_wp(value, false);
  329. /* Drop it to make pte none again */
  330. if (madvise(area_dst, page_size, MADV_DONTNEED))
  331. err("madvise(MADV_DONTNEED) failed");
  332. /* Test read-zero-page upon pte marker */
  333. wp_range(uffd, (uint64_t)area_dst, page_size, true);
  334. *(volatile char *)area_dst;
  335. /* Drop it to make pte none again */
  336. if (madvise(area_dst, page_size, MADV_DONTNEED))
  337. err("madvise(MADV_DONTNEED) failed");
  338. uffd_test_pass();
  339. }
  340. static void uffd_wp_fork_test_common(uffd_test_args_t *args,
  341. bool with_event)
  342. {
  343. int pagemap_fd;
  344. uint64_t value;
  345. if (uffd_register(uffd, area_dst, nr_pages * page_size,
  346. false, true, false))
  347. err("register failed");
  348. pagemap_fd = pagemap_open();
  349. /* Touch the page */
  350. *area_dst = 1;
  351. wp_range(uffd, (uint64_t)area_dst, page_size, true);
  352. value = pagemap_get_entry(pagemap_fd, area_dst);
  353. pagemap_check_wp(value, true);
  354. if (pagemap_test_fork(uffd, with_event, false)) {
  355. uffd_test_fail("Detected %s uffd-wp bit in child in present pte",
  356. with_event ? "missing" : "stall");
  357. goto out;
  358. }
  359. /*
  360. * This is an attempt for zapping the pgtable so as to test the
  361. * markers.
  362. *
  363. * For private mappings, PAGEOUT will only work on exclusive ptes
  364. * (PM_MMAP_EXCLUSIVE) which we should satisfy.
  365. *
  366. * For shared, PAGEOUT may not work. Use DONTNEED instead which
  367. * plays a similar role of zapping (rather than freeing the page)
  368. * to expose pte markers.
  369. */
  370. if (args->mem_type->shared) {
  371. if (madvise(area_dst, page_size, MADV_DONTNEED))
  372. err("MADV_DONTNEED");
  373. } else {
  374. /*
  375. * NOTE: ignore retval because private-hugetlb doesn't yet
  376. * support swapping, so it could fail.
  377. */
  378. madvise(area_dst, page_size, MADV_PAGEOUT);
  379. }
  380. /* Uffd-wp should persist even swapped out */
  381. value = pagemap_get_entry(pagemap_fd, area_dst);
  382. pagemap_check_wp(value, true);
  383. if (pagemap_test_fork(uffd, with_event, false)) {
  384. uffd_test_fail("Detected %s uffd-wp bit in child in zapped pte",
  385. with_event ? "missing" : "stall");
  386. goto out;
  387. }
  388. /* Unprotect; this tests swap pte modifications */
  389. wp_range(uffd, (uint64_t)area_dst, page_size, false);
  390. value = pagemap_get_entry(pagemap_fd, area_dst);
  391. pagemap_check_wp(value, false);
  392. /* Fault in the page from disk */
  393. *area_dst = 2;
  394. value = pagemap_get_entry(pagemap_fd, area_dst);
  395. pagemap_check_wp(value, false);
  396. uffd_test_pass();
  397. out:
  398. if (uffd_unregister(uffd, area_dst, nr_pages * page_size))
  399. err("unregister failed");
  400. close(pagemap_fd);
  401. }
  402. static void uffd_wp_fork_test(uffd_test_args_t *args)
  403. {
  404. uffd_wp_fork_test_common(args, false);
  405. }
  406. static void uffd_wp_fork_with_event_test(uffd_test_args_t *args)
  407. {
  408. uffd_wp_fork_test_common(args, true);
  409. }
  410. static void uffd_wp_fork_pin_test_common(uffd_test_args_t *args,
  411. bool with_event)
  412. {
  413. int pagemap_fd;
  414. pin_args pin_args = {};
  415. if (uffd_register(uffd, area_dst, page_size, false, true, false))
  416. err("register failed");
  417. pagemap_fd = pagemap_open();
  418. /* Touch the page */
  419. *area_dst = 1;
  420. wp_range(uffd, (uint64_t)area_dst, page_size, true);
  421. /*
  422. * 1. First pin, then fork(). This tests fork() special path when
  423. * doing early CoW if the page is private.
  424. */
  425. if (pin_pages(&pin_args, area_dst, page_size)) {
  426. uffd_test_skip("Possibly CONFIG_GUP_TEST missing "
  427. "or unprivileged");
  428. close(pagemap_fd);
  429. uffd_unregister(uffd, area_dst, page_size);
  430. return;
  431. }
  432. if (pagemap_test_fork(uffd, with_event, false)) {
  433. uffd_test_fail("Detected %s uffd-wp bit in early CoW of fork()",
  434. with_event ? "missing" : "stall");
  435. unpin_pages(&pin_args);
  436. goto out;
  437. }
  438. unpin_pages(&pin_args);
  439. /*
  440. * 2. First fork(), then pin (in the child, where test_pin==true).
  441. * This tests COR, aka, page unsharing on private memories.
  442. */
  443. if (pagemap_test_fork(uffd, with_event, true)) {
  444. uffd_test_fail("Detected %s uffd-wp bit when RO pin",
  445. with_event ? "missing" : "stall");
  446. goto out;
  447. }
  448. uffd_test_pass();
  449. out:
  450. if (uffd_unregister(uffd, area_dst, page_size))
  451. err("register failed");
  452. close(pagemap_fd);
  453. }
  454. static void uffd_wp_fork_pin_test(uffd_test_args_t *args)
  455. {
  456. uffd_wp_fork_pin_test_common(args, false);
  457. }
  458. static void uffd_wp_fork_pin_with_event_test(uffd_test_args_t *args)
  459. {
  460. uffd_wp_fork_pin_test_common(args, true);
  461. }
  462. static void check_memory_contents(char *p)
  463. {
  464. unsigned long i, j;
  465. uint8_t expected_byte;
  466. for (i = 0; i < nr_pages; ++i) {
  467. expected_byte = ~((uint8_t)(i % ((uint8_t)-1)));
  468. for (j = 0; j < page_size; j++) {
  469. uint8_t v = *(uint8_t *)(p + (i * page_size) + j);
  470. if (v != expected_byte)
  471. err("unexpected page contents");
  472. }
  473. }
  474. }
  475. static void uffd_minor_test_common(bool test_collapse, bool test_wp)
  476. {
  477. unsigned long p;
  478. pthread_t uffd_mon;
  479. char c;
  480. struct uffd_args args = { 0 };
  481. /*
  482. * NOTE: MADV_COLLAPSE is not yet compatible with WP, so testing
  483. * both do not make much sense.
  484. */
  485. assert(!(test_collapse && test_wp));
  486. if (uffd_register(uffd, area_dst_alias, nr_pages * page_size,
  487. /* NOTE! MADV_COLLAPSE may not work with uffd-wp */
  488. false, test_wp, true))
  489. err("register failure");
  490. /*
  491. * After registering with UFFD, populate the non-UFFD-registered side of
  492. * the shared mapping. This should *not* trigger any UFFD minor faults.
  493. */
  494. for (p = 0; p < nr_pages; ++p)
  495. memset(area_dst + (p * page_size), p % ((uint8_t)-1),
  496. page_size);
  497. args.apply_wp = test_wp;
  498. if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
  499. err("uffd_poll_thread create");
  500. /*
  501. * Read each of the pages back using the UFFD-registered mapping. We
  502. * expect that the first time we touch a page, it will result in a minor
  503. * fault. uffd_poll_thread will resolve the fault by bit-flipping the
  504. * page's contents, and then issuing a CONTINUE ioctl.
  505. */
  506. check_memory_contents(area_dst_alias);
  507. if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
  508. err("pipe write");
  509. if (pthread_join(uffd_mon, NULL))
  510. err("join() failed");
  511. if (test_collapse) {
  512. if (madvise(area_dst_alias, nr_pages * page_size,
  513. MADV_COLLAPSE)) {
  514. /* It's fine to fail for this one... */
  515. uffd_test_skip("MADV_COLLAPSE failed");
  516. return;
  517. }
  518. uffd_test_ops->check_pmd_mapping(area_dst,
  519. nr_pages * page_size /
  520. read_pmd_pagesize());
  521. /*
  522. * This won't cause uffd-fault - it purely just makes sure there
  523. * was no corruption.
  524. */
  525. check_memory_contents(area_dst_alias);
  526. }
  527. if (args.missing_faults != 0 || args.minor_faults != nr_pages)
  528. uffd_test_fail("stats check error");
  529. else
  530. uffd_test_pass();
  531. }
  532. void uffd_minor_test(uffd_test_args_t *args)
  533. {
  534. uffd_minor_test_common(false, false);
  535. }
  536. void uffd_minor_wp_test(uffd_test_args_t *args)
  537. {
  538. uffd_minor_test_common(false, true);
  539. }
  540. void uffd_minor_collapse_test(uffd_test_args_t *args)
  541. {
  542. uffd_minor_test_common(true, false);
  543. }
  544. static sigjmp_buf jbuf, *sigbuf;
  545. static void sighndl(int sig, siginfo_t *siginfo, void *ptr)
  546. {
  547. if (sig == SIGBUS) {
  548. if (sigbuf)
  549. siglongjmp(*sigbuf, 1);
  550. abort();
  551. }
  552. }
  553. /*
  554. * For non-cooperative userfaultfd test we fork() a process that will
  555. * generate pagefaults, will mremap the area monitored by the
  556. * userfaultfd and at last this process will release the monitored
  557. * area.
  558. * For the anonymous and shared memory the area is divided into two
  559. * parts, the first part is accessed before mremap, and the second
  560. * part is accessed after mremap. Since hugetlbfs does not support
  561. * mremap, the entire monitored area is accessed in a single pass for
  562. * HUGETLB_TEST.
  563. * The release of the pages currently generates event for shmem and
  564. * anonymous memory (UFFD_EVENT_REMOVE), hence it is not checked
  565. * for hugetlb.
  566. * For signal test(UFFD_FEATURE_SIGBUS), signal_test = 1, we register
  567. * monitored area, generate pagefaults and test that signal is delivered.
  568. * Use UFFDIO_COPY to allocate missing page and retry. For signal_test = 2
  569. * test robustness use case - we release monitored area, fork a process
  570. * that will generate pagefaults and verify signal is generated.
  571. * This also tests UFFD_FEATURE_EVENT_FORK event along with the signal
  572. * feature. Using monitor thread, verify no userfault events are generated.
  573. */
  574. static int faulting_process(int signal_test, bool wp)
  575. {
  576. unsigned long nr, i;
  577. unsigned long long count;
  578. unsigned long split_nr_pages;
  579. unsigned long lastnr;
  580. struct sigaction act;
  581. volatile unsigned long signalled = 0;
  582. split_nr_pages = (nr_pages + 1) / 2;
  583. if (signal_test) {
  584. sigbuf = &jbuf;
  585. memset(&act, 0, sizeof(act));
  586. act.sa_sigaction = sighndl;
  587. act.sa_flags = SA_SIGINFO;
  588. if (sigaction(SIGBUS, &act, 0))
  589. err("sigaction");
  590. lastnr = (unsigned long)-1;
  591. }
  592. for (nr = 0; nr < split_nr_pages; nr++) {
  593. volatile int steps = 1;
  594. unsigned long offset = nr * page_size;
  595. if (signal_test) {
  596. if (sigsetjmp(*sigbuf, 1) != 0) {
  597. if (steps == 1 && nr == lastnr)
  598. err("Signal repeated");
  599. lastnr = nr;
  600. if (signal_test == 1) {
  601. if (steps == 1) {
  602. /* This is a MISSING request */
  603. steps++;
  604. if (copy_page(uffd, offset, wp))
  605. signalled++;
  606. } else {
  607. /* This is a WP request */
  608. assert(steps == 2);
  609. wp_range(uffd,
  610. (__u64)area_dst +
  611. offset,
  612. page_size, false);
  613. }
  614. } else {
  615. signalled++;
  616. continue;
  617. }
  618. }
  619. }
  620. count = *area_count(area_dst, nr);
  621. if (count != count_verify[nr])
  622. err("nr %lu memory corruption %llu %llu\n",
  623. nr, count, count_verify[nr]);
  624. /*
  625. * Trigger write protection if there is by writing
  626. * the same value back.
  627. */
  628. *area_count(area_dst, nr) = count;
  629. }
  630. if (signal_test)
  631. return signalled != split_nr_pages;
  632. area_dst = mremap(area_dst, nr_pages * page_size, nr_pages * page_size,
  633. MREMAP_MAYMOVE | MREMAP_FIXED, area_src);
  634. if (area_dst == MAP_FAILED)
  635. err("mremap");
  636. /* Reset area_src since we just clobbered it */
  637. area_src = NULL;
  638. for (; nr < nr_pages; nr++) {
  639. count = *area_count(area_dst, nr);
  640. if (count != count_verify[nr]) {
  641. err("nr %lu memory corruption %llu %llu\n",
  642. nr, count, count_verify[nr]);
  643. }
  644. /*
  645. * Trigger write protection if there is by writing
  646. * the same value back.
  647. */
  648. *area_count(area_dst, nr) = count;
  649. }
  650. uffd_test_ops->release_pages(area_dst);
  651. for (nr = 0; nr < nr_pages; nr++)
  652. for (i = 0; i < page_size; i++)
  653. if (*(area_dst + nr * page_size + i) != 0)
  654. err("page %lu offset %lu is not zero", nr, i);
  655. return 0;
  656. }
  657. static void uffd_sigbus_test_common(bool wp)
  658. {
  659. unsigned long userfaults;
  660. pthread_t uffd_mon;
  661. pid_t pid;
  662. int err;
  663. char c;
  664. struct uffd_args args = { 0 };
  665. ready_for_fork = false;
  666. fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
  667. if (uffd_register(uffd, area_dst, nr_pages * page_size,
  668. true, wp, false))
  669. err("register failure");
  670. if (faulting_process(1, wp))
  671. err("faulting process failed");
  672. uffd_test_ops->release_pages(area_dst);
  673. args.apply_wp = wp;
  674. if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
  675. err("uffd_poll_thread create");
  676. while (!ready_for_fork)
  677. ; /* Wait for the poll_thread to start executing before forking */
  678. pid = fork();
  679. if (pid < 0)
  680. err("fork");
  681. if (!pid)
  682. exit(faulting_process(2, wp));
  683. waitpid(pid, &err, 0);
  684. if (err)
  685. err("faulting process failed");
  686. if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
  687. err("pipe write");
  688. if (pthread_join(uffd_mon, (void **)&userfaults))
  689. err("pthread_join()");
  690. if (userfaults)
  691. uffd_test_fail("Signal test failed, userfaults: %ld", userfaults);
  692. else
  693. uffd_test_pass();
  694. }
  695. static void uffd_sigbus_test(uffd_test_args_t *args)
  696. {
  697. uffd_sigbus_test_common(false);
  698. }
  699. static void uffd_sigbus_wp_test(uffd_test_args_t *args)
  700. {
  701. uffd_sigbus_test_common(true);
  702. }
  703. static void uffd_events_test_common(bool wp)
  704. {
  705. pthread_t uffd_mon;
  706. pid_t pid;
  707. int err;
  708. char c;
  709. struct uffd_args args = { 0 };
  710. ready_for_fork = false;
  711. fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
  712. if (uffd_register(uffd, area_dst, nr_pages * page_size,
  713. true, wp, false))
  714. err("register failure");
  715. args.apply_wp = wp;
  716. if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
  717. err("uffd_poll_thread create");
  718. while (!ready_for_fork)
  719. ; /* Wait for the poll_thread to start executing before forking */
  720. pid = fork();
  721. if (pid < 0)
  722. err("fork");
  723. if (!pid)
  724. exit(faulting_process(0, wp));
  725. waitpid(pid, &err, 0);
  726. if (err)
  727. err("faulting process failed");
  728. if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
  729. err("pipe write");
  730. if (pthread_join(uffd_mon, NULL))
  731. err("pthread_join()");
  732. if (args.missing_faults != nr_pages)
  733. uffd_test_fail("Fault counts wrong");
  734. else
  735. uffd_test_pass();
  736. }
  737. static void uffd_events_test(uffd_test_args_t *args)
  738. {
  739. uffd_events_test_common(false);
  740. }
  741. static void uffd_events_wp_test(uffd_test_args_t *args)
  742. {
  743. uffd_events_test_common(true);
  744. }
  745. static void retry_uffdio_zeropage(int ufd,
  746. struct uffdio_zeropage *uffdio_zeropage)
  747. {
  748. uffd_test_ops->alias_mapping(&uffdio_zeropage->range.start,
  749. uffdio_zeropage->range.len,
  750. 0);
  751. if (ioctl(ufd, UFFDIO_ZEROPAGE, uffdio_zeropage)) {
  752. if (uffdio_zeropage->zeropage != -EEXIST)
  753. err("UFFDIO_ZEROPAGE error: %"PRId64,
  754. (int64_t)uffdio_zeropage->zeropage);
  755. } else {
  756. err("UFFDIO_ZEROPAGE error: %"PRId64,
  757. (int64_t)uffdio_zeropage->zeropage);
  758. }
  759. }
  760. static bool do_uffdio_zeropage(int ufd, bool has_zeropage)
  761. {
  762. struct uffdio_zeropage uffdio_zeropage = { 0 };
  763. int ret;
  764. __s64 res;
  765. uffdio_zeropage.range.start = (unsigned long) area_dst;
  766. uffdio_zeropage.range.len = page_size;
  767. uffdio_zeropage.mode = 0;
  768. ret = ioctl(ufd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
  769. res = uffdio_zeropage.zeropage;
  770. if (ret) {
  771. /* real retval in ufdio_zeropage.zeropage */
  772. if (has_zeropage)
  773. err("UFFDIO_ZEROPAGE error: %"PRId64, (int64_t)res);
  774. else if (res != -EINVAL)
  775. err("UFFDIO_ZEROPAGE not -EINVAL");
  776. } else if (has_zeropage) {
  777. if (res != page_size)
  778. err("UFFDIO_ZEROPAGE unexpected size");
  779. else
  780. retry_uffdio_zeropage(ufd, &uffdio_zeropage);
  781. return true;
  782. } else
  783. err("UFFDIO_ZEROPAGE succeeded");
  784. return false;
  785. }
  786. /*
  787. * Registers a range with MISSING mode only for zeropage test. Return true
  788. * if UFFDIO_ZEROPAGE supported, false otherwise. Can't use uffd_register()
  789. * because we want to detect .ioctls along the way.
  790. */
  791. static bool
  792. uffd_register_detect_zeropage(int uffd, void *addr, uint64_t len)
  793. {
  794. uint64_t ioctls = 0;
  795. if (uffd_register_with_ioctls(uffd, addr, len, true,
  796. false, false, &ioctls))
  797. err("zeropage register fail");
  798. return ioctls & (1 << _UFFDIO_ZEROPAGE);
  799. }
  800. /* exercise UFFDIO_ZEROPAGE */
  801. static void uffd_zeropage_test(uffd_test_args_t *args)
  802. {
  803. bool has_zeropage;
  804. int i;
  805. has_zeropage = uffd_register_detect_zeropage(uffd, area_dst, page_size);
  806. if (area_dst_alias)
  807. /* Ignore the retval; we already have it */
  808. uffd_register_detect_zeropage(uffd, area_dst_alias, page_size);
  809. if (do_uffdio_zeropage(uffd, has_zeropage))
  810. for (i = 0; i < page_size; i++)
  811. if (area_dst[i] != 0)
  812. err("data non-zero at offset %d\n", i);
  813. if (uffd_unregister(uffd, area_dst, page_size))
  814. err("unregister");
  815. if (area_dst_alias && uffd_unregister(uffd, area_dst_alias, page_size))
  816. err("unregister");
  817. uffd_test_pass();
  818. }
  819. static void uffd_register_poison(int uffd, void *addr, uint64_t len)
  820. {
  821. uint64_t ioctls = 0;
  822. uint64_t expected = (1 << _UFFDIO_COPY) | (1 << _UFFDIO_POISON);
  823. if (uffd_register_with_ioctls(uffd, addr, len, true,
  824. false, false, &ioctls))
  825. err("poison register fail");
  826. if ((ioctls & expected) != expected)
  827. err("registered area doesn't support COPY and POISON ioctls");
  828. }
  829. static void do_uffdio_poison(int uffd, unsigned long offset)
  830. {
  831. struct uffdio_poison uffdio_poison = { 0 };
  832. int ret;
  833. __s64 res;
  834. uffdio_poison.range.start = (unsigned long) area_dst + offset;
  835. uffdio_poison.range.len = page_size;
  836. uffdio_poison.mode = 0;
  837. ret = ioctl(uffd, UFFDIO_POISON, &uffdio_poison);
  838. res = uffdio_poison.updated;
  839. if (ret)
  840. err("UFFDIO_POISON error: %"PRId64, (int64_t)res);
  841. else if (res != page_size)
  842. err("UFFDIO_POISON unexpected size: %"PRId64, (int64_t)res);
  843. }
  844. static void uffd_poison_handle_fault(
  845. struct uffd_msg *msg, struct uffd_args *args)
  846. {
  847. unsigned long offset;
  848. if (msg->event != UFFD_EVENT_PAGEFAULT)
  849. err("unexpected msg event %u", msg->event);
  850. if (msg->arg.pagefault.flags &
  851. (UFFD_PAGEFAULT_FLAG_WP | UFFD_PAGEFAULT_FLAG_MINOR))
  852. err("unexpected fault type %llu", msg->arg.pagefault.flags);
  853. offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
  854. offset &= ~(page_size-1);
  855. /* Odd pages -> copy zeroed page; even pages -> poison. */
  856. if (offset & page_size)
  857. copy_page(uffd, offset, false);
  858. else
  859. do_uffdio_poison(uffd, offset);
  860. }
  861. static void uffd_poison_test(uffd_test_args_t *targs)
  862. {
  863. pthread_t uffd_mon;
  864. char c;
  865. struct uffd_args args = { 0 };
  866. struct sigaction act = { 0 };
  867. unsigned long nr_sigbus = 0;
  868. unsigned long nr;
  869. fcntl(uffd, F_SETFL, uffd_flags | O_NONBLOCK);
  870. uffd_register_poison(uffd, area_dst, nr_pages * page_size);
  871. memset(area_src, 0, nr_pages * page_size);
  872. args.handle_fault = uffd_poison_handle_fault;
  873. if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
  874. err("uffd_poll_thread create");
  875. sigbuf = &jbuf;
  876. act.sa_sigaction = sighndl;
  877. act.sa_flags = SA_SIGINFO;
  878. if (sigaction(SIGBUS, &act, 0))
  879. err("sigaction");
  880. for (nr = 0; nr < nr_pages; ++nr) {
  881. unsigned long offset = nr * page_size;
  882. const char *bytes = (const char *) area_dst + offset;
  883. const char *i;
  884. if (sigsetjmp(*sigbuf, 1)) {
  885. /*
  886. * Access below triggered a SIGBUS, which was caught by
  887. * sighndl, which then jumped here. Count this SIGBUS,
  888. * and move on to next page.
  889. */
  890. ++nr_sigbus;
  891. continue;
  892. }
  893. for (i = bytes; i < bytes + page_size; ++i) {
  894. if (*i)
  895. err("nonzero byte in area_dst (%p) at %p: %u",
  896. area_dst, i, *i);
  897. }
  898. }
  899. if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
  900. err("pipe write");
  901. if (pthread_join(uffd_mon, NULL))
  902. err("pthread_join()");
  903. if (nr_sigbus != nr_pages / 2)
  904. err("expected to receive %lu SIGBUS, actually received %lu",
  905. nr_pages / 2, nr_sigbus);
  906. uffd_test_pass();
  907. }
  908. static void
  909. uffd_move_handle_fault_common(struct uffd_msg *msg, struct uffd_args *args,
  910. unsigned long len)
  911. {
  912. unsigned long offset;
  913. if (msg->event != UFFD_EVENT_PAGEFAULT)
  914. err("unexpected msg event %u", msg->event);
  915. if (msg->arg.pagefault.flags &
  916. (UFFD_PAGEFAULT_FLAG_WP | UFFD_PAGEFAULT_FLAG_MINOR | UFFD_PAGEFAULT_FLAG_WRITE))
  917. err("unexpected fault type %llu", msg->arg.pagefault.flags);
  918. offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
  919. offset &= ~(len-1);
  920. if (move_page(uffd, offset, len))
  921. args->missing_faults++;
  922. }
  923. static void uffd_move_handle_fault(struct uffd_msg *msg,
  924. struct uffd_args *args)
  925. {
  926. uffd_move_handle_fault_common(msg, args, page_size);
  927. }
  928. static void uffd_move_pmd_handle_fault(struct uffd_msg *msg,
  929. struct uffd_args *args)
  930. {
  931. uffd_move_handle_fault_common(msg, args, read_pmd_pagesize());
  932. }
  933. static void
  934. uffd_move_test_common(uffd_test_args_t *targs, unsigned long chunk_size,
  935. void (*handle_fault)(struct uffd_msg *msg, struct uffd_args *args))
  936. {
  937. unsigned long nr;
  938. pthread_t uffd_mon;
  939. char c;
  940. unsigned long long count;
  941. struct uffd_args args = { 0 };
  942. char *orig_area_src, *orig_area_dst;
  943. unsigned long step_size, step_count;
  944. unsigned long src_offs = 0;
  945. unsigned long dst_offs = 0;
  946. /* Prevent source pages from being mapped more than once */
  947. if (madvise(area_src, nr_pages * page_size, MADV_DONTFORK))
  948. err("madvise(MADV_DONTFORK) failure");
  949. if (uffd_register(uffd, area_dst, nr_pages * page_size,
  950. true, false, false))
  951. err("register failure");
  952. args.handle_fault = handle_fault;
  953. if (pthread_create(&uffd_mon, NULL, uffd_poll_thread, &args))
  954. err("uffd_poll_thread create");
  955. step_size = chunk_size / page_size;
  956. step_count = nr_pages / step_size;
  957. if (chunk_size > page_size) {
  958. char *aligned_src = ALIGN_UP(area_src, chunk_size);
  959. char *aligned_dst = ALIGN_UP(area_dst, chunk_size);
  960. if (aligned_src != area_src || aligned_dst != area_dst) {
  961. src_offs = (aligned_src - area_src) / page_size;
  962. dst_offs = (aligned_dst - area_dst) / page_size;
  963. step_count--;
  964. }
  965. orig_area_src = area_src;
  966. orig_area_dst = area_dst;
  967. area_src = aligned_src;
  968. area_dst = aligned_dst;
  969. }
  970. /*
  971. * Read each of the pages back using the UFFD-registered mapping. We
  972. * expect that the first time we touch a page, it will result in a missing
  973. * fault. uffd_poll_thread will resolve the fault by moving source
  974. * page to destination.
  975. */
  976. for (nr = 0; nr < step_count * step_size; nr += step_size) {
  977. unsigned long i;
  978. /* Check area_src content */
  979. for (i = 0; i < step_size; i++) {
  980. count = *area_count(area_src, nr + i);
  981. if (count != count_verify[src_offs + nr + i])
  982. err("nr %lu source memory invalid %llu %llu\n",
  983. nr + i, count, count_verify[src_offs + nr + i]);
  984. }
  985. /* Faulting into area_dst should move the page or the huge page */
  986. for (i = 0; i < step_size; i++) {
  987. count = *area_count(area_dst, nr + i);
  988. if (count != count_verify[dst_offs + nr + i])
  989. err("nr %lu memory corruption %llu %llu\n",
  990. nr, count, count_verify[dst_offs + nr + i]);
  991. }
  992. /* Re-check area_src content which should be empty */
  993. for (i = 0; i < step_size; i++) {
  994. count = *area_count(area_src, nr + i);
  995. if (count != 0)
  996. err("nr %lu move failed %llu %llu\n",
  997. nr, count, count_verify[src_offs + nr + i]);
  998. }
  999. }
  1000. if (step_size > page_size) {
  1001. area_src = orig_area_src;
  1002. area_dst = orig_area_dst;
  1003. }
  1004. if (write(pipefd[1], &c, sizeof(c)) != sizeof(c))
  1005. err("pipe write");
  1006. if (pthread_join(uffd_mon, NULL))
  1007. err("join() failed");
  1008. if (args.missing_faults != step_count || args.minor_faults != 0)
  1009. uffd_test_fail("stats check error");
  1010. else
  1011. uffd_test_pass();
  1012. }
  1013. static void uffd_move_test(uffd_test_args_t *targs)
  1014. {
  1015. uffd_move_test_common(targs, page_size, uffd_move_handle_fault);
  1016. }
  1017. static void uffd_move_pmd_test(uffd_test_args_t *targs)
  1018. {
  1019. if (madvise(area_dst, nr_pages * page_size, MADV_HUGEPAGE))
  1020. err("madvise(MADV_HUGEPAGE) failure");
  1021. uffd_move_test_common(targs, read_pmd_pagesize(),
  1022. uffd_move_pmd_handle_fault);
  1023. }
  1024. static void uffd_move_pmd_split_test(uffd_test_args_t *targs)
  1025. {
  1026. if (madvise(area_dst, nr_pages * page_size, MADV_NOHUGEPAGE))
  1027. err("madvise(MADV_NOHUGEPAGE) failure");
  1028. uffd_move_test_common(targs, read_pmd_pagesize(),
  1029. uffd_move_pmd_handle_fault);
  1030. }
  1031. static int prevent_hugepages(const char **errmsg)
  1032. {
  1033. /* This should be done before source area is populated */
  1034. if (madvise(area_src, nr_pages * page_size, MADV_NOHUGEPAGE)) {
  1035. /* Ignore only if CONFIG_TRANSPARENT_HUGEPAGE=n */
  1036. if (errno != EINVAL) {
  1037. if (errmsg)
  1038. *errmsg = "madvise(MADV_NOHUGEPAGE) failed";
  1039. return -errno;
  1040. }
  1041. }
  1042. return 0;
  1043. }
  1044. static int request_hugepages(const char **errmsg)
  1045. {
  1046. /* This should be done before source area is populated */
  1047. if (madvise(area_src, nr_pages * page_size, MADV_HUGEPAGE)) {
  1048. if (errmsg) {
  1049. *errmsg = (errno == EINVAL) ?
  1050. "CONFIG_TRANSPARENT_HUGEPAGE is not set" :
  1051. "madvise(MADV_HUGEPAGE) failed";
  1052. }
  1053. return -errno;
  1054. }
  1055. return 0;
  1056. }
  1057. struct uffd_test_case_ops uffd_move_test_case_ops = {
  1058. .post_alloc = prevent_hugepages,
  1059. };
  1060. struct uffd_test_case_ops uffd_move_test_pmd_case_ops = {
  1061. .post_alloc = request_hugepages,
  1062. };
  1063. /*
  1064. * Test the returned uffdio_register.ioctls with different register modes.
  1065. * Note that _UFFDIO_ZEROPAGE is tested separately in the zeropage test.
  1066. */
  1067. static void
  1068. do_register_ioctls_test(uffd_test_args_t *args, bool miss, bool wp, bool minor)
  1069. {
  1070. uint64_t ioctls = 0, expected = BIT_ULL(_UFFDIO_WAKE);
  1071. mem_type_t *mem_type = args->mem_type;
  1072. int ret;
  1073. ret = uffd_register_with_ioctls(uffd, area_dst, page_size,
  1074. miss, wp, minor, &ioctls);
  1075. /*
  1076. * Handle special cases of UFFDIO_REGISTER here where it should
  1077. * just fail with -EINVAL first..
  1078. *
  1079. * Case 1: register MINOR on anon
  1080. * Case 2: register with no mode selected
  1081. */
  1082. if ((minor && (mem_type->mem_flag == MEM_ANON)) ||
  1083. (!miss && !wp && !minor)) {
  1084. if (ret != -EINVAL)
  1085. err("register (miss=%d, wp=%d, minor=%d) failed "
  1086. "with wrong errno=%d", miss, wp, minor, ret);
  1087. return;
  1088. }
  1089. /* UFFDIO_REGISTER should succeed, then check ioctls returned */
  1090. if (miss)
  1091. expected |= BIT_ULL(_UFFDIO_COPY);
  1092. if (wp)
  1093. expected |= BIT_ULL(_UFFDIO_WRITEPROTECT);
  1094. if (minor)
  1095. expected |= BIT_ULL(_UFFDIO_CONTINUE);
  1096. if ((ioctls & expected) != expected)
  1097. err("unexpected uffdio_register.ioctls "
  1098. "(miss=%d, wp=%d, minor=%d): expected=0x%"PRIx64", "
  1099. "returned=0x%"PRIx64, miss, wp, minor, expected, ioctls);
  1100. if (uffd_unregister(uffd, area_dst, page_size))
  1101. err("unregister");
  1102. }
  1103. static void uffd_register_ioctls_test(uffd_test_args_t *args)
  1104. {
  1105. int miss, wp, minor;
  1106. for (miss = 0; miss <= 1; miss++)
  1107. for (wp = 0; wp <= 1; wp++)
  1108. for (minor = 0; minor <= 1; minor++)
  1109. do_register_ioctls_test(args, miss, wp, minor);
  1110. uffd_test_pass();
  1111. }
  1112. uffd_test_case_t uffd_tests[] = {
  1113. {
  1114. /* Test returned uffdio_register.ioctls. */
  1115. .name = "register-ioctls",
  1116. .uffd_fn = uffd_register_ioctls_test,
  1117. .mem_targets = MEM_ALL,
  1118. .uffd_feature_required = UFFD_FEATURE_MISSING_HUGETLBFS |
  1119. UFFD_FEATURE_MISSING_SHMEM |
  1120. UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1121. UFFD_FEATURE_WP_HUGETLBFS_SHMEM |
  1122. UFFD_FEATURE_MINOR_HUGETLBFS |
  1123. UFFD_FEATURE_MINOR_SHMEM,
  1124. },
  1125. {
  1126. .name = "zeropage",
  1127. .uffd_fn = uffd_zeropage_test,
  1128. .mem_targets = MEM_ALL,
  1129. .uffd_feature_required = 0,
  1130. },
  1131. {
  1132. .name = "move",
  1133. .uffd_fn = uffd_move_test,
  1134. .mem_targets = MEM_ANON,
  1135. .uffd_feature_required = UFFD_FEATURE_MOVE,
  1136. .test_case_ops = &uffd_move_test_case_ops,
  1137. },
  1138. {
  1139. .name = "move-pmd",
  1140. .uffd_fn = uffd_move_pmd_test,
  1141. .mem_targets = MEM_ANON,
  1142. .uffd_feature_required = UFFD_FEATURE_MOVE,
  1143. .test_case_ops = &uffd_move_test_pmd_case_ops,
  1144. },
  1145. {
  1146. .name = "move-pmd-split",
  1147. .uffd_fn = uffd_move_pmd_split_test,
  1148. .mem_targets = MEM_ANON,
  1149. .uffd_feature_required = UFFD_FEATURE_MOVE,
  1150. .test_case_ops = &uffd_move_test_pmd_case_ops,
  1151. },
  1152. {
  1153. .name = "wp-fork",
  1154. .uffd_fn = uffd_wp_fork_test,
  1155. .mem_targets = MEM_ALL,
  1156. .uffd_feature_required = UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1157. UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
  1158. },
  1159. {
  1160. .name = "wp-fork-with-event",
  1161. .uffd_fn = uffd_wp_fork_with_event_test,
  1162. .mem_targets = MEM_ALL,
  1163. .uffd_feature_required = UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1164. UFFD_FEATURE_WP_HUGETLBFS_SHMEM |
  1165. /* when set, child process should inherit uffd-wp bits */
  1166. UFFD_FEATURE_EVENT_FORK,
  1167. },
  1168. {
  1169. .name = "wp-fork-pin",
  1170. .uffd_fn = uffd_wp_fork_pin_test,
  1171. .mem_targets = MEM_ALL,
  1172. .uffd_feature_required = UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1173. UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
  1174. },
  1175. {
  1176. .name = "wp-fork-pin-with-event",
  1177. .uffd_fn = uffd_wp_fork_pin_with_event_test,
  1178. .mem_targets = MEM_ALL,
  1179. .uffd_feature_required = UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1180. UFFD_FEATURE_WP_HUGETLBFS_SHMEM |
  1181. /* when set, child process should inherit uffd-wp bits */
  1182. UFFD_FEATURE_EVENT_FORK,
  1183. },
  1184. {
  1185. .name = "wp-unpopulated",
  1186. .uffd_fn = uffd_wp_unpopulated_test,
  1187. .mem_targets = MEM_ANON,
  1188. .uffd_feature_required =
  1189. UFFD_FEATURE_PAGEFAULT_FLAG_WP | UFFD_FEATURE_WP_UNPOPULATED,
  1190. },
  1191. {
  1192. .name = "minor",
  1193. .uffd_fn = uffd_minor_test,
  1194. .mem_targets = MEM_SHMEM | MEM_HUGETLB,
  1195. .uffd_feature_required =
  1196. UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM,
  1197. },
  1198. {
  1199. .name = "minor-wp",
  1200. .uffd_fn = uffd_minor_wp_test,
  1201. .mem_targets = MEM_SHMEM | MEM_HUGETLB,
  1202. .uffd_feature_required =
  1203. UFFD_FEATURE_MINOR_HUGETLBFS | UFFD_FEATURE_MINOR_SHMEM |
  1204. UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1205. /*
  1206. * HACK: here we leveraged WP_UNPOPULATED to detect whether
  1207. * minor mode supports wr-protect. There's no feature flag
  1208. * for it so this is the best we can test against.
  1209. */
  1210. UFFD_FEATURE_WP_UNPOPULATED,
  1211. },
  1212. {
  1213. .name = "minor-collapse",
  1214. .uffd_fn = uffd_minor_collapse_test,
  1215. /* MADV_COLLAPSE only works with shmem */
  1216. .mem_targets = MEM_SHMEM,
  1217. /* We can't test MADV_COLLAPSE, so try our luck */
  1218. .uffd_feature_required = UFFD_FEATURE_MINOR_SHMEM,
  1219. },
  1220. {
  1221. .name = "sigbus",
  1222. .uffd_fn = uffd_sigbus_test,
  1223. .mem_targets = MEM_ALL,
  1224. .uffd_feature_required = UFFD_FEATURE_SIGBUS |
  1225. UFFD_FEATURE_EVENT_FORK,
  1226. },
  1227. {
  1228. .name = "sigbus-wp",
  1229. .uffd_fn = uffd_sigbus_wp_test,
  1230. .mem_targets = MEM_ALL,
  1231. .uffd_feature_required = UFFD_FEATURE_SIGBUS |
  1232. UFFD_FEATURE_EVENT_FORK | UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1233. UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
  1234. },
  1235. {
  1236. .name = "events",
  1237. .uffd_fn = uffd_events_test,
  1238. .mem_targets = MEM_ALL,
  1239. .uffd_feature_required = UFFD_FEATURE_EVENT_FORK |
  1240. UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE,
  1241. },
  1242. {
  1243. .name = "events-wp",
  1244. .uffd_fn = uffd_events_wp_test,
  1245. .mem_targets = MEM_ALL,
  1246. .uffd_feature_required = UFFD_FEATURE_EVENT_FORK |
  1247. UFFD_FEATURE_EVENT_REMAP | UFFD_FEATURE_EVENT_REMOVE |
  1248. UFFD_FEATURE_PAGEFAULT_FLAG_WP |
  1249. UFFD_FEATURE_WP_HUGETLBFS_SHMEM,
  1250. },
  1251. {
  1252. .name = "poison",
  1253. .uffd_fn = uffd_poison_test,
  1254. .mem_targets = MEM_ALL,
  1255. .uffd_feature_required = UFFD_FEATURE_POISON,
  1256. },
  1257. };
  1258. static void usage(const char *prog)
  1259. {
  1260. printf("usage: %s [-f TESTNAME]\n", prog);
  1261. puts("");
  1262. puts(" -f: test name to filter (e.g., event)");
  1263. puts(" -h: show the help msg");
  1264. puts(" -l: list tests only");
  1265. puts("");
  1266. exit(KSFT_FAIL);
  1267. }
  1268. int main(int argc, char *argv[])
  1269. {
  1270. int n_tests = sizeof(uffd_tests) / sizeof(uffd_test_case_t);
  1271. int n_mems = sizeof(mem_types) / sizeof(mem_type_t);
  1272. const char *test_filter = NULL;
  1273. bool list_only = false;
  1274. uffd_test_case_t *test;
  1275. mem_type_t *mem_type;
  1276. uffd_test_args_t args;
  1277. const char *errmsg;
  1278. int has_uffd, opt;
  1279. int i, j;
  1280. while ((opt = getopt(argc, argv, "f:hl")) != -1) {
  1281. switch (opt) {
  1282. case 'f':
  1283. test_filter = optarg;
  1284. break;
  1285. case 'l':
  1286. list_only = true;
  1287. break;
  1288. case 'h':
  1289. default:
  1290. /* Unknown */
  1291. usage(argv[0]);
  1292. break;
  1293. }
  1294. }
  1295. if (!test_filter && !list_only) {
  1296. has_uffd = test_uffd_api(false);
  1297. has_uffd |= test_uffd_api(true);
  1298. if (!has_uffd) {
  1299. printf("Userfaultfd not supported or unprivileged, skip all tests\n");
  1300. exit(KSFT_SKIP);
  1301. }
  1302. }
  1303. for (i = 0; i < n_tests; i++) {
  1304. test = &uffd_tests[i];
  1305. if (test_filter && !strstr(test->name, test_filter))
  1306. continue;
  1307. if (list_only) {
  1308. printf("%s\n", test->name);
  1309. continue;
  1310. }
  1311. for (j = 0; j < n_mems; j++) {
  1312. mem_type = &mem_types[j];
  1313. if (!(test->mem_targets & mem_type->mem_flag))
  1314. continue;
  1315. uffd_test_start("%s on %s", test->name, mem_type->name);
  1316. if ((mem_type->mem_flag == MEM_HUGETLB ||
  1317. mem_type->mem_flag == MEM_HUGETLB_PRIVATE) &&
  1318. (default_huge_page_size() == 0)) {
  1319. uffd_test_skip("huge page size is 0, feature missing?");
  1320. continue;
  1321. }
  1322. if (!uffd_feature_supported(test)) {
  1323. uffd_test_skip("feature missing");
  1324. continue;
  1325. }
  1326. if (uffd_setup_environment(&args, test, mem_type,
  1327. &errmsg)) {
  1328. uffd_test_skip(errmsg);
  1329. continue;
  1330. }
  1331. test->uffd_fn(&args);
  1332. uffd_test_ctx_clear();
  1333. }
  1334. }
  1335. if (!list_only)
  1336. uffd_test_report();
  1337. return ksft_get_fail_cnt() ? KSFT_FAIL : KSFT_PASS;
  1338. }
  1339. #else /* __NR_userfaultfd */
  1340. #warning "missing __NR_userfaultfd definition"
  1341. int main(void)
  1342. {
  1343. printf("Skipping %s (missing __NR_userfaultfd)\n", __file__);
  1344. return KSFT_SKIP;
  1345. }
  1346. #endif /* __NR_userfaultfd */