ksm_functional_tests.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719
  1. // SPDX-License-Identifier: GPL-2.0-only
  2. /*
  3. * KSM functional tests
  4. *
  5. * Copyright 2022, Red Hat, Inc.
  6. *
  7. * Author(s): David Hildenbrand <david@redhat.com>
  8. */
  9. #define _GNU_SOURCE
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <stdbool.h>
  13. #include <stdint.h>
  14. #include <unistd.h>
  15. #include <errno.h>
  16. #include <fcntl.h>
  17. #include <sys/mman.h>
  18. #include <sys/prctl.h>
  19. #include <sys/syscall.h>
  20. #include <sys/ioctl.h>
  21. #include <sys/wait.h>
  22. #include <linux/userfaultfd.h>
  23. #include "../kselftest.h"
  24. #include "vm_util.h"
  25. #define KiB 1024u
  26. #define MiB (1024 * KiB)
  27. #define FORK_EXEC_CHILD_PRG_NAME "ksm_fork_exec_child"
  28. #define MAP_MERGE_FAIL ((void *)-1)
  29. #define MAP_MERGE_SKIP ((void *)-2)
  30. enum ksm_merge_mode {
  31. KSM_MERGE_PRCTL,
  32. KSM_MERGE_MADVISE,
  33. KSM_MERGE_NONE, /* PRCTL already set */
  34. };
  35. static int mem_fd;
  36. static int ksm_fd;
  37. static int ksm_full_scans_fd;
  38. static int proc_self_ksm_stat_fd;
  39. static int proc_self_ksm_merging_pages_fd;
  40. static int ksm_use_zero_pages_fd;
  41. static int pagemap_fd;
  42. static size_t pagesize;
  43. static bool range_maps_duplicates(char *addr, unsigned long size)
  44. {
  45. unsigned long offs_a, offs_b, pfn_a, pfn_b;
  46. /*
  47. * There is no easy way to check if there are KSM pages mapped into
  48. * this range. We only check that the range does not map the same PFN
  49. * twice by comparing each pair of mapped pages.
  50. */
  51. for (offs_a = 0; offs_a < size; offs_a += pagesize) {
  52. pfn_a = pagemap_get_pfn(pagemap_fd, addr + offs_a);
  53. /* Page not present or PFN not exposed by the kernel. */
  54. if (pfn_a == -1ul || !pfn_a)
  55. continue;
  56. for (offs_b = offs_a + pagesize; offs_b < size;
  57. offs_b += pagesize) {
  58. pfn_b = pagemap_get_pfn(pagemap_fd, addr + offs_b);
  59. if (pfn_b == -1ul || !pfn_b)
  60. continue;
  61. if (pfn_a == pfn_b)
  62. return true;
  63. }
  64. }
  65. return false;
  66. }
  67. static long get_my_ksm_zero_pages(void)
  68. {
  69. char buf[200];
  70. char *substr_ksm_zero;
  71. size_t value_pos;
  72. ssize_t read_size;
  73. unsigned long my_ksm_zero_pages;
  74. if (!proc_self_ksm_stat_fd)
  75. return 0;
  76. read_size = pread(proc_self_ksm_stat_fd, buf, sizeof(buf) - 1, 0);
  77. if (read_size < 0)
  78. return -errno;
  79. buf[read_size] = 0;
  80. substr_ksm_zero = strstr(buf, "ksm_zero_pages");
  81. if (!substr_ksm_zero)
  82. return 0;
  83. value_pos = strcspn(substr_ksm_zero, "0123456789");
  84. my_ksm_zero_pages = strtol(substr_ksm_zero + value_pos, NULL, 10);
  85. return my_ksm_zero_pages;
  86. }
  87. static long get_my_merging_pages(void)
  88. {
  89. char buf[10];
  90. ssize_t ret;
  91. if (proc_self_ksm_merging_pages_fd < 0)
  92. return proc_self_ksm_merging_pages_fd;
  93. ret = pread(proc_self_ksm_merging_pages_fd, buf, sizeof(buf) - 1, 0);
  94. if (ret <= 0)
  95. return -errno;
  96. buf[ret] = 0;
  97. return strtol(buf, NULL, 10);
  98. }
  99. static long ksm_get_full_scans(void)
  100. {
  101. char buf[10];
  102. ssize_t ret;
  103. ret = pread(ksm_full_scans_fd, buf, sizeof(buf) - 1, 0);
  104. if (ret <= 0)
  105. return -errno;
  106. buf[ret] = 0;
  107. return strtol(buf, NULL, 10);
  108. }
  109. static int ksm_merge(void)
  110. {
  111. long start_scans, end_scans;
  112. /* Wait for two full scans such that any possible merging happened. */
  113. start_scans = ksm_get_full_scans();
  114. if (start_scans < 0)
  115. return start_scans;
  116. if (write(ksm_fd, "1", 1) != 1)
  117. return -errno;
  118. do {
  119. end_scans = ksm_get_full_scans();
  120. if (end_scans < 0)
  121. return end_scans;
  122. } while (end_scans < start_scans + 2);
  123. return 0;
  124. }
  125. static int ksm_unmerge(void)
  126. {
  127. if (write(ksm_fd, "2", 1) != 1)
  128. return -errno;
  129. return 0;
  130. }
  131. static char *__mmap_and_merge_range(char val, unsigned long size, int prot,
  132. enum ksm_merge_mode mode)
  133. {
  134. char *map;
  135. char *err_map = MAP_MERGE_FAIL;
  136. int ret;
  137. /* Stabilize accounting by disabling KSM completely. */
  138. if (ksm_unmerge()) {
  139. ksft_print_msg("Disabling (unmerging) KSM failed\n");
  140. return err_map;
  141. }
  142. if (get_my_merging_pages() > 0) {
  143. ksft_print_msg("Still pages merged\n");
  144. return err_map;
  145. }
  146. map = mmap(NULL, size, PROT_READ|PROT_WRITE,
  147. MAP_PRIVATE|MAP_ANON, -1, 0);
  148. if (map == MAP_FAILED) {
  149. ksft_print_msg("mmap() failed\n");
  150. return err_map;
  151. }
  152. /* Don't use THP. Ignore if THP are not around on a kernel. */
  153. if (madvise(map, size, MADV_NOHUGEPAGE) && errno != EINVAL) {
  154. ksft_print_msg("MADV_NOHUGEPAGE failed\n");
  155. goto unmap;
  156. }
  157. /* Make sure each page contains the same values to merge them. */
  158. memset(map, val, size);
  159. if (mprotect(map, size, prot)) {
  160. ksft_print_msg("mprotect() failed\n");
  161. err_map = MAP_MERGE_SKIP;
  162. goto unmap;
  163. }
  164. switch (mode) {
  165. case KSM_MERGE_PRCTL:
  166. ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
  167. if (ret < 0 && errno == EINVAL) {
  168. ksft_print_msg("PR_SET_MEMORY_MERGE not supported\n");
  169. err_map = MAP_MERGE_SKIP;
  170. goto unmap;
  171. } else if (ret) {
  172. ksft_print_msg("PR_SET_MEMORY_MERGE=1 failed\n");
  173. goto unmap;
  174. }
  175. break;
  176. case KSM_MERGE_MADVISE:
  177. if (madvise(map, size, MADV_MERGEABLE)) {
  178. ksft_print_msg("MADV_MERGEABLE failed\n");
  179. goto unmap;
  180. }
  181. break;
  182. case KSM_MERGE_NONE:
  183. break;
  184. }
  185. /* Run KSM to trigger merging and wait. */
  186. if (ksm_merge()) {
  187. ksft_print_msg("Running KSM failed\n");
  188. goto unmap;
  189. }
  190. /*
  191. * Check if anything was merged at all. Ignore the zero page that is
  192. * accounted differently (depending on kernel support).
  193. */
  194. if (val && !get_my_merging_pages()) {
  195. ksft_print_msg("No pages got merged\n");
  196. goto unmap;
  197. }
  198. return map;
  199. unmap:
  200. munmap(map, size);
  201. return err_map;
  202. }
  203. static char *mmap_and_merge_range(char val, unsigned long size, int prot,
  204. enum ksm_merge_mode mode)
  205. {
  206. char *map;
  207. char *ret = MAP_FAILED;
  208. map = __mmap_and_merge_range(val, size, prot, mode);
  209. if (map == MAP_MERGE_FAIL)
  210. ksft_test_result_fail("Merging memory failed");
  211. else if (map == MAP_MERGE_SKIP)
  212. ksft_test_result_skip("Merging memory skipped");
  213. else
  214. ret = map;
  215. return ret;
  216. }
  217. static void test_unmerge(void)
  218. {
  219. const unsigned int size = 2 * MiB;
  220. char *map;
  221. ksft_print_msg("[RUN] %s\n", __func__);
  222. map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
  223. if (map == MAP_FAILED)
  224. return;
  225. if (madvise(map, size, MADV_UNMERGEABLE)) {
  226. ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
  227. goto unmap;
  228. }
  229. ksft_test_result(!range_maps_duplicates(map, size),
  230. "Pages were unmerged\n");
  231. unmap:
  232. munmap(map, size);
  233. }
  234. static void test_unmerge_zero_pages(void)
  235. {
  236. const unsigned int size = 2 * MiB;
  237. char *map;
  238. unsigned int offs;
  239. unsigned long pages_expected;
  240. ksft_print_msg("[RUN] %s\n", __func__);
  241. if (proc_self_ksm_stat_fd < 0) {
  242. ksft_test_result_skip("open(\"/proc/self/ksm_stat\") failed\n");
  243. return;
  244. }
  245. if (ksm_use_zero_pages_fd < 0) {
  246. ksft_test_result_skip("open \"/sys/kernel/mm/ksm/use_zero_pages\" failed\n");
  247. return;
  248. }
  249. if (write(ksm_use_zero_pages_fd, "1", 1) != 1) {
  250. ksft_test_result_skip("write \"/sys/kernel/mm/ksm/use_zero_pages\" failed\n");
  251. return;
  252. }
  253. /* Let KSM deduplicate zero pages. */
  254. map = mmap_and_merge_range(0x00, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
  255. if (map == MAP_FAILED)
  256. return;
  257. /* Check if ksm_zero_pages is updated correctly after KSM merging */
  258. pages_expected = size / pagesize;
  259. if (pages_expected != get_my_ksm_zero_pages()) {
  260. ksft_test_result_fail("'ksm_zero_pages' updated after merging\n");
  261. goto unmap;
  262. }
  263. /* Try to unmerge half of the region */
  264. if (madvise(map, size / 2, MADV_UNMERGEABLE)) {
  265. ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
  266. goto unmap;
  267. }
  268. /* Check if ksm_zero_pages is updated correctly after unmerging */
  269. pages_expected /= 2;
  270. if (pages_expected != get_my_ksm_zero_pages()) {
  271. ksft_test_result_fail("'ksm_zero_pages' updated after unmerging\n");
  272. goto unmap;
  273. }
  274. /* Trigger unmerging of the other half by writing to the pages. */
  275. for (offs = size / 2; offs < size; offs += pagesize)
  276. *((unsigned int *)&map[offs]) = offs;
  277. /* Now we should have no zeropages remaining. */
  278. if (get_my_ksm_zero_pages()) {
  279. ksft_test_result_fail("'ksm_zero_pages' updated after write fault\n");
  280. goto unmap;
  281. }
  282. /* Check if ksm zero pages are really unmerged */
  283. ksft_test_result(!range_maps_duplicates(map, size),
  284. "KSM zero pages were unmerged\n");
  285. unmap:
  286. munmap(map, size);
  287. }
  288. static void test_unmerge_discarded(void)
  289. {
  290. const unsigned int size = 2 * MiB;
  291. char *map;
  292. ksft_print_msg("[RUN] %s\n", __func__);
  293. map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
  294. if (map == MAP_FAILED)
  295. return;
  296. /* Discard half of all mapped pages so we have pte_none() entries. */
  297. if (madvise(map, size / 2, MADV_DONTNEED)) {
  298. ksft_test_result_fail("MADV_DONTNEED failed\n");
  299. goto unmap;
  300. }
  301. if (madvise(map, size, MADV_UNMERGEABLE)) {
  302. ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
  303. goto unmap;
  304. }
  305. ksft_test_result(!range_maps_duplicates(map, size),
  306. "Pages were unmerged\n");
  307. unmap:
  308. munmap(map, size);
  309. }
  310. #ifdef __NR_userfaultfd
  311. static void test_unmerge_uffd_wp(void)
  312. {
  313. struct uffdio_writeprotect uffd_writeprotect;
  314. const unsigned int size = 2 * MiB;
  315. struct uffdio_api uffdio_api;
  316. char *map;
  317. int uffd;
  318. ksft_print_msg("[RUN] %s\n", __func__);
  319. map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_MADVISE);
  320. if (map == MAP_FAILED)
  321. return;
  322. /* See if UFFD is around. */
  323. uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
  324. if (uffd < 0) {
  325. ksft_test_result_skip("__NR_userfaultfd failed\n");
  326. goto unmap;
  327. }
  328. /* See if UFFD-WP is around. */
  329. uffdio_api.api = UFFD_API;
  330. uffdio_api.features = UFFD_FEATURE_PAGEFAULT_FLAG_WP;
  331. if (ioctl(uffd, UFFDIO_API, &uffdio_api) < 0) {
  332. ksft_test_result_fail("UFFDIO_API failed\n");
  333. goto close_uffd;
  334. }
  335. if (!(uffdio_api.features & UFFD_FEATURE_PAGEFAULT_FLAG_WP)) {
  336. ksft_test_result_skip("UFFD_FEATURE_PAGEFAULT_FLAG_WP not available\n");
  337. goto close_uffd;
  338. }
  339. /* Register UFFD-WP, no need for an actual handler. */
  340. if (uffd_register(uffd, map, size, false, true, false)) {
  341. ksft_test_result_fail("UFFDIO_REGISTER_MODE_WP failed\n");
  342. goto close_uffd;
  343. }
  344. /* Write-protect the range using UFFD-WP. */
  345. uffd_writeprotect.range.start = (unsigned long) map;
  346. uffd_writeprotect.range.len = size;
  347. uffd_writeprotect.mode = UFFDIO_WRITEPROTECT_MODE_WP;
  348. if (ioctl(uffd, UFFDIO_WRITEPROTECT, &uffd_writeprotect)) {
  349. ksft_test_result_fail("UFFDIO_WRITEPROTECT failed\n");
  350. goto close_uffd;
  351. }
  352. if (madvise(map, size, MADV_UNMERGEABLE)) {
  353. ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
  354. goto close_uffd;
  355. }
  356. ksft_test_result(!range_maps_duplicates(map, size),
  357. "Pages were unmerged\n");
  358. close_uffd:
  359. close(uffd);
  360. unmap:
  361. munmap(map, size);
  362. }
  363. #endif
  364. /* Verify that KSM can be enabled / queried with prctl. */
  365. static void test_prctl(void)
  366. {
  367. int ret;
  368. ksft_print_msg("[RUN] %s\n", __func__);
  369. ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
  370. if (ret < 0 && errno == EINVAL) {
  371. ksft_test_result_skip("PR_SET_MEMORY_MERGE not supported\n");
  372. return;
  373. } else if (ret) {
  374. ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 failed\n");
  375. return;
  376. }
  377. ret = prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0);
  378. if (ret < 0) {
  379. ksft_test_result_fail("PR_GET_MEMORY_MERGE failed\n");
  380. return;
  381. } else if (ret != 1) {
  382. ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 not effective\n");
  383. return;
  384. }
  385. ret = prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0);
  386. if (ret) {
  387. ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
  388. return;
  389. }
  390. ret = prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0);
  391. if (ret < 0) {
  392. ksft_test_result_fail("PR_GET_MEMORY_MERGE failed\n");
  393. return;
  394. } else if (ret != 0) {
  395. ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 not effective\n");
  396. return;
  397. }
  398. ksft_test_result_pass("Setting/clearing PR_SET_MEMORY_MERGE works\n");
  399. }
  400. static int test_child_ksm(void)
  401. {
  402. const unsigned int size = 2 * MiB;
  403. char *map;
  404. /* Test if KSM is enabled for the process. */
  405. if (prctl(PR_GET_MEMORY_MERGE, 0, 0, 0, 0) != 1)
  406. return -1;
  407. /* Test if merge could really happen. */
  408. map = __mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_NONE);
  409. if (map == MAP_MERGE_FAIL)
  410. return -2;
  411. else if (map == MAP_MERGE_SKIP)
  412. return -3;
  413. munmap(map, size);
  414. return 0;
  415. }
  416. static void test_child_ksm_err(int status)
  417. {
  418. if (status == -1)
  419. ksft_test_result_fail("unexpected PR_GET_MEMORY_MERGE result in child\n");
  420. else if (status == -2)
  421. ksft_test_result_fail("Merge in child failed\n");
  422. else if (status == -3)
  423. ksft_test_result_skip("Merge in child skipped\n");
  424. }
  425. /* Verify that prctl ksm flag is inherited. */
  426. static void test_prctl_fork(void)
  427. {
  428. int ret, status;
  429. pid_t child_pid;
  430. ksft_print_msg("[RUN] %s\n", __func__);
  431. ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
  432. if (ret < 0 && errno == EINVAL) {
  433. ksft_test_result_skip("PR_SET_MEMORY_MERGE not supported\n");
  434. return;
  435. } else if (ret) {
  436. ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 failed\n");
  437. return;
  438. }
  439. child_pid = fork();
  440. if (!child_pid) {
  441. exit(test_child_ksm());
  442. } else if (child_pid < 0) {
  443. ksft_test_result_fail("fork() failed\n");
  444. return;
  445. }
  446. if (waitpid(child_pid, &status, 0) < 0) {
  447. ksft_test_result_fail("waitpid() failed\n");
  448. return;
  449. }
  450. status = WEXITSTATUS(status);
  451. if (status) {
  452. test_child_ksm_err(status);
  453. return;
  454. }
  455. if (prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0)) {
  456. ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
  457. return;
  458. }
  459. ksft_test_result_pass("PR_SET_MEMORY_MERGE value is inherited\n");
  460. }
  461. static void test_prctl_fork_exec(void)
  462. {
  463. int ret, status;
  464. pid_t child_pid;
  465. ksft_print_msg("[RUN] %s\n", __func__);
  466. ret = prctl(PR_SET_MEMORY_MERGE, 1, 0, 0, 0);
  467. if (ret < 0 && errno == EINVAL) {
  468. ksft_test_result_skip("PR_SET_MEMORY_MERGE not supported\n");
  469. return;
  470. } else if (ret) {
  471. ksft_test_result_fail("PR_SET_MEMORY_MERGE=1 failed\n");
  472. return;
  473. }
  474. child_pid = fork();
  475. if (child_pid == -1) {
  476. ksft_test_result_skip("fork() failed\n");
  477. return;
  478. } else if (child_pid == 0) {
  479. char *prg_name = "./ksm_functional_tests";
  480. char *argv_for_program[] = { prg_name, FORK_EXEC_CHILD_PRG_NAME };
  481. execv(prg_name, argv_for_program);
  482. return;
  483. }
  484. if (waitpid(child_pid, &status, 0) > 0) {
  485. if (WIFEXITED(status)) {
  486. status = WEXITSTATUS(status);
  487. if (status) {
  488. test_child_ksm_err(status);
  489. return;
  490. }
  491. } else {
  492. ksft_test_result_fail("program didn't terminate normally\n");
  493. return;
  494. }
  495. } else {
  496. ksft_test_result_fail("waitpid() failed\n");
  497. return;
  498. }
  499. if (prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0)) {
  500. ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
  501. return;
  502. }
  503. ksft_test_result_pass("PR_SET_MEMORY_MERGE value is inherited\n");
  504. }
  505. static void test_prctl_unmerge(void)
  506. {
  507. const unsigned int size = 2 * MiB;
  508. char *map;
  509. ksft_print_msg("[RUN] %s\n", __func__);
  510. map = mmap_and_merge_range(0xcf, size, PROT_READ | PROT_WRITE, KSM_MERGE_PRCTL);
  511. if (map == MAP_FAILED)
  512. return;
  513. if (prctl(PR_SET_MEMORY_MERGE, 0, 0, 0, 0)) {
  514. ksft_test_result_fail("PR_SET_MEMORY_MERGE=0 failed\n");
  515. goto unmap;
  516. }
  517. ksft_test_result(!range_maps_duplicates(map, size),
  518. "Pages were unmerged\n");
  519. unmap:
  520. munmap(map, size);
  521. }
  522. static void test_prot_none(void)
  523. {
  524. const unsigned int size = 2 * MiB;
  525. char *map;
  526. int i;
  527. ksft_print_msg("[RUN] %s\n", __func__);
  528. map = mmap_and_merge_range(0x11, size, PROT_NONE, KSM_MERGE_MADVISE);
  529. if (map == MAP_FAILED)
  530. goto unmap;
  531. /* Store a unique value in each page on one half using ptrace */
  532. for (i = 0; i < size / 2; i += pagesize) {
  533. lseek(mem_fd, (uintptr_t) map + i, SEEK_SET);
  534. if (write(mem_fd, &i, sizeof(i)) != sizeof(i)) {
  535. ksft_test_result_fail("ptrace write failed\n");
  536. goto unmap;
  537. }
  538. }
  539. /* Trigger unsharing on the other half. */
  540. if (madvise(map + size / 2, size / 2, MADV_UNMERGEABLE)) {
  541. ksft_test_result_fail("MADV_UNMERGEABLE failed\n");
  542. goto unmap;
  543. }
  544. ksft_test_result(!range_maps_duplicates(map, size),
  545. "Pages were unmerged\n");
  546. unmap:
  547. munmap(map, size);
  548. }
  549. static void init_global_file_handles(void)
  550. {
  551. mem_fd = open("/proc/self/mem", O_RDWR);
  552. if (mem_fd < 0)
  553. ksft_exit_fail_msg("opening /proc/self/mem failed\n");
  554. ksm_fd = open("/sys/kernel/mm/ksm/run", O_RDWR);
  555. if (ksm_fd < 0)
  556. ksft_exit_skip("open(\"/sys/kernel/mm/ksm/run\") failed\n");
  557. ksm_full_scans_fd = open("/sys/kernel/mm/ksm/full_scans", O_RDONLY);
  558. if (ksm_full_scans_fd < 0)
  559. ksft_exit_skip("open(\"/sys/kernel/mm/ksm/full_scans\") failed\n");
  560. pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
  561. if (pagemap_fd < 0)
  562. ksft_exit_skip("open(\"/proc/self/pagemap\") failed\n");
  563. proc_self_ksm_stat_fd = open("/proc/self/ksm_stat", O_RDONLY);
  564. proc_self_ksm_merging_pages_fd = open("/proc/self/ksm_merging_pages",
  565. O_RDONLY);
  566. ksm_use_zero_pages_fd = open("/sys/kernel/mm/ksm/use_zero_pages", O_RDWR);
  567. }
  568. int main(int argc, char **argv)
  569. {
  570. unsigned int tests = 8;
  571. int err;
  572. if (argc > 1 && !strcmp(argv[1], FORK_EXEC_CHILD_PRG_NAME)) {
  573. init_global_file_handles();
  574. exit(test_child_ksm());
  575. }
  576. #ifdef __NR_userfaultfd
  577. tests++;
  578. #endif
  579. ksft_print_header();
  580. ksft_set_plan(tests);
  581. pagesize = getpagesize();
  582. init_global_file_handles();
  583. test_unmerge();
  584. test_unmerge_zero_pages();
  585. test_unmerge_discarded();
  586. #ifdef __NR_userfaultfd
  587. test_unmerge_uffd_wp();
  588. #endif
  589. test_prot_none();
  590. test_prctl();
  591. test_prctl_fork();
  592. test_prctl_fork_exec();
  593. test_prctl_unmerge();
  594. err = ksft_get_fail_cnt();
  595. if (err)
  596. ksft_exit_fail_msg("%d out of %d tests failed\n",
  597. err, ksft_test_num());
  598. ksft_exit_pass();
  599. }