xref: /linux/tools/testing/selftests/mm/khugepaged.c (revision 81afb1ee7b2fb8b533aaa5cbd907fd000e60f193)
1 #define _GNU_SOURCE
2 #include <ctype.h>
3 #include <errno.h>
4 #include <fcntl.h>
5 #include <limits.h>
6 #include <dirent.h>
7 #include <signal.h>
8 #include <stdio.h>
9 #include <stdlib.h>
10 #include <stdbool.h>
11 #include <string.h>
12 #include <unistd.h>
13 
14 #include <linux/mman.h>
15 #include <sys/mman.h>
16 #include <sys/wait.h>
17 #include <sys/types.h>
18 #include <sys/stat.h>
19 #include <sys/sysmacros.h>
20 #include <sys/vfs.h>
21 
22 #include "linux/magic.h"
23 
24 #include "vm_util.h"
25 #include "hugepage_settings.h"
26 
27 #define BASE_ADDR ((void *)(1UL << 30))
28 static unsigned long hpage_pmd_size;
29 static unsigned long page_size;
30 static int hpage_pmd_nr;
31 static int anon_order;
32 
33 #define PID_SMAPS "/proc/self/smaps"
34 #define TEST_FILE "collapse_test_file"
35 
36 #define MAX_LINE_LENGTH 500
37 
38 enum vma_type {
39 	VMA_ANON,
40 	VMA_FILE,
41 	VMA_SHMEM,
42 };
43 
44 enum file_setup_ops {
45 	FILE_SETUP_READ_ONLY_FS,
46 	FILE_SETUP_READ_WRITE_FS_READ_DATA,
47 	FILE_SETUP_READ_WRITE_FS_WRITE_DATA,
48 };
49 
50 struct mem_ops {
51 	void *(*setup_area)(int nr_hpages);
52 	void (*cleanup_area)(void *p, unsigned long size);
53 	void (*fault)(void *p, unsigned long start, unsigned long end);
54 	bool (*check_huge)(void *addr, int nr_hpages);
55 	const char *name;
56 };
57 
58 static struct mem_ops *read_only_file_ops;
59 static struct mem_ops *read_write_file_read_ops;
60 static struct mem_ops *read_write_file_write_ops;
61 static struct mem_ops *anon_ops;
62 static struct mem_ops *shmem_ops;
63 
64 struct collapse_context {
65 	void (*collapse)(const char *msg, char *p, int nr_hpages,
66 			 struct mem_ops *ops, bool expect);
67 	bool enforce_pte_scan_limits;
68 	const char *name;
69 };
70 
71 static struct collapse_context *khugepaged_context;
72 static struct collapse_context *madvise_context;
73 
74 struct file_info {
75 	const char *dir;
76 	char path[PATH_MAX];
77 	enum vma_type type;
78 	int fd;
79 	char dev_queue_read_ahead_path[PATH_MAX];
80 };
81 
82 static struct file_info finfo;
83 static int exit_status;
84 
85 static void success(const char *msg)
86 {
87 	printf(" \e[32m%s\e[0m\n", msg);
88 	exit_status = KSFT_PASS;
89 }
90 
91 static void fail(const char *msg)
92 {
93 	printf(" \e[31m%s\e[0m\n", msg);
94 	exit_status = KSFT_FAIL;
95 }
96 
97 static void skip(const char *msg)
98 {
99 	printf(" \e[33m%s\e[0m\n", msg);
100 	exit_status = KSFT_SKIP;
101 }
102 
103 static void save_settings(void)
104 {
105 	ksft_print_msg("Save THP and khugepaged settings...");
106 	if ((read_only_file_ops || read_write_file_read_ops ||
107 	     read_write_file_write_ops) &&
108 	    finfo.type == VMA_FILE)
109 		thp_set_read_ahead_path(finfo.dev_queue_read_ahead_path);
110 	thp_save_settings();
111 
112 	success("OK");
113 }
114 
115 static void get_finfo(const char *dir)
116 {
117 	struct stat path_stat;
118 	struct statfs fs;
119 	char buf[1 << 10];
120 	char path[PATH_MAX];
121 	char *str, *end;
122 
123 	finfo.dir = dir;
124 	stat(finfo.dir, &path_stat);
125 	if (!S_ISDIR(path_stat.st_mode))
126 		ksft_exit_fail_msg("%s: Not a directory (%s)\n", __func__, finfo.dir);
127 	if (snprintf(finfo.path, sizeof(finfo.path), "%s/" TEST_FILE,
128 		     finfo.dir) >= sizeof(finfo.path))
129 		ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
130 	if (statfs(finfo.dir, &fs))
131 		ksft_exit_fail_perror("statfs()");
132 	finfo.type = fs.f_type == TMPFS_MAGIC ? VMA_SHMEM : VMA_FILE;
133 	if (finfo.type == VMA_SHMEM)
134 		return;
135 
136 	/* Find owning device's queue/read_ahead_kb control */
137 	if (snprintf(path, sizeof(path), "/sys/dev/block/%d:%d/uevent",
138 		     major(path_stat.st_dev), minor(path_stat.st_dev))
139 	    >= sizeof(path))
140 		ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
141 	if (read_file(path, buf, sizeof(buf)) < 0)
142 		ksft_exit_fail_perror("read_file(read_num)");
143 	if (strstr(buf, "DEVTYPE=disk")) {
144 		/* Found it */
145 		if (snprintf(finfo.dev_queue_read_ahead_path,
146 			     sizeof(finfo.dev_queue_read_ahead_path),
147 			     "/sys/dev/block/%d:%d/queue/read_ahead_kb",
148 			     major(path_stat.st_dev), minor(path_stat.st_dev))
149 		    >= sizeof(finfo.dev_queue_read_ahead_path))
150 			ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
151 		return;
152 	}
153 	if (!strstr(buf, "DEVTYPE=partition"))
154 		ksft_exit_fail_msg("%s: Unknown device type: %s\n", __func__, path);
155 	/*
156 	 * Partition of block device - need to find actual device.
157 	 * Using naming convention that devnameN is partition of
158 	 * device devname.
159 	 */
160 	str = strstr(buf, "DEVNAME=");
161 	if (!str)
162 		ksft_exit_fail_msg("%s: Could not read: %s", __func__, path);
163 	str += 8;
164 	end = str;
165 	while (*end) {
166 		if (isdigit(*end)) {
167 			*end = '\0';
168 			if (snprintf(finfo.dev_queue_read_ahead_path,
169 				     sizeof(finfo.dev_queue_read_ahead_path),
170 				     "/sys/block/%s/queue/read_ahead_kb",
171 				     str) >= sizeof(finfo.dev_queue_read_ahead_path))
172 				ksft_exit_fail_msg("%s: Pathname is too long\n", __func__);
173 			return;
174 		}
175 		++end;
176 	}
177 	ksft_exit_fail_msg("%s: Could not read: %s\n", __func__, path);
178 }
179 
180 static bool check_swap(void *addr, unsigned long size)
181 {
182 	bool swap = false;
183 	int ret;
184 	FILE *fp;
185 	char buffer[MAX_LINE_LENGTH];
186 	char addr_pattern[MAX_LINE_LENGTH];
187 
188 	ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "%08lx-",
189 		       (unsigned long) addr);
190 	if (ret >= MAX_LINE_LENGTH)
191 		ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
192 
193 	fp = fopen(PID_SMAPS, "r");
194 	if (!fp)
195 		ksft_exit_fail_msg("%s: Failed to open file %s\n", __func__, PID_SMAPS);
196 	if (!check_for_pattern(fp, addr_pattern, buffer, sizeof(buffer)))
197 		goto err_out;
198 
199 	ret = snprintf(addr_pattern, MAX_LINE_LENGTH, "Swap:%19ld kB",
200 		       size >> 10);
201 	if (ret >= MAX_LINE_LENGTH)
202 		ksft_exit_fail_msg("%s: Pattern is too long\n", __func__);
203 	/*
204 	 * Fetch the Swap: in the same block and check whether it got
205 	 * the expected number of hugeepages next.
206 	 */
207 	if (!check_for_pattern(fp, "Swap:", buffer, sizeof(buffer)))
208 		goto err_out;
209 
210 	if (strncmp(buffer, addr_pattern, strlen(addr_pattern)))
211 		goto err_out;
212 
213 	swap = true;
214 err_out:
215 	fclose(fp);
216 	return swap;
217 }
218 
219 static void *alloc_mapping(int nr)
220 {
221 	void *p;
222 
223 	p = mmap(BASE_ADDR, nr * hpage_pmd_size, PROT_READ | PROT_WRITE,
224 		 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
225 	if (p != BASE_ADDR)
226 		ksft_exit_fail_msg("Failed to allocate VMA at %p\n", BASE_ADDR);
227 
228 	return p;
229 }
230 
231 static void fill_memory(int *p, unsigned long start, unsigned long end)
232 {
233 	int i;
234 
235 	for (i = start / page_size; i < end / page_size; i++)
236 		p[i * page_size / sizeof(*p)] = i + 0xdead0000;
237 }
238 
239 /*
240  * MADV_COLLAPSE is a best-effort request and may fail if an internal
241  * resource is temporarily unavailable, in which case it will set errno to
242  * EAGAIN.  In such a case, immediately reattempt the operation one more
243  * time.
244  */
245 static int madvise_collapse_retry(void *p, unsigned long size)
246 {
247 	bool retry = true;
248 	int ret;
249 
250 retry:
251 	ret = madvise(p, size, MADV_COLLAPSE);
252 	if (ret && errno == EAGAIN && retry) {
253 		retry = false;
254 		goto retry;
255 	}
256 	return ret;
257 }
258 
259 /*
260  * Returns pmd-mapped hugepage in VMA marked VM_HUGEPAGE, filled with
261  * validate_memory()'able contents.
262  */
263 static void *alloc_hpage(struct mem_ops *ops)
264 {
265 	void *p = ops->setup_area(1);
266 
267 	ops->fault(p, 0, hpage_pmd_size);
268 
269 	/*
270 	 * VMA should be neither VM_HUGEPAGE nor VM_NOHUGEPAGE.
271 	 * The latter is ineligible for collapse by MADV_COLLAPSE
272 	 * while the former might cause MADV_COLLAPSE to race with
273 	 * khugepaged on low-load system (like a test machine), which
274 	 * would cause MADV_COLLAPSE to fail with EAGAIN.
275 	 */
276 	ksft_print_msg("Allocate huge page...");
277 	if (madvise_collapse_retry(p, hpage_pmd_size))
278 		ksft_exit_fail_perror("madvise(MADV_COLLAPSE)");
279 	if (!ops->check_huge(p, 1))
280 		ksft_exit_fail_perror("madvise(MADV_COLLAPSE)");
281 	if (madvise(p, hpage_pmd_size, MADV_HUGEPAGE))
282 		ksft_exit_fail_perror("madvise(MADV_HUGEPAGE)");
283 	success("OK");
284 	return p;
285 }
286 
287 static void validate_memory(int *p, unsigned long start, unsigned long end)
288 {
289 	int i;
290 
291 	for (i = start / page_size; i < end / page_size; i++) {
292 		if (p[i * page_size / sizeof(*p)] != i + 0xdead0000)
293 			ksft_exit_fail_msg("Page %d is corrupted: %#x\n",
294 					   i, p[i * page_size / sizeof(*p)]);
295 	}
296 }
297 
298 static void *anon_setup_area(int nr_hpages)
299 {
300 	return alloc_mapping(nr_hpages);
301 }
302 
303 static void anon_cleanup_area(void *p, unsigned long size)
304 {
305 	munmap(p, size);
306 }
307 
308 static void anon_fault(void *p, unsigned long start, unsigned long end)
309 {
310 	fill_memory(p, start, end);
311 }
312 
313 static bool anon_check_huge(void *addr, int nr_hpages)
314 {
315 	return check_huge_anon(addr, nr_hpages, hpage_pmd_size);
316 }
317 
318 static void *file_setup_area_common(int nr_hpages, enum file_setup_ops setup)
319 {
320 	const int open_opt = setup == FILE_SETUP_READ_ONLY_FS ? O_RDONLY : O_RDWR;
321 	const int mmap_prot = setup == FILE_SETUP_READ_ONLY_FS ? PROT_READ : (PROT_READ | PROT_WRITE);
322 	int fd;
323 	void *p;
324 	unsigned long size;
325 
326 	unlink(finfo.path);  /* Cleanup from previous failed tests */
327 	ksft_print_msg("Creating %s for collapse%s...", finfo.path,
328 		       finfo.type == VMA_SHMEM ? " (tmpfs)" : "");
329 	fd = open(finfo.path, O_CREAT | O_RDWR | O_TRUNC | O_EXCL,
330 		  777);
331 	if (fd < 0)
332 		ksft_exit_fail_perror("open()");
333 
334 	size = nr_hpages * hpage_pmd_size;
335 	if (ftruncate(fd, size)) {
336 		perror("ftruncate()");
337 		exit(EXIT_FAILURE);
338 	}
339 	p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE,
340 		MAP_SHARED, fd, 0);
341 	if (p != BASE_ADDR) {
342 		perror("mmap()");
343 		exit(EXIT_FAILURE);
344 	}
345 	fill_memory(p, 0, size);
346 	if (msync(p, size, MS_SYNC)) {
347 		perror("msync()");
348 		exit(EXIT_FAILURE);
349 	}
350 	close(fd);
351 	munmap(p, size);
352 	success("OK");
353 	ksft_print_msg("Opening %s %s for collapse...", finfo.path,
354 	       setup == FILE_SETUP_READ_ONLY_FS ? "read-only" :
355 	       setup == FILE_SETUP_READ_WRITE_FS_READ_DATA ?
356 						  "read-write (read)" :
357 						  "read-write (write)");
358 	finfo.fd = open(finfo.path, open_opt, 777);
359 	if (finfo.fd < 0)
360 		ksft_exit_fail_perror("open()");
361 	p = mmap(BASE_ADDR, size, mmap_prot, MAP_SHARED, finfo.fd, 0);
362 	if (p == MAP_FAILED || p != BASE_ADDR)
363 		ksft_exit_fail_perror("mmap()");
364 
365 	/* Drop page cache */
366 	write_file("/proc/sys/vm/drop_caches", "3", 2);
367 	success("OK");
368 	return p;
369 }
370 
371 static void *file_setup_read_only_area(int nr_hpages)
372 {
373 	return file_setup_area_common(nr_hpages, FILE_SETUP_READ_ONLY_FS);
374 }
375 
376 static void *file_setup_read_write_fs_read_area(int nr_hpages)
377 {
378 	return file_setup_area_common(nr_hpages, FILE_SETUP_READ_WRITE_FS_READ_DATA);
379 }
380 
381 static void *file_setup_read_write_fs_write_area(int nr_hpages)
382 {
383 	return file_setup_area_common(nr_hpages, FILE_SETUP_READ_WRITE_FS_WRITE_DATA);
384 }
385 
386 static void file_cleanup_area(void *p, unsigned long size)
387 {
388 	munmap(p, size);
389 	close(finfo.fd);
390 	unlink(finfo.path);
391 }
392 
393 static void file_fault_read(void *p, unsigned long start, unsigned long end)
394 {
395 	if (madvise(((char *)p) + start, end - start, MADV_POPULATE_READ))
396 		ksft_exit_fail_perror("madvise(MADV_POPULATE_READ)");
397 }
398 
399 static void file_fault_read_and_flush(void *p, unsigned long start, unsigned long end)
400 {
401 	file_fault_read(p, start, end);
402 	/*
403 	 * make folio clean, since dirty folios from read&write file are
404 	 * rejected and not flushed
405 	 */
406 	msync((char *)p + start, end - start, MS_SYNC);
407 }
408 
409 static void file_fault_write(void *p, unsigned long start, unsigned long end)
410 {
411 	if (madvise(((char *)p) + start, end - start, MADV_POPULATE_WRITE))
412 		ksft_exit_fail_perror("madvise(MADV_POPULATE_WRITE)");
413 }
414 
415 static bool file_check_huge(void *addr, int nr_hpages)
416 {
417 	switch (finfo.type) {
418 	case VMA_FILE:
419 		return check_huge_file(addr, nr_hpages, hpage_pmd_size);
420 	case VMA_SHMEM:
421 		return check_huge_shmem(addr, nr_hpages, hpage_pmd_size);
422 	default:
423 		exit(EXIT_FAILURE);
424 		return false;
425 	}
426 }
427 
428 static void *shmem_setup_area(int nr_hpages)
429 {
430 	void *p;
431 	unsigned long size = nr_hpages * hpage_pmd_size;
432 
433 	finfo.fd = memfd_create("khugepaged-selftest-collapse-shmem", 0);
434 	if (finfo.fd < 0)
435 		ksft_exit_fail_perror("memfd_create()");
436 	if (ftruncate(finfo.fd, size))
437 		ksft_exit_fail_perror("ftruncate()");
438 	p = mmap(BASE_ADDR, size, PROT_READ | PROT_WRITE, MAP_SHARED, finfo.fd,
439 		 0);
440 	if (p != BASE_ADDR)
441 		ksft_exit_fail_perror("mmap()");
442 	return p;
443 }
444 
445 static void shmem_cleanup_area(void *p, unsigned long size)
446 {
447 	munmap(p, size);
448 	close(finfo.fd);
449 }
450 
451 static bool shmem_check_huge(void *addr, int nr_hpages)
452 {
453 	return check_huge_shmem(addr, nr_hpages, hpage_pmd_size);
454 }
455 
456 static struct mem_ops __anon_ops = {
457 	.setup_area = &anon_setup_area,
458 	.cleanup_area = &anon_cleanup_area,
459 	.fault = &anon_fault,
460 	.check_huge = &anon_check_huge,
461 	.name = "anon",
462 };
463 
464 static struct mem_ops __read_only_file_ops = {
465 	.setup_area = &file_setup_read_only_area,
466 	.cleanup_area = &file_cleanup_area,
467 	.fault = &file_fault_read,
468 	.check_huge = &file_check_huge,
469 	.name = "file",
470 };
471 
472 static struct mem_ops __read_write_file_read_ops = {
473 	.setup_area = &file_setup_read_write_fs_read_area,
474 	.cleanup_area = &file_cleanup_area,
475 	.fault = &file_fault_read_and_flush,
476 	.check_huge = &file_check_huge,
477 	.name = "file",
478 };
479 
480 static struct mem_ops __read_write_file_write_ops = {
481 	.setup_area = &file_setup_read_write_fs_write_area,
482 	.cleanup_area = &file_cleanup_area,
483 	.fault = &file_fault_write,
484 	.check_huge = &file_check_huge,
485 	.name = "file",
486 };
487 
488 static struct mem_ops __shmem_ops = {
489 	.setup_area = &shmem_setup_area,
490 	.cleanup_area = &shmem_cleanup_area,
491 	.fault = &anon_fault,
492 	.check_huge = &shmem_check_huge,
493 	.name = "shmem",
494 };
495 
496 static bool is_tmpfs(struct mem_ops *ops)
497 {
498 	return (ops == &__read_only_file_ops ||
499 		ops == &__read_write_file_read_ops ||
500 		ops == &__read_write_file_write_ops) &&
501 	       finfo.type == VMA_SHMEM;
502 }
503 
504 static bool is_anon(struct mem_ops *ops)
505 {
506 	return ops == &__anon_ops;
507 }
508 
509 static void __madvise_collapse(const char *msg, char *p, int nr_hpages,
510 			       struct mem_ops *ops, bool expect)
511 {
512 	int ret;
513 	struct thp_settings settings = *thp_current_settings();
514 
515 	ksft_print_msg("%s...", msg);
516 
517 	/*
518 	 * read&write file collapse succeeds for MADV_COLLAPSE because dirty
519 	 * folios are written back after collapse fails for dirty folios and
520 	 * another collapse is attempted.
521 	 */
522 
523 	/*
524 	 * Prevent khugepaged interference and tests that MADV_COLLAPSE
525 	 * ignores /sys/kernel/mm/transparent_hugepage/enabled
526 	 */
527 	settings.thp_enabled = THP_NEVER;
528 	settings.shmem_enabled = SHMEM_NEVER;
529 	thp_push_settings(&settings);
530 
531 	/* Clear VM_NOHUGEPAGE */
532 	madvise(p, nr_hpages * hpage_pmd_size, MADV_HUGEPAGE);
533 	ret = madvise_collapse_retry(p, nr_hpages * hpage_pmd_size);
534 	if (((bool)ret) == expect)
535 		fail("Fail: Bad return value");
536 	else if (!ops->check_huge(p, expect ? nr_hpages : 0))
537 		fail("Fail: check_huge()");
538 	else
539 		success("OK");
540 
541 	thp_pop_settings();
542 }
543 
544 static void madvise_collapse(const char *msg, char *p, int nr_hpages,
545 			     struct mem_ops *ops, bool expect)
546 {
547 	/* Sanity check */
548 	if (!ops->check_huge(p, 0))
549 		ksft_exit_fail_msg("Unexpected huge page\n");
550 	__madvise_collapse(msg, p, nr_hpages, ops, expect);
551 }
552 
553 #define TICK 500000
554 static bool wait_for_scan(const char *msg, char *p, int nr_hpages,
555 			  struct mem_ops *ops)
556 {
557 	int full_scans;
558 	int timeout = 6; /* 3 seconds */
559 
560 	/* Sanity check */
561 	if (!ops->check_huge(p, 0))
562 		ksft_exit_fail_msg("Unexpected huge page\n");
563 
564 	madvise(p, nr_hpages * hpage_pmd_size, MADV_HUGEPAGE);
565 
566 	/* Wait until the second full_scan completed */
567 	full_scans = thp_read_num("khugepaged/full_scans") + 2;
568 
569 	ksft_print_msg("%s...", msg);
570 	while (timeout--) {
571 		if (ops->check_huge(p, nr_hpages))
572 			break;
573 		if (thp_read_num("khugepaged/full_scans") >= full_scans)
574 			break;
575 		printf(".");
576 		usleep(TICK);
577 	}
578 
579 	return timeout == -1;
580 }
581 
582 static void khugepaged_collapse(const char *msg, char *p, int nr_hpages,
583 				struct mem_ops *ops, bool expect)
584 {
585 	/*
586 	 * read&write file collapse fails since khugepaged does not flush
587 	 * the target dirty folios
588 	 */
589 	if (!is_tmpfs(ops) && ops == &__read_write_file_write_ops)
590 		expect = false;
591 
592 	if (wait_for_scan(msg, p, nr_hpages, ops)) {
593 		if (expect)
594 			fail("Timeout");
595 		else
596 			success("OK");
597 		return;
598 	}
599 
600 	/*
601 	 * For file and shmem memory, khugepaged only retracts pte entries after
602 	 * putting the new hugepage in the page cache. The hugepage must be
603 	 * subsequently refaulted to install the pmd mapping for the mm.
604 	 */
605 	if (ops != &__anon_ops)
606 		ops->fault(p, 0, nr_hpages * hpage_pmd_size);
607 
608 	if (ops->check_huge(p, expect ? nr_hpages : 0))
609 		success("OK");
610 	else
611 		fail("Fail");
612 }
613 
614 static struct collapse_context __khugepaged_context = {
615 	.collapse = &khugepaged_collapse,
616 	.enforce_pte_scan_limits = true,
617 	.name = "khugepaged",
618 };
619 
620 static struct collapse_context __madvise_context = {
621 	.collapse = &madvise_collapse,
622 	.enforce_pte_scan_limits = false,
623 	.name = "madvise",
624 };
625 
626 static void alloc_at_fault(void)
627 {
628 	struct thp_settings settings = *thp_current_settings();
629 	char *p;
630 
631 	settings.thp_enabled = THP_ALWAYS;
632 	thp_push_settings(&settings);
633 
634 	p = alloc_mapping(1);
635 	*p = 1;
636 	ksft_print_msg("Allocate huge page on fault...");
637 	if (check_huge_anon(p, 1, hpage_pmd_size))
638 		success("OK");
639 	else
640 		fail("Fail");
641 
642 	thp_pop_settings();
643 
644 	madvise(p, page_size, MADV_DONTNEED);
645 	ksft_print_msg("Split huge PMD on MADV_DONTNEED...");
646 	if (check_huge_anon(p, 0, hpage_pmd_size))
647 		success("OK");
648 	else
649 		fail("Fail");
650 	munmap(p, hpage_pmd_size);
651 
652 	ksft_test_result_report(exit_status, "allocate on fault and split\n");
653 }
654 
655 static void collapse_full(struct collapse_context *c, struct mem_ops *ops)
656 {
657 	void *p;
658 	int nr_hpages = 4;
659 	unsigned long size = nr_hpages * hpage_pmd_size;
660 
661 	p = ops->setup_area(nr_hpages);
662 	ops->fault(p, 0, size);
663 	c->collapse("Collapse multiple fully populated PTE table", p, nr_hpages,
664 		    ops, true);
665 	validate_memory(p, 0, size);
666 	ops->cleanup_area(p, size);
667 
668 	ksft_test_result_report(exit_status, "%s\n", __func__);
669 }
670 
671 static void collapse_empty(struct collapse_context *c, struct mem_ops *ops)
672 {
673 	void *p;
674 
675 	p = ops->setup_area(1);
676 	c->collapse("Do not collapse empty PTE table", p, 1, ops, false);
677 	ops->cleanup_area(p, hpage_pmd_size);
678 	ksft_test_result_report(exit_status, "%s\n", __func__);
679 }
680 
681 static void collapse_single_pte_entry(struct collapse_context *c, struct mem_ops *ops)
682 {
683 	void *p;
684 
685 	p = ops->setup_area(1);
686 	ops->fault(p, 0, page_size);
687 	c->collapse("Collapse PTE table with single PTE entry present", p,
688 		    1, ops, true);
689 	ops->cleanup_area(p, hpage_pmd_size);
690 	ksft_test_result_report(exit_status, "%s\n", __func__);
691 }
692 
693 static void collapse_max_ptes_none(struct collapse_context *c, struct mem_ops *ops)
694 {
695 	int max_ptes_none = hpage_pmd_nr / 2;
696 	struct thp_settings settings = *thp_current_settings();
697 	void *p;
698 	int fault_nr_pages = is_anon(ops) ? 1 << anon_order : 1;
699 
700 	settings.khugepaged.max_ptes_none = max_ptes_none;
701 	thp_push_settings(&settings);
702 
703 	p = ops->setup_area(1);
704 
705 	if (is_tmpfs(ops)) {
706 		/* shmem pages always in the page cache */
707 		printf("tmpfs...");
708 		skip("Skip");
709 		goto skip;
710 	}
711 
712 	ops->fault(p, 0, (hpage_pmd_nr - max_ptes_none - fault_nr_pages) * page_size);
713 	c->collapse("Maybe collapse with max_ptes_none exceeded", p, 1,
714 		    ops, !c->enforce_pte_scan_limits);
715 	validate_memory(p, 0, (hpage_pmd_nr - max_ptes_none - fault_nr_pages) * page_size);
716 
717 	if (c->enforce_pte_scan_limits) {
718 		ops->cleanup_area(p, hpage_pmd_size);
719 		p = ops->setup_area(1);
720 
721 		ops->fault(p, 0, (hpage_pmd_nr - max_ptes_none) * page_size);
722 		c->collapse("Collapse with max_ptes_none PTEs empty", p, 1, ops,
723 			    true);
724 		validate_memory(p, 0,
725 				(hpage_pmd_nr - max_ptes_none) * page_size);
726 	}
727 skip:
728 	ops->cleanup_area(p, hpage_pmd_size);
729 	thp_pop_settings();
730 	ksft_test_result_report(exit_status, "%s\n", __func__);
731 }
732 
733 static void collapse_swapin_single_pte(struct collapse_context *c, struct mem_ops *ops)
734 {
735 	void *p;
736 
737 	p = ops->setup_area(1);
738 	ops->fault(p, 0, hpage_pmd_size);
739 
740 	ksft_print_msg("Swapout one page...");
741 	if (madvise(p, page_size, MADV_PAGEOUT))
742 		ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
743 	if (check_swap(p, page_size)) {
744 		success("OK");
745 	} else {
746 		fail("Fail");
747 		goto out;
748 	}
749 
750 	c->collapse("Collapse with swapping in single PTE entry", p, 1, ops,
751 		    true);
752 	validate_memory(p, 0, hpage_pmd_size);
753 out:
754 	ops->cleanup_area(p, hpage_pmd_size);
755 	ksft_test_result_report(exit_status, "%s\n", __func__);
756 }
757 
758 static void collapse_max_ptes_swap(struct collapse_context *c, struct mem_ops *ops)
759 {
760 	int max_ptes_swap = thp_read_num("khugepaged/max_ptes_swap");
761 	void *p;
762 
763 	p = ops->setup_area(1);
764 	ops->fault(p, 0, hpage_pmd_size);
765 
766 	ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap + 1, hpage_pmd_nr);
767 	if (madvise(p, (max_ptes_swap + 1) * page_size, MADV_PAGEOUT))
768 		ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
769 	if (check_swap(p, (max_ptes_swap + 1) * page_size)) {
770 		success("OK");
771 	} else {
772 		fail("Fail");
773 		goto out;
774 	}
775 
776 	c->collapse("Maybe collapse with max_ptes_swap exceeded", p, 1, ops,
777 		    !c->enforce_pte_scan_limits);
778 	validate_memory(p, 0, hpage_pmd_size);
779 
780 	if (c->enforce_pte_scan_limits) {
781 		ops->fault(p, 0, hpage_pmd_size);
782 		ksft_print_msg("Swapout %d of %d pages...", max_ptes_swap,
783 		       hpage_pmd_nr);
784 		if (madvise(p, max_ptes_swap * page_size, MADV_PAGEOUT))
785 			ksft_exit_fail_perror("madvise(MADV_PAGEOUT)");
786 		if (check_swap(p, max_ptes_swap * page_size)) {
787 			success("OK");
788 		} else {
789 			fail("Fail");
790 			goto out;
791 		}
792 
793 		c->collapse("Collapse with max_ptes_swap pages swapped out", p,
794 			    1, ops, true);
795 		validate_memory(p, 0, hpage_pmd_size);
796 	}
797 out:
798 	ops->cleanup_area(p, hpage_pmd_size);
799 	ksft_test_result_report(exit_status, "%s\n", __func__);
800 }
801 
802 static void collapse_single_pte_entry_compound(struct collapse_context *c, struct mem_ops *ops)
803 {
804 	void *p;
805 
806 	p = alloc_hpage(ops);
807 
808 	if (is_tmpfs(ops)) {
809 		/* MADV_DONTNEED won't evict tmpfs pages */
810 		printf("tmpfs...");
811 		skip("Skip");
812 		goto skip;
813 	}
814 
815 	madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
816 	ksft_print_msg("Split huge page leaving single PTE mapping compound page...");
817 	madvise(p + page_size, hpage_pmd_size - page_size, MADV_DONTNEED);
818 	if (ops->check_huge(p, 0))
819 		success("OK");
820 	else
821 		fail("Fail");
822 
823 	c->collapse("Collapse PTE table with single PTE mapping compound page",
824 		    p, 1, ops, true);
825 	validate_memory(p, 0, page_size);
826 skip:
827 	ops->cleanup_area(p, hpage_pmd_size);
828 	ksft_test_result_report(exit_status, "%s\n", __func__);
829 }
830 
831 static void collapse_full_of_compound(struct collapse_context *c, struct mem_ops *ops)
832 {
833 	void *p;
834 
835 	p = alloc_hpage(ops);
836 	ksft_print_msg("Split huge page leaving single PTE page table full of compound pages...");
837 	madvise(p, page_size, MADV_NOHUGEPAGE);
838 	madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
839 	if (ops->check_huge(p, 0))
840 		success("OK");
841 	else
842 		fail("Fail");
843 
844 	c->collapse("Collapse PTE table full of compound pages", p, 1, ops,
845 		    true);
846 	validate_memory(p, 0, hpage_pmd_size);
847 	ops->cleanup_area(p, hpage_pmd_size);
848 	ksft_test_result_report(exit_status, "%s\n", __func__);
849 }
850 
851 static void collapse_compound_extreme(struct collapse_context *c, struct mem_ops *ops)
852 {
853 	void *p;
854 	int i;
855 
856 	p = ops->setup_area(1);
857 	ksft_print_msg("Construct PTE page table full of different PTE-mapped compound pages\n");
858 	for (i = 0; i < hpage_pmd_nr; i++) {
859 		madvise(BASE_ADDR, hpage_pmd_size, MADV_HUGEPAGE);
860 		ops->fault(BASE_ADDR, 0, hpage_pmd_size);
861 		if (!ops->check_huge(BASE_ADDR, 1))
862 			ksft_exit_fail_msg("Failed to allocate huge page\n");
863 		madvise(BASE_ADDR, hpage_pmd_size, MADV_NOHUGEPAGE);
864 
865 		p = mremap(BASE_ADDR - i * page_size,
866 				i * page_size + hpage_pmd_size,
867 				(i + 1) * page_size,
868 				MREMAP_MAYMOVE | MREMAP_FIXED,
869 				BASE_ADDR + 2 * hpage_pmd_size);
870 		if (p == MAP_FAILED)
871 			ksft_exit_fail_perror("mremap+unmap");
872 
873 		p = mremap(BASE_ADDR + 2 * hpage_pmd_size,
874 				(i + 1) * page_size,
875 				(i + 1) * page_size + hpage_pmd_size,
876 				MREMAP_MAYMOVE | MREMAP_FIXED,
877 				BASE_ADDR - (i + 1) * page_size);
878 		if (p == MAP_FAILED)
879 			ksft_exit_fail_perror("mremap+alloc");
880 	}
881 
882 	ops->cleanup_area(BASE_ADDR, hpage_pmd_size);
883 	ops->fault(p, 0, hpage_pmd_size);
884 	if (!ops->check_huge(p, 1))
885 		success("OK");
886 	else
887 		fail("Fail");
888 
889 	c->collapse("Collapse PTE table full of different compound pages", p, 1,
890 		    ops, true);
891 
892 	validate_memory(p, 0, hpage_pmd_size);
893 	ops->cleanup_area(p, hpage_pmd_size);
894 	ksft_test_result_report(exit_status, "%s\n", __func__);
895 }
896 
897 static void collapse_fork(struct collapse_context *c, struct mem_ops *ops)
898 {
899 	int wstatus;
900 	void *p;
901 
902 	p = ops->setup_area(1);
903 
904 	ksft_print_msg("Allocate small page...");
905 	ops->fault(p, 0, page_size);
906 	if (ops->check_huge(p, 0))
907 		success("OK");
908 	else
909 		fail("Fail");
910 
911 	ksft_print_msg("Share small page over fork()...");
912 	if (!fork()) {
913 		/* Do not touch settings on child exit */
914 		if (ops->check_huge(p, 0))
915 			success("OK");
916 		else
917 			fail("Fail");
918 
919 		ops->fault(p, page_size, 2 * page_size);
920 		c->collapse("Collapse PTE table with single page shared with parent process",
921 			    p, 1, ops, true);
922 
923 		validate_memory(p, 0, page_size);
924 		ops->cleanup_area(p, hpage_pmd_size);
925 		_exit(exit_status);
926 	}
927 
928 	wait(&wstatus);
929 	exit_status = WEXITSTATUS(wstatus);
930 
931 	ksft_print_msg("Check if parent still has small page...");
932 	if (ops->check_huge(p, 0))
933 		success("OK");
934 	else
935 		fail("Fail");
936 	validate_memory(p, 0, page_size);
937 	ops->cleanup_area(p, hpage_pmd_size);
938 	ksft_test_result_report(exit_status, "%s\n", __func__);
939 }
940 
941 static void collapse_fork_compound(struct collapse_context *c, struct mem_ops *ops)
942 {
943 	int wstatus;
944 	void *p;
945 
946 	p = alloc_hpage(ops);
947 	ksft_print_msg("Share huge page over fork()...");
948 	if (!fork()) {
949 		/* Do not touch settings on child exit */
950 		if (ops->check_huge(p, 1))
951 			success("OK");
952 		else
953 			fail("Fail");
954 
955 		ksft_print_msg("Split huge page PMD in child process...");
956 		madvise(p, page_size, MADV_NOHUGEPAGE);
957 		madvise(p, hpage_pmd_size, MADV_NOHUGEPAGE);
958 		if (ops->check_huge(p, 0))
959 			success("OK");
960 		else
961 			fail("Fail");
962 		ops->fault(p, 0, page_size);
963 
964 		thp_write_num("khugepaged/max_ptes_shared", hpage_pmd_nr - 1);
965 		c->collapse("Collapse PTE table full of compound pages in child",
966 			    p, 1, ops, true);
967 		thp_write_num("khugepaged/max_ptes_shared",
968 			  thp_current_settings()->khugepaged.max_ptes_shared);
969 
970 		validate_memory(p, 0, hpage_pmd_size);
971 		ops->cleanup_area(p, hpage_pmd_size);
972 		_exit(exit_status);
973 	}
974 
975 	wait(&wstatus);
976 	exit_status = WEXITSTATUS(wstatus);
977 
978 	ksft_print_msg("Check if parent still has huge page...");
979 	if (ops->check_huge(p, 1))
980 		success("OK");
981 	else
982 		fail("Fail");
983 	validate_memory(p, 0, hpage_pmd_size);
984 	ops->cleanup_area(p, hpage_pmd_size);
985 	ksft_test_result_report(exit_status, "%s\n", __func__);
986 }
987 
988 static void collapse_max_ptes_shared(struct collapse_context *c, struct mem_ops *ops)
989 {
990 	int max_ptes_shared = thp_read_num("khugepaged/max_ptes_shared");
991 	int wstatus;
992 	void *p;
993 
994 	p = alloc_hpage(ops);
995 	ksft_print_msg("Share huge page over fork()...");
996 	if (!fork()) {
997 		/* Do not touch settings on child exit */
998 		if (ops->check_huge(p, 1))
999 			success("OK");
1000 		else
1001 			fail("Fail");
1002 
1003 		ksft_print_msg("Trigger CoW on page %d of %d...",
1004 				hpage_pmd_nr - max_ptes_shared - 1, hpage_pmd_nr);
1005 		ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared - 1) * page_size);
1006 		if (ops->check_huge(p, 0))
1007 			success("OK");
1008 		else
1009 			fail("Fail");
1010 
1011 		c->collapse("Maybe collapse with max_ptes_shared exceeded", p,
1012 			    1, ops, !c->enforce_pte_scan_limits);
1013 
1014 		if (c->enforce_pte_scan_limits) {
1015 			ksft_print_msg("Trigger CoW on page %d of %d...",
1016 			       hpage_pmd_nr - max_ptes_shared, hpage_pmd_nr);
1017 			ops->fault(p, 0, (hpage_pmd_nr - max_ptes_shared) *
1018 				    page_size);
1019 			if (ops->check_huge(p, 0))
1020 				success("OK");
1021 			else
1022 				fail("Fail");
1023 
1024 			c->collapse("Collapse with max_ptes_shared PTEs shared",
1025 				    p, 1, ops, true);
1026 		}
1027 
1028 		validate_memory(p, 0, hpage_pmd_size);
1029 		ops->cleanup_area(p, hpage_pmd_size);
1030 		_exit(exit_status);
1031 	}
1032 
1033 	wait(&wstatus);
1034 	exit_status = WEXITSTATUS(wstatus);
1035 
1036 	ksft_print_msg("Check if parent still has huge page...");
1037 	if (ops->check_huge(p, 1))
1038 		success("OK");
1039 	else
1040 		fail("Fail");
1041 	validate_memory(p, 0, hpage_pmd_size);
1042 	ops->cleanup_area(p, hpage_pmd_size);
1043 	ksft_test_result_report(exit_status, "%s\n", __func__);
1044 }
1045 
1046 static void madvise_collapse_existing_thps(struct collapse_context *c,
1047 					   struct mem_ops *ops)
1048 {
1049 	void *p;
1050 
1051 	p = ops->setup_area(1);
1052 	ops->fault(p, 0, hpage_pmd_size);
1053 	c->collapse("Collapse fully populated PTE table...", p, 1, ops, true);
1054 	validate_memory(p, 0, hpage_pmd_size);
1055 
1056 	/* c->collapse() will find a hugepage and complain - call directly. */
1057 	__madvise_collapse("Re-collapse PMD-mapped hugepage", p, 1, ops, true);
1058 	validate_memory(p, 0, hpage_pmd_size);
1059 	ops->cleanup_area(p, hpage_pmd_size);
1060 	ksft_test_result_report(exit_status, "%s\n", __func__);
1061 }
1062 
1063 /*
1064  * Test race with khugepaged where page tables have been retracted and
1065  * pmd cleared.
1066  */
1067 static void madvise_retracted_page_tables(struct collapse_context *c,
1068 					  struct mem_ops *ops)
1069 {
1070 	void *p;
1071 	int nr_hpages = 1;
1072 	unsigned long size = nr_hpages * hpage_pmd_size;
1073 
1074 	p = ops->setup_area(nr_hpages);
1075 	ops->fault(p, 0, size);
1076 
1077 	/* Let khugepaged collapse and leave pmd cleared */
1078 	if (wait_for_scan("Collapse and leave PMD cleared", p, nr_hpages,
1079 			  ops)) {
1080 		fail("Timeout");
1081 		return;
1082 	}
1083 	success("OK");
1084 	c->collapse("Install huge PMD from page cache", p, nr_hpages, ops,
1085 		    true);
1086 	validate_memory(p, 0, size);
1087 	ops->cleanup_area(p, size);
1088 	ksft_test_result_report(exit_status, "%s\n", __func__);
1089 }
1090 
1091 static void usage(void)
1092 {
1093 	fprintf(stderr, "\nUsage: ./khugepaged [OPTIONS] <test type> [dir]\n\n");
1094 	fprintf(stderr, "\t<test type>\t: <context>:<mem_type>\n");
1095 	fprintf(stderr, "\t<context>\t: [all|khugepaged|madvise]\n");
1096 	fprintf(stderr, "\t<mem_type>\t: [all|anon|file|shmem]\n");
1097 	fprintf(stderr, "\n\t\"file,all\" mem_type requires [dir] argument\n");
1098 	fprintf(stderr, "\n\t\"file,all\" mem_type requires a file system\n");
1099 	fprintf(stderr,	"\twith PMD-sized large folio support\n");
1100 	fprintf(stderr, "\n\tif [dir] is a (sub)directory of a tmpfs mount, tmpfs must be\n");
1101 	fprintf(stderr,	"\tmounted with huge=advise option for khugepaged tests to work\n");
1102 	fprintf(stderr,	"\n\tSupported Options:\n");
1103 	fprintf(stderr,	"\t\t-h: This help message.\n");
1104 	fprintf(stderr,	"\t\t-s: mTHP size, expressed as page order.\n");
1105 	fprintf(stderr,	"\t\t    Defaults to 0. Use this size for anon or shmem allocations.\n");
1106 	exit(1);
1107 }
1108 
1109 static void parse_test_type(int argc, char **argv)
1110 {
1111 	int opt;
1112 	char *buf;
1113 	const char *token;
1114 
1115 	while ((opt = getopt(argc, argv, "s:h")) != -1) {
1116 		switch (opt) {
1117 		case 's':
1118 			anon_order = atoi(optarg);
1119 			break;
1120 		case 'h':
1121 		default:
1122 			usage();
1123 		}
1124 	}
1125 
1126 	argv += optind;
1127 	argc -= optind;
1128 
1129 	if (argc == 0) {
1130 		/* Backwards compatibility */
1131 		khugepaged_context =  &__khugepaged_context;
1132 		madvise_context =  &__madvise_context;
1133 		anon_ops = &__anon_ops;
1134 		return;
1135 	}
1136 
1137 	buf = strdup(argv[0]);
1138 	token = strsep(&buf, ":");
1139 
1140 	if (!strcmp(token, "all")) {
1141 		khugepaged_context =  &__khugepaged_context;
1142 		madvise_context =  &__madvise_context;
1143 	} else if (!strcmp(token, "khugepaged")) {
1144 		khugepaged_context =  &__khugepaged_context;
1145 	} else if (!strcmp(token, "madvise")) {
1146 		madvise_context =  &__madvise_context;
1147 	} else {
1148 		usage();
1149 	}
1150 
1151 	if (!buf)
1152 		usage();
1153 
1154 	if (!strcmp(buf, "all")) {
1155 		read_only_file_ops =  &__read_only_file_ops;
1156 		read_write_file_read_ops =  &__read_write_file_read_ops;
1157 		read_write_file_write_ops =  &__read_write_file_write_ops;
1158 		anon_ops = &__anon_ops;
1159 		shmem_ops = &__shmem_ops;
1160 	} else if (!strcmp(buf, "anon")) {
1161 		anon_ops = &__anon_ops;
1162 	} else if (!strcmp(buf, "file")) {
1163 		read_only_file_ops =  &__read_only_file_ops;
1164 		read_write_file_read_ops =  &__read_write_file_read_ops;
1165 		read_write_file_write_ops =  &__read_write_file_write_ops;
1166 	} else if (!strcmp(buf, "shmem")) {
1167 		shmem_ops = &__shmem_ops;
1168 	} else {
1169 		usage();
1170 	}
1171 
1172 	if (!read_only_file_ops && !read_write_file_read_ops &&
1173 	    !read_write_file_write_ops)
1174 		return;
1175 
1176 	if (argc != 2)
1177 		usage();
1178 
1179 	get_finfo(argv[1]);
1180 }
1181 
1182 typedef void (*test_fn)(struct collapse_context *c, struct mem_ops *ops);
1183 
1184 struct test_case {
1185 	struct collapse_context *ctx;
1186 	struct mem_ops *ops;
1187 	const char *desc;
1188 	test_fn fn;
1189 };
1190 
1191 #define MAX_TEST_CASES 64
1192 static struct test_case test_cases[MAX_TEST_CASES];
1193 static int nr_test_cases;
1194 
1195 #define TEST(t, c, o) do {						\
1196 	if (c && o) {							\
1197 		if (nr_test_cases >= MAX_TEST_CASES)			\
1198 			ksft_exit_fail_msg("MAX_TEST_CASES is too small\n"); \
1199 		test_cases[nr_test_cases++] = (struct test_case){	\
1200 			.ctx	= c,					\
1201 			.ops	= o,					\
1202 			.desc	= #t,					\
1203 			.fn	= t,					\
1204 		};							\
1205 	}								\
1206 	} while (0)
1207 
1208 int main(int argc, char **argv)
1209 {
1210 	int hpage_pmd_order;
1211 	struct thp_settings default_settings = {
1212 		.thp_enabled = THP_MADVISE,
1213 		.thp_defrag = THP_DEFRAG_ALWAYS,
1214 		.shmem_enabled = SHMEM_ADVISE,
1215 		.use_zero_page = 0,
1216 		.khugepaged = {
1217 			.defrag = 1,
1218 			.alloc_sleep_millisecs = 10,
1219 			.scan_sleep_millisecs = 10,
1220 		},
1221 		/*
1222 		 * When testing file-backed memory, the collapse path
1223 		 * looks at how many pages are found in the page cache, not
1224 		 * what pages are mapped. Disable read ahead optimization so
1225 		 * pages don't find their way into the page cache unless
1226 		 * we mem_ops->fault() them in.
1227 		 */
1228 		.read_ahead_kb = 0,
1229 	};
1230 
1231 	ksft_print_header();
1232 
1233 	if (!thp_is_enabled())
1234 		ksft_exit_skip("Transparent Hugepages not available\n");
1235 
1236 	parse_test_type(argc, argv);
1237 
1238 	setbuf(stdout, NULL);
1239 
1240 	page_size = getpagesize();
1241 	hpage_pmd_size = read_pmd_pagesize();
1242 	if (!hpage_pmd_size)
1243 		ksft_exit_fail_msg("Reading PMD pagesize failed\n");
1244 	hpage_pmd_nr = hpage_pmd_size / page_size;
1245 	hpage_pmd_order = __builtin_ctz(hpage_pmd_nr);
1246 
1247 	default_settings.khugepaged.max_ptes_none = hpage_pmd_nr - 1;
1248 	default_settings.khugepaged.max_ptes_swap = hpage_pmd_nr / 8;
1249 	default_settings.khugepaged.max_ptes_shared = hpage_pmd_nr / 2;
1250 	default_settings.khugepaged.pages_to_scan = hpage_pmd_nr * 8;
1251 	default_settings.hugepages[hpage_pmd_order].enabled = THP_INHERIT;
1252 	default_settings.hugepages[anon_order].enabled = THP_ALWAYS;
1253 	default_settings.shmem_hugepages[hpage_pmd_order].enabled = SHMEM_INHERIT;
1254 	default_settings.shmem_hugepages[anon_order].enabled = SHMEM_ALWAYS;
1255 
1256 	save_settings();
1257 	thp_push_settings(&default_settings);
1258 
1259 	TEST(collapse_full, khugepaged_context, anon_ops);
1260 	TEST(collapse_full, khugepaged_context, read_only_file_ops);
1261 	TEST(collapse_full, khugepaged_context, read_write_file_read_ops);
1262 	TEST(collapse_full, khugepaged_context, read_write_file_write_ops);
1263 	TEST(collapse_full, khugepaged_context, shmem_ops);
1264 	TEST(collapse_full, madvise_context, anon_ops);
1265 	TEST(collapse_full, madvise_context, read_only_file_ops);
1266 	TEST(collapse_full, madvise_context, read_write_file_read_ops);
1267 	TEST(collapse_full, madvise_context, read_write_file_write_ops);
1268 	TEST(collapse_full, madvise_context, shmem_ops);
1269 
1270 	TEST(collapse_empty, khugepaged_context, anon_ops);
1271 	TEST(collapse_empty, madvise_context, anon_ops);
1272 
1273 	TEST(collapse_single_pte_entry, khugepaged_context, anon_ops);
1274 	TEST(collapse_single_pte_entry, khugepaged_context, read_only_file_ops);
1275 	TEST(collapse_single_pte_entry, khugepaged_context, read_write_file_read_ops);
1276 	TEST(collapse_single_pte_entry, khugepaged_context, read_write_file_write_ops);
1277 	TEST(collapse_single_pte_entry, khugepaged_context, shmem_ops);
1278 	TEST(collapse_single_pte_entry, madvise_context, anon_ops);
1279 	TEST(collapse_single_pte_entry, madvise_context, read_only_file_ops);
1280 	TEST(collapse_single_pte_entry, madvise_context, read_write_file_read_ops);
1281 	TEST(collapse_single_pte_entry, madvise_context, read_write_file_write_ops);
1282 	TEST(collapse_single_pte_entry, madvise_context, shmem_ops);
1283 
1284 	TEST(collapse_max_ptes_none, khugepaged_context, anon_ops);
1285 	TEST(collapse_max_ptes_none, khugepaged_context, read_only_file_ops);
1286 	TEST(collapse_max_ptes_none, khugepaged_context, read_write_file_read_ops);
1287 	TEST(collapse_max_ptes_none, khugepaged_context, read_write_file_write_ops);
1288 	TEST(collapse_max_ptes_none, madvise_context, anon_ops);
1289 	TEST(collapse_max_ptes_none, madvise_context, read_only_file_ops);
1290 	TEST(collapse_max_ptes_none, madvise_context, read_write_file_read_ops);
1291 	TEST(collapse_max_ptes_none, madvise_context, read_write_file_write_ops);
1292 
1293 	TEST(collapse_single_pte_entry_compound, khugepaged_context, anon_ops);
1294 	TEST(collapse_single_pte_entry_compound, khugepaged_context, read_only_file_ops);
1295 	TEST(collapse_single_pte_entry_compound, khugepaged_context, read_write_file_read_ops);
1296 	TEST(collapse_single_pte_entry_compound, madvise_context, anon_ops);
1297 	TEST(collapse_single_pte_entry_compound, madvise_context, read_only_file_ops);
1298 	TEST(collapse_single_pte_entry_compound, madvise_context, read_write_file_read_ops);
1299 
1300 	TEST(collapse_full_of_compound, khugepaged_context, anon_ops);
1301 	TEST(collapse_full_of_compound, khugepaged_context, read_only_file_ops);
1302 	TEST(collapse_full_of_compound, khugepaged_context, read_write_file_read_ops);
1303 	TEST(collapse_full_of_compound, khugepaged_context, shmem_ops);
1304 	TEST(collapse_full_of_compound, madvise_context, anon_ops);
1305 	TEST(collapse_full_of_compound, madvise_context, read_only_file_ops);
1306 	TEST(collapse_full_of_compound, madvise_context, read_write_file_read_ops);
1307 	TEST(collapse_full_of_compound, madvise_context, shmem_ops);
1308 
1309 	TEST(collapse_compound_extreme, khugepaged_context, anon_ops);
1310 	TEST(collapse_compound_extreme, madvise_context, anon_ops);
1311 
1312 	TEST(collapse_swapin_single_pte, khugepaged_context, anon_ops);
1313 	TEST(collapse_swapin_single_pte, madvise_context, anon_ops);
1314 
1315 	TEST(collapse_max_ptes_swap, khugepaged_context, anon_ops);
1316 	TEST(collapse_max_ptes_swap, madvise_context, anon_ops);
1317 
1318 	TEST(collapse_fork, khugepaged_context, anon_ops);
1319 	TEST(collapse_fork, madvise_context, anon_ops);
1320 
1321 	TEST(collapse_fork_compound, khugepaged_context, anon_ops);
1322 	TEST(collapse_fork_compound, madvise_context, anon_ops);
1323 
1324 	TEST(collapse_max_ptes_shared, khugepaged_context, anon_ops);
1325 	TEST(collapse_max_ptes_shared, madvise_context, anon_ops);
1326 
1327 	TEST(madvise_collapse_existing_thps, madvise_context, anon_ops);
1328 	TEST(madvise_collapse_existing_thps, madvise_context, read_only_file_ops);
1329 	TEST(madvise_collapse_existing_thps, madvise_context, read_write_file_read_ops);
1330 	TEST(madvise_collapse_existing_thps, madvise_context, shmem_ops);
1331 
1332 	TEST(madvise_retracted_page_tables, madvise_context, read_only_file_ops);
1333 	TEST(madvise_retracted_page_tables, madvise_context, read_write_file_read_ops);
1334 	TEST(madvise_retracted_page_tables, madvise_context, shmem_ops);
1335 
1336 	ksft_set_plan(nr_test_cases + 1);
1337 
1338 	alloc_at_fault();
1339 	for (int i = 0; i < nr_test_cases; i++) {
1340 		struct test_case *t = &test_cases[i];
1341 
1342 		ksft_print_msg("\n# Run test: %s (%s:%s)\n", t->desc, t->ctx->name, t->ops->name);
1343 		t->fn(t->ctx, t->ops);
1344 	}
1345 
1346 	ksft_finished();
1347 }
1348