uffd-common.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * Userfaultfd tests util functions
  4. *
  5. * Copyright (C) 2015-2023 Red Hat, Inc.
  6. */
  7. #include "uffd-common.h"
  8. #define BASE_PMD_ADDR ((void *)(1UL << 30))
  9. volatile bool test_uffdio_copy_eexist = true;
  10. unsigned long nr_cpus, nr_pages, nr_pages_per_cpu, page_size;
  11. char *area_src, *area_src_alias, *area_dst, *area_dst_alias, *area_remap;
  12. int uffd = -1, uffd_flags, finished, *pipefd, test_type;
  13. bool map_shared;
  14. bool test_uffdio_wp = true;
  15. unsigned long long *count_verify;
  16. uffd_test_ops_t *uffd_test_ops;
  17. uffd_test_case_ops_t *uffd_test_case_ops;
  18. atomic_bool ready_for_fork;
  19. static int uffd_mem_fd_create(off_t mem_size, bool hugetlb)
  20. {
  21. unsigned int memfd_flags = 0;
  22. int mem_fd;
  23. if (hugetlb)
  24. memfd_flags = MFD_HUGETLB;
  25. mem_fd = memfd_create("uffd-test", memfd_flags);
  26. if (mem_fd < 0)
  27. err("memfd_create");
  28. if (ftruncate(mem_fd, mem_size))
  29. err("ftruncate");
  30. if (fallocate(mem_fd,
  31. FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE, 0,
  32. mem_size))
  33. err("fallocate");
  34. return mem_fd;
  35. }
  36. static void anon_release_pages(char *rel_area)
  37. {
  38. if (madvise(rel_area, nr_pages * page_size, MADV_DONTNEED))
  39. err("madvise(MADV_DONTNEED) failed");
  40. }
  41. static int anon_allocate_area(void **alloc_area, bool is_src)
  42. {
  43. *alloc_area = mmap(NULL, nr_pages * page_size, PROT_READ | PROT_WRITE,
  44. MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
  45. if (*alloc_area == MAP_FAILED) {
  46. *alloc_area = NULL;
  47. return -errno;
  48. }
  49. return 0;
  50. }
  51. static void noop_alias_mapping(__u64 *start, size_t len, unsigned long offset)
  52. {
  53. }
  54. static void hugetlb_release_pages(char *rel_area)
  55. {
  56. if (!map_shared) {
  57. if (madvise(rel_area, nr_pages * page_size, MADV_DONTNEED))
  58. err("madvise(MADV_DONTNEED) failed");
  59. } else {
  60. if (madvise(rel_area, nr_pages * page_size, MADV_REMOVE))
  61. err("madvise(MADV_REMOVE) failed");
  62. }
  63. }
  64. static int hugetlb_allocate_area(void **alloc_area, bool is_src)
  65. {
  66. off_t size = nr_pages * page_size;
  67. off_t offset = is_src ? 0 : size;
  68. void *area_alias = NULL;
  69. char **alloc_area_alias;
  70. int mem_fd = uffd_mem_fd_create(size * 2, true);
  71. *alloc_area = mmap(NULL, size, PROT_READ | PROT_WRITE,
  72. (map_shared ? MAP_SHARED : MAP_PRIVATE) |
  73. (is_src ? 0 : MAP_NORESERVE),
  74. mem_fd, offset);
  75. if (*alloc_area == MAP_FAILED) {
  76. *alloc_area = NULL;
  77. return -errno;
  78. }
  79. if (map_shared) {
  80. area_alias = mmap(NULL, size, PROT_READ | PROT_WRITE,
  81. MAP_SHARED, mem_fd, offset);
  82. if (area_alias == MAP_FAILED)
  83. return -errno;
  84. }
  85. if (is_src) {
  86. alloc_area_alias = &area_src_alias;
  87. } else {
  88. alloc_area_alias = &area_dst_alias;
  89. }
  90. if (area_alias)
  91. *alloc_area_alias = area_alias;
  92. close(mem_fd);
  93. return 0;
  94. }
  95. static void hugetlb_alias_mapping(__u64 *start, size_t len, unsigned long offset)
  96. {
  97. if (!map_shared)
  98. return;
  99. *start = (unsigned long) area_dst_alias + offset;
  100. }
  101. static void shmem_release_pages(char *rel_area)
  102. {
  103. if (madvise(rel_area, nr_pages * page_size, MADV_REMOVE))
  104. err("madvise(MADV_REMOVE) failed");
  105. }
  106. static int shmem_allocate_area(void **alloc_area, bool is_src)
  107. {
  108. void *area_alias = NULL;
  109. size_t bytes = nr_pages * page_size, hpage_size = read_pmd_pagesize();
  110. unsigned long offset = is_src ? 0 : bytes;
  111. char *p = NULL, *p_alias = NULL;
  112. int mem_fd = uffd_mem_fd_create(bytes * 2, false);
  113. /* TODO: clean this up. Use a static addr is ugly */
  114. p = BASE_PMD_ADDR;
  115. if (!is_src)
  116. /* src map + alias + interleaved hpages */
  117. p += 2 * (bytes + hpage_size);
  118. p_alias = p;
  119. p_alias += bytes;
  120. p_alias += hpage_size; /* Prevent src/dst VMA merge */
  121. *alloc_area = mmap(p, bytes, PROT_READ | PROT_WRITE, MAP_SHARED,
  122. mem_fd, offset);
  123. if (*alloc_area == MAP_FAILED) {
  124. *alloc_area = NULL;
  125. return -errno;
  126. }
  127. if (*alloc_area != p)
  128. err("mmap of memfd failed at %p", p);
  129. area_alias = mmap(p_alias, bytes, PROT_READ | PROT_WRITE, MAP_SHARED,
  130. mem_fd, offset);
  131. if (area_alias == MAP_FAILED) {
  132. munmap(*alloc_area, bytes);
  133. *alloc_area = NULL;
  134. return -errno;
  135. }
  136. if (area_alias != p_alias)
  137. err("mmap of anonymous memory failed at %p", p_alias);
  138. if (is_src)
  139. area_src_alias = area_alias;
  140. else
  141. area_dst_alias = area_alias;
  142. close(mem_fd);
  143. return 0;
  144. }
  145. static void shmem_alias_mapping(__u64 *start, size_t len, unsigned long offset)
  146. {
  147. *start = (unsigned long)area_dst_alias + offset;
  148. }
  149. static void shmem_check_pmd_mapping(void *p, int expect_nr_hpages)
  150. {
  151. if (!check_huge_shmem(area_dst_alias, expect_nr_hpages,
  152. read_pmd_pagesize()))
  153. err("Did not find expected %d number of hugepages",
  154. expect_nr_hpages);
  155. }
  156. struct uffd_test_ops anon_uffd_test_ops = {
  157. .allocate_area = anon_allocate_area,
  158. .release_pages = anon_release_pages,
  159. .alias_mapping = noop_alias_mapping,
  160. .check_pmd_mapping = NULL,
  161. };
  162. struct uffd_test_ops shmem_uffd_test_ops = {
  163. .allocate_area = shmem_allocate_area,
  164. .release_pages = shmem_release_pages,
  165. .alias_mapping = shmem_alias_mapping,
  166. .check_pmd_mapping = shmem_check_pmd_mapping,
  167. };
  168. struct uffd_test_ops hugetlb_uffd_test_ops = {
  169. .allocate_area = hugetlb_allocate_area,
  170. .release_pages = hugetlb_release_pages,
  171. .alias_mapping = hugetlb_alias_mapping,
  172. .check_pmd_mapping = NULL,
  173. };
  174. void uffd_stats_report(struct uffd_args *args, int n_cpus)
  175. {
  176. int i;
  177. unsigned long long miss_total = 0, wp_total = 0, minor_total = 0;
  178. for (i = 0; i < n_cpus; i++) {
  179. miss_total += args[i].missing_faults;
  180. wp_total += args[i].wp_faults;
  181. minor_total += args[i].minor_faults;
  182. }
  183. printf("userfaults: ");
  184. if (miss_total) {
  185. printf("%llu missing (", miss_total);
  186. for (i = 0; i < n_cpus; i++)
  187. printf("%lu+", args[i].missing_faults);
  188. printf("\b) ");
  189. }
  190. if (wp_total) {
  191. printf("%llu wp (", wp_total);
  192. for (i = 0; i < n_cpus; i++)
  193. printf("%lu+", args[i].wp_faults);
  194. printf("\b) ");
  195. }
  196. if (minor_total) {
  197. printf("%llu minor (", minor_total);
  198. for (i = 0; i < n_cpus; i++)
  199. printf("%lu+", args[i].minor_faults);
  200. printf("\b)");
  201. }
  202. printf("\n");
  203. }
  204. int userfaultfd_open(uint64_t *features)
  205. {
  206. struct uffdio_api uffdio_api;
  207. uffd = uffd_open(UFFD_FLAGS);
  208. if (uffd < 0)
  209. return -1;
  210. uffd_flags = fcntl(uffd, F_GETFD, NULL);
  211. uffdio_api.api = UFFD_API;
  212. uffdio_api.features = *features;
  213. if (ioctl(uffd, UFFDIO_API, &uffdio_api))
  214. /* Probably lack of CAP_PTRACE? */
  215. return -1;
  216. if (uffdio_api.api != UFFD_API)
  217. err("UFFDIO_API error: %" PRIu64, (uint64_t)uffdio_api.api);
  218. *features = uffdio_api.features;
  219. return 0;
  220. }
  221. static inline void munmap_area(void **area)
  222. {
  223. if (*area)
  224. if (munmap(*area, nr_pages * page_size))
  225. err("munmap");
  226. *area = NULL;
  227. }
  228. void uffd_test_ctx_clear(void)
  229. {
  230. size_t i;
  231. if (pipefd) {
  232. for (i = 0; i < nr_cpus * 2; ++i) {
  233. if (close(pipefd[i]))
  234. err("close pipefd");
  235. }
  236. free(pipefd);
  237. pipefd = NULL;
  238. }
  239. if (count_verify) {
  240. free(count_verify);
  241. count_verify = NULL;
  242. }
  243. if (uffd != -1) {
  244. if (close(uffd))
  245. err("close uffd");
  246. uffd = -1;
  247. }
  248. munmap_area((void **)&area_src);
  249. munmap_area((void **)&area_src_alias);
  250. munmap_area((void **)&area_dst);
  251. munmap_area((void **)&area_dst_alias);
  252. munmap_area((void **)&area_remap);
  253. }
  254. int uffd_test_ctx_init(uint64_t features, const char **errmsg)
  255. {
  256. unsigned long nr, cpu;
  257. int ret;
  258. if (uffd_test_case_ops && uffd_test_case_ops->pre_alloc) {
  259. ret = uffd_test_case_ops->pre_alloc(errmsg);
  260. if (ret)
  261. return ret;
  262. }
  263. ret = uffd_test_ops->allocate_area((void **)&area_src, true);
  264. ret |= uffd_test_ops->allocate_area((void **)&area_dst, false);
  265. if (ret) {
  266. if (errmsg)
  267. *errmsg = "memory allocation failed";
  268. return ret;
  269. }
  270. if (uffd_test_case_ops && uffd_test_case_ops->post_alloc) {
  271. ret = uffd_test_case_ops->post_alloc(errmsg);
  272. if (ret)
  273. return ret;
  274. }
  275. ret = userfaultfd_open(&features);
  276. if (ret) {
  277. if (errmsg)
  278. *errmsg = "possible lack of priviledge";
  279. return ret;
  280. }
  281. count_verify = malloc(nr_pages * sizeof(unsigned long long));
  282. if (!count_verify)
  283. err("count_verify");
  284. for (nr = 0; nr < nr_pages; nr++) {
  285. *area_mutex(area_src, nr) =
  286. (pthread_mutex_t)PTHREAD_MUTEX_INITIALIZER;
  287. count_verify[nr] = *area_count(area_src, nr) = 1;
  288. /*
  289. * In the transition between 255 to 256, powerpc will
  290. * read out of order in my_bcmp and see both bytes as
  291. * zero, so leave a placeholder below always non-zero
  292. * after the count, to avoid my_bcmp to trigger false
  293. * positives.
  294. */
  295. *(area_count(area_src, nr) + 1) = 1;
  296. }
  297. /*
  298. * After initialization of area_src, we must explicitly release pages
  299. * for area_dst to make sure it's fully empty. Otherwise we could have
  300. * some area_dst pages be errornously initialized with zero pages,
  301. * hence we could hit memory corruption later in the test.
  302. *
  303. * One example is when THP is globally enabled, above allocate_area()
  304. * calls could have the two areas merged into a single VMA (as they
  305. * will have the same VMA flags so they're mergeable). When we
  306. * initialize the area_src above, it's possible that some part of
  307. * area_dst could have been faulted in via one huge THP that will be
  308. * shared between area_src and area_dst. It could cause some of the
  309. * area_dst won't be trapped by missing userfaults.
  310. *
  311. * This release_pages() will guarantee even if that happened, we'll
  312. * proactively split the thp and drop any accidentally initialized
  313. * pages within area_dst.
  314. */
  315. uffd_test_ops->release_pages(area_dst);
  316. pipefd = malloc(sizeof(int) * nr_cpus * 2);
  317. if (!pipefd)
  318. err("pipefd");
  319. for (cpu = 0; cpu < nr_cpus; cpu++)
  320. if (pipe2(&pipefd[cpu * 2], O_CLOEXEC | O_NONBLOCK))
  321. err("pipe");
  322. return 0;
  323. }
  324. void wp_range(int ufd, __u64 start, __u64 len, bool wp)
  325. {
  326. struct uffdio_writeprotect prms;
  327. /* Write protection page faults */
  328. prms.range.start = start;
  329. prms.range.len = len;
  330. /* Undo write-protect, do wakeup after that */
  331. prms.mode = wp ? UFFDIO_WRITEPROTECT_MODE_WP : 0;
  332. if (ioctl(ufd, UFFDIO_WRITEPROTECT, &prms))
  333. err("clear WP failed: address=0x%"PRIx64, (uint64_t)start);
  334. }
  335. static void continue_range(int ufd, __u64 start, __u64 len, bool wp)
  336. {
  337. struct uffdio_continue req;
  338. int ret;
  339. req.range.start = start;
  340. req.range.len = len;
  341. req.mode = 0;
  342. if (wp)
  343. req.mode |= UFFDIO_CONTINUE_MODE_WP;
  344. if (ioctl(ufd, UFFDIO_CONTINUE, &req))
  345. err("UFFDIO_CONTINUE failed for address 0x%" PRIx64,
  346. (uint64_t)start);
  347. /*
  348. * Error handling within the kernel for continue is subtly different
  349. * from copy or zeropage, so it may be a source of bugs. Trigger an
  350. * error (-EEXIST) on purpose, to verify doing so doesn't cause a BUG.
  351. */
  352. req.mapped = 0;
  353. ret = ioctl(ufd, UFFDIO_CONTINUE, &req);
  354. if (ret >= 0 || req.mapped != -EEXIST)
  355. err("failed to exercise UFFDIO_CONTINUE error handling, ret=%d, mapped=%" PRId64,
  356. ret, (int64_t) req.mapped);
  357. }
  358. int uffd_read_msg(int ufd, struct uffd_msg *msg)
  359. {
  360. int ret = read(uffd, msg, sizeof(*msg));
  361. if (ret != sizeof(*msg)) {
  362. if (ret < 0) {
  363. if (errno == EAGAIN || errno == EINTR)
  364. return 1;
  365. err("blocking read error");
  366. } else {
  367. err("short read");
  368. }
  369. }
  370. return 0;
  371. }
  372. void uffd_handle_page_fault(struct uffd_msg *msg, struct uffd_args *args)
  373. {
  374. unsigned long offset;
  375. if (msg->event != UFFD_EVENT_PAGEFAULT)
  376. err("unexpected msg event %u", msg->event);
  377. if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WP) {
  378. /* Write protect page faults */
  379. wp_range(uffd, msg->arg.pagefault.address, page_size, false);
  380. args->wp_faults++;
  381. } else if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_MINOR) {
  382. uint8_t *area;
  383. int b;
  384. /*
  385. * Minor page faults
  386. *
  387. * To prove we can modify the original range for testing
  388. * purposes, we're going to bit flip this range before
  389. * continuing.
  390. *
  391. * Note that this requires all minor page fault tests operate on
  392. * area_dst (non-UFFD-registered) and area_dst_alias
  393. * (UFFD-registered).
  394. */
  395. area = (uint8_t *)(area_dst +
  396. ((char *)msg->arg.pagefault.address -
  397. area_dst_alias));
  398. for (b = 0; b < page_size; ++b)
  399. area[b] = ~area[b];
  400. continue_range(uffd, msg->arg.pagefault.address, page_size,
  401. args->apply_wp);
  402. args->minor_faults++;
  403. } else {
  404. /*
  405. * Missing page faults.
  406. *
  407. * Here we force a write check for each of the missing mode
  408. * faults. It's guaranteed because the only threads that
  409. * will trigger uffd faults are the locking threads, and
  410. * their first instruction to touch the missing page will
  411. * always be pthread_mutex_lock().
  412. *
  413. * Note that here we relied on an NPTL glibc impl detail to
  414. * always read the lock type at the entry of the lock op
  415. * (pthread_mutex_t.__data.__type, offset 0x10) before
  416. * doing any locking operations to guarantee that. It's
  417. * actually not good to rely on this impl detail because
  418. * logically a pthread-compatible lib can implement the
  419. * locks without types and we can fail when linking with
  420. * them. However since we used to find bugs with this
  421. * strict check we still keep it around. Hopefully this
  422. * could be a good hint when it fails again. If one day
  423. * it'll break on some other impl of glibc we'll revisit.
  424. */
  425. if (msg->arg.pagefault.flags & UFFD_PAGEFAULT_FLAG_WRITE)
  426. err("unexpected write fault");
  427. offset = (char *)(unsigned long)msg->arg.pagefault.address - area_dst;
  428. offset &= ~(page_size-1);
  429. if (copy_page(uffd, offset, args->apply_wp))
  430. args->missing_faults++;
  431. }
  432. }
  433. void *uffd_poll_thread(void *arg)
  434. {
  435. struct uffd_args *args = (struct uffd_args *)arg;
  436. unsigned long cpu = args->cpu;
  437. struct pollfd pollfd[2];
  438. struct uffd_msg msg;
  439. struct uffdio_register uffd_reg;
  440. int ret;
  441. char tmp_chr;
  442. if (!args->handle_fault)
  443. args->handle_fault = uffd_handle_page_fault;
  444. pollfd[0].fd = uffd;
  445. pollfd[0].events = POLLIN;
  446. pollfd[1].fd = pipefd[cpu*2];
  447. pollfd[1].events = POLLIN;
  448. ready_for_fork = true;
  449. for (;;) {
  450. ret = poll(pollfd, 2, -1);
  451. if (ret <= 0) {
  452. if (errno == EINTR || errno == EAGAIN)
  453. continue;
  454. err("poll error: %d", ret);
  455. }
  456. if (pollfd[1].revents) {
  457. if (!(pollfd[1].revents & POLLIN))
  458. err("pollfd[1].revents %d", pollfd[1].revents);
  459. if (read(pollfd[1].fd, &tmp_chr, 1) != 1)
  460. err("read pipefd error");
  461. break;
  462. }
  463. if (!(pollfd[0].revents & POLLIN))
  464. err("pollfd[0].revents %d", pollfd[0].revents);
  465. if (uffd_read_msg(uffd, &msg))
  466. continue;
  467. switch (msg.event) {
  468. default:
  469. err("unexpected msg event %u\n", msg.event);
  470. break;
  471. case UFFD_EVENT_PAGEFAULT:
  472. args->handle_fault(&msg, args);
  473. break;
  474. case UFFD_EVENT_FORK:
  475. close(uffd);
  476. uffd = msg.arg.fork.ufd;
  477. pollfd[0].fd = uffd;
  478. break;
  479. case UFFD_EVENT_REMOVE:
  480. uffd_reg.range.start = msg.arg.remove.start;
  481. uffd_reg.range.len = msg.arg.remove.end -
  482. msg.arg.remove.start;
  483. if (ioctl(uffd, UFFDIO_UNREGISTER, &uffd_reg.range))
  484. err("remove failure");
  485. break;
  486. case UFFD_EVENT_REMAP:
  487. area_remap = area_dst; /* save for later unmap */
  488. area_dst = (char *)(unsigned long)msg.arg.remap.to;
  489. break;
  490. }
  491. }
  492. return NULL;
  493. }
  494. static void retry_copy_page(int ufd, struct uffdio_copy *uffdio_copy,
  495. unsigned long offset)
  496. {
  497. uffd_test_ops->alias_mapping(&uffdio_copy->dst,
  498. uffdio_copy->len,
  499. offset);
  500. if (ioctl(ufd, UFFDIO_COPY, uffdio_copy)) {
  501. /* real retval in ufdio_copy.copy */
  502. if (uffdio_copy->copy != -EEXIST)
  503. err("UFFDIO_COPY retry error: %"PRId64,
  504. (int64_t)uffdio_copy->copy);
  505. } else {
  506. err("UFFDIO_COPY retry unexpected: %"PRId64,
  507. (int64_t)uffdio_copy->copy);
  508. }
  509. }
  510. static void wake_range(int ufd, unsigned long addr, unsigned long len)
  511. {
  512. struct uffdio_range uffdio_wake;
  513. uffdio_wake.start = addr;
  514. uffdio_wake.len = len;
  515. if (ioctl(ufd, UFFDIO_WAKE, &uffdio_wake))
  516. fprintf(stderr, "error waking %lu\n",
  517. addr), exit(1);
  518. }
  519. int __copy_page(int ufd, unsigned long offset, bool retry, bool wp)
  520. {
  521. struct uffdio_copy uffdio_copy;
  522. if (offset >= nr_pages * page_size)
  523. err("unexpected offset %lu\n", offset);
  524. uffdio_copy.dst = (unsigned long) area_dst + offset;
  525. uffdio_copy.src = (unsigned long) area_src + offset;
  526. uffdio_copy.len = page_size;
  527. if (wp)
  528. uffdio_copy.mode = UFFDIO_COPY_MODE_WP;
  529. else
  530. uffdio_copy.mode = 0;
  531. uffdio_copy.copy = 0;
  532. if (ioctl(ufd, UFFDIO_COPY, &uffdio_copy)) {
  533. /* real retval in ufdio_copy.copy */
  534. if (uffdio_copy.copy != -EEXIST)
  535. err("UFFDIO_COPY error: %"PRId64,
  536. (int64_t)uffdio_copy.copy);
  537. wake_range(ufd, uffdio_copy.dst, page_size);
  538. } else if (uffdio_copy.copy != page_size) {
  539. err("UFFDIO_COPY error: %"PRId64, (int64_t)uffdio_copy.copy);
  540. } else {
  541. if (test_uffdio_copy_eexist && retry) {
  542. test_uffdio_copy_eexist = false;
  543. retry_copy_page(ufd, &uffdio_copy, offset);
  544. }
  545. return 1;
  546. }
  547. return 0;
  548. }
  549. int copy_page(int ufd, unsigned long offset, bool wp)
  550. {
  551. return __copy_page(ufd, offset, false, wp);
  552. }
  553. int move_page(int ufd, unsigned long offset, unsigned long len)
  554. {
  555. struct uffdio_move uffdio_move;
  556. if (offset + len > nr_pages * page_size)
  557. err("unexpected offset %lu and length %lu\n", offset, len);
  558. uffdio_move.dst = (unsigned long) area_dst + offset;
  559. uffdio_move.src = (unsigned long) area_src + offset;
  560. uffdio_move.len = len;
  561. uffdio_move.mode = UFFDIO_MOVE_MODE_ALLOW_SRC_HOLES;
  562. uffdio_move.move = 0;
  563. if (ioctl(ufd, UFFDIO_MOVE, &uffdio_move)) {
  564. /* real retval in uffdio_move.move */
  565. if (uffdio_move.move != -EEXIST)
  566. err("UFFDIO_MOVE error: %"PRId64,
  567. (int64_t)uffdio_move.move);
  568. wake_range(ufd, uffdio_move.dst, len);
  569. } else if (uffdio_move.move != len) {
  570. err("UFFDIO_MOVE error: %"PRId64, (int64_t)uffdio_move.move);
  571. } else
  572. return 1;
  573. return 0;
  574. }
  575. int uffd_open_dev(unsigned int flags)
  576. {
  577. int fd, uffd;
  578. fd = open("/dev/userfaultfd", O_RDWR | O_CLOEXEC);
  579. if (fd < 0)
  580. return fd;
  581. uffd = ioctl(fd, USERFAULTFD_IOC_NEW, flags);
  582. close(fd);
  583. return uffd;
  584. }
  585. int uffd_open_sys(unsigned int flags)
  586. {
  587. #ifdef __NR_userfaultfd
  588. return syscall(__NR_userfaultfd, flags);
  589. #else
  590. return -1;
  591. #endif
  592. }
  593. int uffd_open(unsigned int flags)
  594. {
  595. int uffd = uffd_open_sys(flags);
  596. if (uffd < 0)
  597. uffd = uffd_open_dev(flags);
  598. return uffd;
  599. }
  600. int uffd_get_features(uint64_t *features)
  601. {
  602. struct uffdio_api uffdio_api = { .api = UFFD_API, .features = 0 };
  603. /*
  604. * This should by default work in most kernels; the feature list
  605. * will be the same no matter what we pass in here.
  606. */
  607. int fd = uffd_open(UFFD_USER_MODE_ONLY);
  608. if (fd < 0)
  609. /* Maybe the kernel is older than user-only mode? */
  610. fd = uffd_open(0);
  611. if (fd < 0)
  612. return fd;
  613. if (ioctl(fd, UFFDIO_API, &uffdio_api)) {
  614. close(fd);
  615. return -errno;
  616. }
  617. *features = uffdio_api.features;
  618. close(fd);
  619. return 0;
  620. }