xref: /linux/tools/testing/selftests/mm/pagemap_ioctl.c (revision 4b66d18918f8e4d85e51974a9e3ce9abad5c7c3d)
1 // SPDX-License-Identifier: GPL-2.0
2 
3 #define _GNU_SOURCE
4 #include <stdio.h>
5 #include <fcntl.h>
6 #include <string.h>
7 #include <sys/mman.h>
8 #include <errno.h>
9 #include <malloc.h>
10 #include "vm_util.h"
11 #include "../kselftest.h"
12 #include <linux/types.h>
13 #include <linux/memfd.h>
14 #include <linux/userfaultfd.h>
15 #include <linux/fs.h>
16 #include <sys/ioctl.h>
17 #include <sys/stat.h>
18 #include <math.h>
19 #include <asm/unistd.h>
20 #include <pthread.h>
21 #include <sys/resource.h>
22 #include <assert.h>
23 #include <sys/ipc.h>
24 #include <sys/shm.h>
25 
26 #define PAGEMAP_BITS_ALL		(PAGE_IS_WPALLOWED | PAGE_IS_WRITTEN |	\
27 					 PAGE_IS_FILE | PAGE_IS_PRESENT |	\
28 					 PAGE_IS_SWAPPED | PAGE_IS_PFNZERO |	\
29 					 PAGE_IS_HUGE)
30 #define PAGEMAP_NON_WRITTEN_BITS	(PAGE_IS_WPALLOWED | PAGE_IS_FILE |	\
31 					 PAGE_IS_PRESENT | PAGE_IS_SWAPPED |	\
32 					 PAGE_IS_PFNZERO | PAGE_IS_HUGE)
33 
34 #define TEST_ITERATIONS 100
35 #define PAGEMAP "/proc/self/pagemap"
36 int pagemap_fd;
37 int uffd;
38 size_t page_size;
39 size_t hpage_size;
40 const char *progname;
41 
42 #define LEN(region)	((region.end - region.start)/page_size)
43 
44 static long pagemap_ioctl(void *start, int len, void *vec, int vec_len, int flag,
45 			  int max_pages, long required_mask, long anyof_mask, long excluded_mask,
46 			  long return_mask)
47 {
48 	struct pm_scan_arg arg;
49 
50 	arg.start = (uintptr_t)start;
51 	arg.end = (uintptr_t)(start + len);
52 	arg.vec = (uintptr_t)vec;
53 	arg.vec_len = vec_len;
54 	arg.flags = flag;
55 	arg.size = sizeof(struct pm_scan_arg);
56 	arg.max_pages = max_pages;
57 	arg.category_mask = required_mask;
58 	arg.category_anyof_mask = anyof_mask;
59 	arg.category_inverted = excluded_mask;
60 	arg.return_mask = return_mask;
61 
62 	return ioctl(pagemap_fd, PAGEMAP_SCAN, &arg);
63 }
64 
65 static long pagemap_ioc(void *start, int len, void *vec, int vec_len, int flag,
66 			int max_pages, long required_mask, long anyof_mask, long excluded_mask,
67 			long return_mask, long *walk_end)
68 {
69 	struct pm_scan_arg arg;
70 	int ret;
71 
72 	arg.start = (uintptr_t)start;
73 	arg.end = (uintptr_t)(start + len);
74 	arg.vec = (uintptr_t)vec;
75 	arg.vec_len = vec_len;
76 	arg.flags = flag;
77 	arg.size = sizeof(struct pm_scan_arg);
78 	arg.max_pages = max_pages;
79 	arg.category_mask = required_mask;
80 	arg.category_anyof_mask = anyof_mask;
81 	arg.category_inverted = excluded_mask;
82 	arg.return_mask = return_mask;
83 
84 	ret = ioctl(pagemap_fd, PAGEMAP_SCAN, &arg);
85 
86 	if (walk_end)
87 		*walk_end = arg.walk_end;
88 
89 	return ret;
90 }
91 
92 
93 int init_uffd(void)
94 {
95 	struct uffdio_api uffdio_api;
96 
97 	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK | UFFD_USER_MODE_ONLY);
98 	if (uffd == -1)
99 		return uffd;
100 
101 	uffdio_api.api = UFFD_API;
102 	uffdio_api.features = UFFD_FEATURE_WP_UNPOPULATED | UFFD_FEATURE_WP_ASYNC |
103 			      UFFD_FEATURE_WP_HUGETLBFS_SHMEM;
104 	if (ioctl(uffd, UFFDIO_API, &uffdio_api))
105 		return -1;
106 
107 	if (!(uffdio_api.api & UFFDIO_REGISTER_MODE_WP) ||
108 	    !(uffdio_api.features & UFFD_FEATURE_WP_UNPOPULATED) ||
109 	    !(uffdio_api.features & UFFD_FEATURE_WP_ASYNC) ||
110 	    !(uffdio_api.features & UFFD_FEATURE_WP_HUGETLBFS_SHMEM))
111 		return -1;
112 
113 	return 0;
114 }
115 
116 int wp_init(void *lpBaseAddress, long dwRegionSize)
117 {
118 	struct uffdio_register uffdio_register;
119 	struct uffdio_writeprotect wp;
120 
121 	uffdio_register.range.start = (unsigned long)lpBaseAddress;
122 	uffdio_register.range.len = dwRegionSize;
123 	uffdio_register.mode = UFFDIO_REGISTER_MODE_WP;
124 	if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register))
125 		ksft_exit_fail_msg("ioctl(UFFDIO_REGISTER) %d %s\n", errno, strerror(errno));
126 
127 	if (!(uffdio_register.ioctls & UFFDIO_WRITEPROTECT))
128 		ksft_exit_fail_msg("ioctl set is incorrect\n");
129 
130 	wp.range.start = (unsigned long)lpBaseAddress;
131 	wp.range.len = dwRegionSize;
132 	wp.mode = UFFDIO_WRITEPROTECT_MODE_WP;
133 
134 	if (ioctl(uffd, UFFDIO_WRITEPROTECT, &wp))
135 		ksft_exit_fail_msg("ioctl(UFFDIO_WRITEPROTECT)\n");
136 
137 	return 0;
138 }
139 
140 int wp_free(void *lpBaseAddress, long dwRegionSize)
141 {
142 	struct uffdio_register uffdio_register;
143 
144 	uffdio_register.range.start = (unsigned long)lpBaseAddress;
145 	uffdio_register.range.len = dwRegionSize;
146 	uffdio_register.mode = UFFDIO_REGISTER_MODE_WP;
147 	if (ioctl(uffd, UFFDIO_UNREGISTER, &uffdio_register.range))
148 		ksft_exit_fail_msg("ioctl unregister failure\n");
149 	return 0;
150 }
151 
152 int wp_addr_range(void *lpBaseAddress, int dwRegionSize)
153 {
154 	if (pagemap_ioctl(lpBaseAddress, dwRegionSize, NULL, 0,
155 			  PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
156 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) < 0)
157 		ksft_exit_fail_msg("error %d %d %s\n", 1, errno, strerror(errno));
158 
159 	return 0;
160 }
161 
162 void *gethugetlb_mem(int size, int *shmid)
163 {
164 	char *mem;
165 
166 	if (shmid) {
167 		*shmid = shmget(2, size, SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W);
168 		if (*shmid < 0)
169 			return NULL;
170 
171 		mem = shmat(*shmid, 0, 0);
172 		if (mem == (char *)-1) {
173 			shmctl(*shmid, IPC_RMID, NULL);
174 			ksft_exit_fail_msg("Shared memory attach failure\n");
175 		}
176 	} else {
177 		mem = mmap(NULL, size, PROT_READ | PROT_WRITE,
178 			   MAP_ANONYMOUS | MAP_HUGETLB | MAP_PRIVATE, -1, 0);
179 		if (mem == MAP_FAILED)
180 			return NULL;
181 	}
182 
183 	return mem;
184 }
185 
186 int userfaultfd_tests(void)
187 {
188 	long mem_size, vec_size, written, num_pages = 16;
189 	char *mem, *vec;
190 
191 	mem_size = num_pages * page_size;
192 	mem = mmap(NULL, mem_size, PROT_NONE, MAP_PRIVATE | MAP_ANON, -1, 0);
193 	if (mem == MAP_FAILED)
194 		ksft_exit_fail_msg("error nomem\n");
195 
196 	wp_init(mem, mem_size);
197 
198 	/* Change protection of pages differently */
199 	mprotect(mem, mem_size/8, PROT_READ|PROT_WRITE);
200 	mprotect(mem + 1 * mem_size/8, mem_size/8, PROT_READ);
201 	mprotect(mem + 2 * mem_size/8, mem_size/8, PROT_READ|PROT_WRITE);
202 	mprotect(mem + 3 * mem_size/8, mem_size/8, PROT_READ);
203 	mprotect(mem + 4 * mem_size/8, mem_size/8, PROT_READ|PROT_WRITE);
204 	mprotect(mem + 5 * mem_size/8, mem_size/8, PROT_NONE);
205 	mprotect(mem + 6 * mem_size/8, mem_size/8, PROT_READ|PROT_WRITE);
206 	mprotect(mem + 7 * mem_size/8, mem_size/8, PROT_READ);
207 
208 	wp_addr_range(mem + (mem_size/16), mem_size - 2 * (mem_size/8));
209 	wp_addr_range(mem, mem_size);
210 
211 	vec_size = mem_size/page_size;
212 	vec = malloc(sizeof(struct page_region) * vec_size);
213 
214 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
215 				vec_size - 2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
216 	if (written < 0)
217 		ksft_exit_fail_msg("error %ld %d %s\n", written, errno, strerror(errno));
218 
219 	ksft_test_result(written == 0, "%s all new pages must not be written (dirty)\n", __func__);
220 
221 	wp_free(mem, mem_size);
222 	munmap(mem, mem_size);
223 	free(vec);
224 	return 0;
225 }
226 
227 int get_reads(struct page_region *vec, int vec_size)
228 {
229 	int i, sum = 0;
230 
231 	for (i = 0; i < vec_size; i++)
232 		sum += LEN(vec[i]);
233 
234 	return sum;
235 }
236 
237 int sanity_tests_sd(void)
238 {
239 	unsigned long long mem_size, vec_size, i, total_pages = 0;
240 	long ret, ret2, ret3;
241 	int num_pages = 1000;
242 	int total_writes, total_reads, reads, count;
243 	struct page_region *vec, *vec2;
244 	char *mem, *m[2];
245 	long walk_end;
246 
247 	vec_size = num_pages/2;
248 	mem_size = num_pages * page_size;
249 
250 	vec = malloc(sizeof(struct page_region) * vec_size);
251 	if (!vec)
252 		ksft_exit_fail_msg("error nomem\n");
253 
254 	vec2 = malloc(sizeof(struct page_region) * vec_size);
255 	if (!vec2)
256 		ksft_exit_fail_msg("error nomem\n");
257 
258 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
259 	if (mem == MAP_FAILED)
260 		ksft_exit_fail_msg("error nomem\n");
261 
262 	wp_init(mem, mem_size);
263 	wp_addr_range(mem, mem_size);
264 
265 	/* 1. wrong operation */
266 	ksft_test_result(pagemap_ioctl(mem, 0, vec, vec_size, 0,
267 				       0, PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) == 0,
268 			 "%s Zero range size is valid\n", __func__);
269 
270 	ksft_test_result(pagemap_ioctl(mem, mem_size, NULL, vec_size, 0,
271 				       0, PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) < 0,
272 			 "%s output buffer must be specified with size\n", __func__);
273 
274 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, 0, 0,
275 				       0, PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) == 0,
276 			 "%s output buffer can be 0\n", __func__);
277 
278 	ksft_test_result(pagemap_ioctl(mem, mem_size, 0, 0, 0,
279 				       0, PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) == 0,
280 			 "%s output buffer can be 0\n", __func__);
281 
282 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, -1,
283 				       0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) < 0,
284 			 "%s wrong flag specified\n", __func__);
285 
286 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size,
287 				       PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC | 0xFF,
288 				       0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) < 0,
289 			 "%s flag has extra bits specified\n", __func__);
290 
291 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0,
292 				       0, 0, 0, 0, PAGE_IS_WRITTEN) >= 0,
293 			 "%s no selection mask is specified\n", __func__);
294 
295 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0,
296 				       0, PAGE_IS_WRITTEN, PAGE_IS_WRITTEN, 0, 0) == 0,
297 			 "%s no return mask is specified\n", __func__);
298 
299 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0,
300 				       0, PAGE_IS_WRITTEN, 0, 0, 0x1000) < 0,
301 			 "%s wrong return mask specified\n", __func__);
302 
303 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size,
304 				       PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
305 				       0, 0xFFF, PAGE_IS_WRITTEN, 0, PAGE_IS_WRITTEN) < 0,
306 			 "%s mixture of correct and wrong flag\n", __func__);
307 
308 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size,
309 				       PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
310 				       0, 0, 0, PAGEMAP_BITS_ALL, PAGE_IS_WRITTEN) >= 0,
311 			 "%s PAGEMAP_BITS_ALL can be specified with PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC\n",
312 			 __func__);
313 
314 	/* 2. Clear area with larger vec size */
315 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
316 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC, 0,
317 			    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
318 	ksft_test_result(ret >= 0, "%s Clear area with larger vec size\n", __func__);
319 
320 	/* 3. Repeated pattern of written and non-written pages */
321 	for (i = 0; i < mem_size; i += 2 * page_size)
322 		mem[i]++;
323 
324 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0, PAGE_IS_WRITTEN, 0,
325 			    0, PAGE_IS_WRITTEN);
326 	if (ret < 0)
327 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
328 
329 	ksft_test_result((unsigned long long)ret == mem_size/(page_size * 2),
330 			 "%s Repeated pattern of written and non-written pages\n", __func__);
331 
332 	/* 4. Repeated pattern of written and non-written pages in parts */
333 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
334 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
335 			    num_pages/2 - 2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
336 	if (ret < 0)
337 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
338 
339 	ret2 = pagemap_ioctl(mem, mem_size, vec, 2, 0, 0, PAGE_IS_WRITTEN, 0, 0,
340 			     PAGE_IS_WRITTEN);
341 	if (ret2 < 0)
342 		ksft_exit_fail_msg("error %ld %d %s\n", ret2, errno, strerror(errno));
343 
344 	ret3 = pagemap_ioctl(mem, mem_size, vec, vec_size,
345 			     PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
346 			     0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
347 	if (ret3 < 0)
348 		ksft_exit_fail_msg("error %ld %d %s\n", ret3, errno, strerror(errno));
349 
350 	ksft_test_result((ret + ret3) == num_pages/2 && ret2 == 2,
351 			 "%s Repeated pattern of written and non-written pages in parts %ld %ld %ld\n",
352 			 __func__, ret, ret3, ret2);
353 
354 	/* 5. Repeated pattern of written and non-written pages max_pages */
355 	for (i = 0; i < mem_size; i += 2 * page_size)
356 		mem[i]++;
357 	mem[(mem_size/page_size - 1) * page_size]++;
358 
359 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
360 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
361 			    num_pages/2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
362 	if (ret < 0)
363 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
364 
365 	ret2 = pagemap_ioctl(mem, mem_size, vec, vec_size,
366 			     PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
367 			     0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
368 	if (ret2 < 0)
369 		ksft_exit_fail_msg("error %ld %d %s\n", ret2, errno, strerror(errno));
370 
371 	ksft_test_result(ret == num_pages/2 && ret2 == 1,
372 			 "%s Repeated pattern of written and non-written pages max_pages\n",
373 			 __func__);
374 
375 	/* 6. only get 2 dirty pages and clear them as well */
376 	vec_size = mem_size/page_size;
377 	memset(mem, -1, mem_size);
378 
379 	/* get and clear second and third pages */
380 	ret = pagemap_ioctl(mem + page_size, 2 * page_size, vec, 1,
381 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
382 			    2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
383 	if (ret < 0)
384 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
385 
386 	ret2 = pagemap_ioctl(mem, mem_size, vec2, vec_size, 0, 0,
387 			      PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
388 	if (ret2 < 0)
389 		ksft_exit_fail_msg("error %ld %d %s\n", ret2, errno, strerror(errno));
390 
391 	ksft_test_result(ret == 1 && LEN(vec[0]) == 2 &&
392 			 vec[0].start == (uintptr_t)(mem + page_size) &&
393 			 ret2 == 2 && LEN(vec2[0]) == 1 && vec2[0].start == (uintptr_t)mem &&
394 			 LEN(vec2[1]) == vec_size - 3 &&
395 			 vec2[1].start == (uintptr_t)(mem + 3 * page_size),
396 			 "%s only get 2 written pages and clear them as well\n", __func__);
397 
398 	wp_free(mem, mem_size);
399 	munmap(mem, mem_size);
400 
401 	/* 7. Two regions */
402 	m[0] = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
403 	if (m[0] == MAP_FAILED)
404 		ksft_exit_fail_msg("error nomem\n");
405 	m[1] = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
406 	if (m[1] == MAP_FAILED)
407 		ksft_exit_fail_msg("error nomem\n");
408 
409 	wp_init(m[0], mem_size);
410 	wp_init(m[1], mem_size);
411 	wp_addr_range(m[0], mem_size);
412 	wp_addr_range(m[1], mem_size);
413 
414 	memset(m[0], 'a', mem_size);
415 	memset(m[1], 'b', mem_size);
416 
417 	wp_addr_range(m[0], mem_size);
418 
419 	ret = pagemap_ioctl(m[1], mem_size, vec, 1, 0, 0, PAGE_IS_WRITTEN, 0, 0,
420 			    PAGE_IS_WRITTEN);
421 	if (ret < 0)
422 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
423 
424 	ksft_test_result(ret == 1 && LEN(vec[0]) == mem_size/page_size,
425 			 "%s Two regions\n", __func__);
426 
427 	wp_free(m[0], mem_size);
428 	wp_free(m[1], mem_size);
429 	munmap(m[0], mem_size);
430 	munmap(m[1], mem_size);
431 
432 	free(vec);
433 	free(vec2);
434 
435 	/* 8. Smaller vec */
436 	mem_size = 1050 * page_size;
437 	vec_size = mem_size/(page_size*2);
438 
439 	vec = malloc(sizeof(struct page_region) * vec_size);
440 	if (!vec)
441 		ksft_exit_fail_msg("error nomem\n");
442 
443 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
444 	if (mem == MAP_FAILED)
445 		ksft_exit_fail_msg("error nomem\n");
446 
447 	wp_init(mem, mem_size);
448 	wp_addr_range(mem, mem_size);
449 
450 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
451 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC, 0,
452 			    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
453 	if (ret < 0)
454 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
455 
456 	for (i = 0; i < mem_size/page_size; i += 2)
457 		mem[i * page_size]++;
458 
459 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
460 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
461 			    mem_size/(page_size*5), PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
462 	if (ret < 0)
463 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
464 
465 	total_pages += ret;
466 
467 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
468 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
469 			    mem_size/(page_size*5), PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
470 	if (ret < 0)
471 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
472 
473 	total_pages += ret;
474 
475 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
476 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
477 			    mem_size/(page_size*5), PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
478 	if (ret < 0)
479 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
480 
481 	total_pages += ret;
482 
483 	ksft_test_result(total_pages == mem_size/(page_size*2), "%s Smaller max_pages\n", __func__);
484 
485 	free(vec);
486 	wp_free(mem, mem_size);
487 	munmap(mem, mem_size);
488 	total_pages = 0;
489 
490 	/* 9. Smaller vec */
491 	mem_size = 10000 * page_size;
492 	vec_size = 50;
493 
494 	vec = malloc(sizeof(struct page_region) * vec_size);
495 	if (!vec)
496 		ksft_exit_fail_msg("error nomem\n");
497 
498 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
499 	if (mem == MAP_FAILED)
500 		ksft_exit_fail_msg("error nomem\n");
501 
502 	wp_init(mem, mem_size);
503 	wp_addr_range(mem, mem_size);
504 
505 	for (count = 0; count < TEST_ITERATIONS; count++) {
506 		total_writes = total_reads = 0;
507 		walk_end = (long)mem;
508 
509 		for (i = 0; i < mem_size; i += page_size) {
510 			if (rand() % 2) {
511 				mem[i]++;
512 				total_writes++;
513 			}
514 		}
515 
516 		while (total_reads < total_writes) {
517 			ret = pagemap_ioc((void *)walk_end, mem_size-(walk_end - (long)mem), vec,
518 					  vec_size, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
519 					  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
520 			if (ret < 0)
521 				ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
522 
523 			if ((unsigned long)ret > vec_size)
524 				break;
525 
526 			reads = get_reads(vec, ret);
527 			total_reads += reads;
528 		}
529 
530 		if (total_reads != total_writes)
531 			break;
532 	}
533 
534 	ksft_test_result(count == TEST_ITERATIONS, "Smaller vec\n");
535 
536 	free(vec);
537 	wp_free(mem, mem_size);
538 	munmap(mem, mem_size);
539 
540 	/* 10. Walk_end tester */
541 	vec_size = 1000;
542 	mem_size = vec_size * page_size;
543 
544 	vec = malloc(sizeof(struct page_region) * vec_size);
545 	if (!vec)
546 		ksft_exit_fail_msg("error nomem\n");
547 
548 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
549 	if (mem == MAP_FAILED)
550 		ksft_exit_fail_msg("error nomem\n");
551 
552 	wp_init(mem, mem_size);
553 	wp_addr_range(mem, mem_size);
554 
555 	memset(mem, 0, mem_size);
556 
557 	ret = pagemap_ioc(mem, 0, vec, vec_size, 0,
558 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
559 	if (ret < 0)
560 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
561 	ksft_test_result(ret == 0 && walk_end == (long)mem,
562 			 "Walk_end: Same start and end address\n");
563 
564 	ret = pagemap_ioc(mem, 0, vec, vec_size, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
565 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
566 	if (ret < 0)
567 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
568 	ksft_test_result(ret == 0 && walk_end == (long)mem,
569 			 "Walk_end: Same start and end with WP\n");
570 
571 	ret = pagemap_ioc(mem, 0, vec, 0, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
572 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
573 	if (ret < 0)
574 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
575 	ksft_test_result(ret == 0 && walk_end == (long)mem,
576 			 "Walk_end: Same start and end with 0 output buffer\n");
577 
578 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
579 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
580 	if (ret < 0)
581 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
582 	ksft_test_result(ret == 1 && walk_end == (long)(mem + mem_size),
583 			 "Walk_end: Big vec\n");
584 
585 	ret = pagemap_ioc(mem, mem_size, vec, 1, 0,
586 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
587 	if (ret < 0)
588 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
589 	ksft_test_result(ret == 1 && walk_end == (long)(mem + mem_size),
590 			 "Walk_end: vec of minimum length\n");
591 
592 	ret = pagemap_ioc(mem, mem_size, vec, 1, 0,
593 			  vec_size, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
594 	if (ret < 0)
595 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
596 	ksft_test_result(ret == 1 && walk_end == (long)(mem + mem_size),
597 			 "Walk_end: Max pages specified\n");
598 
599 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
600 			  vec_size/2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
601 	if (ret < 0)
602 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
603 	ksft_test_result(ret == 1 && walk_end == (long)(mem + mem_size/2),
604 			 "Walk_end: Half max pages\n");
605 
606 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
607 			  1, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
608 	if (ret < 0)
609 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
610 	ksft_test_result(ret == 1 && walk_end == (long)(mem + page_size),
611 			 "Walk_end: 1 max page\n");
612 
613 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
614 			  -1, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
615 	if (ret < 0)
616 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
617 	ksft_test_result(ret == 1 && walk_end == (long)(mem + mem_size),
618 			 "Walk_end: max pages\n");
619 
620 	wp_addr_range(mem, mem_size);
621 	for (i = 0; i < mem_size; i += 2 * page_size)
622 		mem[i]++;
623 
624 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
625 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
626 	if (ret < 0)
627 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
628 	ksft_test_result((unsigned long)ret == vec_size/2 && walk_end == (long)(mem + mem_size),
629 			 "Walk_end sparse: Big vec\n");
630 
631 	ret = pagemap_ioc(mem, mem_size, vec, 1, 0,
632 			  0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
633 	if (ret < 0)
634 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
635 	ksft_test_result(ret == 1 && walk_end == (long)(mem + page_size * 2),
636 			 "Walk_end sparse: vec of minimum length\n");
637 
638 	ret = pagemap_ioc(mem, mem_size, vec, 1, 0,
639 			  vec_size, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
640 	if (ret < 0)
641 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
642 	ksft_test_result(ret == 1 && walk_end == (long)(mem + page_size * 2),
643 			 "Walk_end sparse: Max pages specified\n");
644 
645 	ret = pagemap_ioc(mem, mem_size, vec, vec_size/2, 0,
646 			  vec_size, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
647 	if (ret < 0)
648 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
649 	ksft_test_result((unsigned long)ret == vec_size/2 && walk_end == (long)(mem + mem_size),
650 			 "Walk_end sparse: Max pages specified\n");
651 
652 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
653 			  vec_size, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
654 	if (ret < 0)
655 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
656 	ksft_test_result((unsigned long)ret == vec_size/2 && walk_end == (long)(mem + mem_size),
657 			 "Walk_end sparse: Max pages specified\n");
658 
659 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
660 			  vec_size/2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
661 	if (ret < 0)
662 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
663 	ksft_test_result((unsigned long)ret == vec_size/2 && walk_end == (long)(mem + mem_size),
664 			 "Walk_endsparse : Half max pages\n");
665 
666 	ret = pagemap_ioc(mem, mem_size, vec, vec_size, 0,
667 			  1, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN, &walk_end);
668 	if (ret < 0)
669 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
670 	ksft_test_result(ret == 1 && walk_end == (long)(mem + page_size * 2),
671 			 "Walk_end: 1 max page\n");
672 
673 	free(vec);
674 	wp_free(mem, mem_size);
675 	munmap(mem, mem_size);
676 
677 	return 0;
678 }
679 
680 int base_tests(char *prefix, char *mem, unsigned long long mem_size, int skip)
681 {
682 	unsigned long long vec_size;
683 	int written;
684 	struct page_region *vec, *vec2;
685 
686 	if (skip) {
687 		ksft_test_result_skip("%s all new pages must not be written (dirty)\n", prefix);
688 		ksft_test_result_skip("%s all pages must be written (dirty)\n", prefix);
689 		ksft_test_result_skip("%s all pages dirty other than first and the last one\n",
690 				      prefix);
691 		ksft_test_result_skip("%s PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC\n", prefix);
692 		ksft_test_result_skip("%s only middle page dirty\n", prefix);
693 		ksft_test_result_skip("%s only two middle pages dirty\n", prefix);
694 		return 0;
695 	}
696 
697 	vec_size = mem_size/page_size;
698 	vec = malloc(sizeof(struct page_region) * vec_size);
699 	vec2 = malloc(sizeof(struct page_region) * vec_size);
700 
701 	/* 1. all new pages must be not be written (dirty) */
702 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
703 				vec_size - 2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
704 	if (written < 0)
705 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
706 
707 	ksft_test_result(written == 0, "%s all new pages must not be written (dirty)\n", prefix);
708 
709 	/* 2. all pages must be written */
710 	memset(mem, -1, mem_size);
711 
712 	written = pagemap_ioctl(mem, mem_size, vec, 1, 0, 0, PAGE_IS_WRITTEN, 0, 0,
713 			      PAGE_IS_WRITTEN);
714 	if (written < 0)
715 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
716 
717 	ksft_test_result(written == 1 && LEN(vec[0]) == mem_size/page_size,
718 			 "%s all pages must be written (dirty)\n", prefix);
719 
720 	/* 3. all pages dirty other than first and the last one */
721 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
722 				0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
723 	if (written < 0)
724 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
725 
726 	memset(mem + page_size, 0, mem_size - (2 * page_size));
727 
728 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
729 				0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
730 	if (written < 0)
731 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
732 
733 	ksft_test_result(written == 1 && LEN(vec[0]) >= vec_size - 2 && LEN(vec[0]) <= vec_size,
734 			 "%s all pages dirty other than first and the last one\n", prefix);
735 
736 	written = pagemap_ioctl(mem, mem_size, vec, 1, 0, 0,
737 				PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
738 	if (written < 0)
739 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
740 
741 	ksft_test_result(written == 0,
742 			 "%s PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC\n", prefix);
743 
744 	/* 4. only middle page dirty */
745 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
746 				0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
747 	if (written < 0)
748 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
749 
750 	mem[vec_size/2 * page_size]++;
751 
752 	written = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0, PAGE_IS_WRITTEN,
753 				0, 0, PAGE_IS_WRITTEN);
754 	if (written < 0)
755 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
756 
757 	ksft_test_result(written == 1 && LEN(vec[0]) >= 1,
758 			 "%s only middle page dirty\n", prefix);
759 
760 	/* 5. only two middle pages dirty and walk over only middle pages */
761 	written = pagemap_ioctl(mem, mem_size, vec, 1, PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
762 				0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN | PAGE_IS_HUGE);
763 	if (written < 0)
764 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
765 
766 	mem[vec_size/2 * page_size]++;
767 	mem[(vec_size/2 + 1) * page_size]++;
768 
769 	written = pagemap_ioctl(&mem[vec_size/2 * page_size], 2 * page_size, vec, 1, 0,
770 				0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN | PAGE_IS_HUGE);
771 	if (written < 0)
772 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
773 
774 	ksft_test_result(written == 1 && vec[0].start == (uintptr_t)(&mem[vec_size/2 * page_size])
775 			 && LEN(vec[0]) == 2,
776 			 "%s only two middle pages dirty\n", prefix);
777 
778 	free(vec);
779 	free(vec2);
780 	return 0;
781 }
782 
783 void *gethugepage(int map_size)
784 {
785 	int ret;
786 	char *map;
787 
788 	map = memalign(hpage_size, map_size);
789 	if (!map)
790 		ksft_exit_fail_msg("memalign failed %d %s\n", errno, strerror(errno));
791 
792 	ret = madvise(map, map_size, MADV_HUGEPAGE);
793 	if (ret)
794 		return NULL;
795 
796 	memset(map, 0, map_size);
797 
798 	return map;
799 }
800 
801 int hpage_unit_tests(void)
802 {
803 	char *map;
804 	int ret, ret2;
805 	size_t num_pages = 10;
806 	unsigned long long map_size = hpage_size * num_pages;
807 	unsigned long long vec_size = map_size/page_size;
808 	struct page_region *vec, *vec2;
809 
810 	vec = malloc(sizeof(struct page_region) * vec_size);
811 	vec2 = malloc(sizeof(struct page_region) * vec_size);
812 	if (!vec || !vec2)
813 		ksft_exit_fail_msg("malloc failed\n");
814 
815 	map = gethugepage(map_size);
816 	if (map) {
817 		wp_init(map, map_size);
818 		wp_addr_range(map, map_size);
819 
820 		/* 1. all new huge page must not be written (dirty) */
821 		ret = pagemap_ioctl(map, map_size, vec, vec_size,
822 				    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC, 0,
823 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
824 		if (ret < 0)
825 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
826 
827 		ksft_test_result(ret == 0, "%s all new huge page must not be written (dirty)\n",
828 				 __func__);
829 
830 		/* 2. all the huge page must not be written */
831 		ret = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
832 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
833 		if (ret < 0)
834 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
835 
836 		ksft_test_result(ret == 0, "%s all the huge page must not be written\n", __func__);
837 
838 		/* 3. all the huge page must be written and clear dirty as well */
839 		memset(map, -1, map_size);
840 		ret = pagemap_ioctl(map, map_size, vec, vec_size,
841 				    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
842 				    0, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
843 		if (ret < 0)
844 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
845 
846 		ksft_test_result(ret == 1 && vec[0].start == (uintptr_t)map &&
847 				 LEN(vec[0]) == vec_size && vec[0].categories == PAGE_IS_WRITTEN,
848 				 "%s all the huge page must be written and clear\n", __func__);
849 
850 		/* 4. only middle page written */
851 		wp_free(map, map_size);
852 		free(map);
853 		map = gethugepage(map_size);
854 		wp_init(map, map_size);
855 		wp_addr_range(map, map_size);
856 		map[vec_size/2 * page_size]++;
857 
858 		ret = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
859 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
860 		if (ret < 0)
861 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
862 
863 		ksft_test_result(ret == 1 && LEN(vec[0]) > 0,
864 				 "%s only middle page written\n", __func__);
865 
866 		wp_free(map, map_size);
867 		free(map);
868 	} else {
869 		ksft_test_result_skip("%s all new huge page must be written\n", __func__);
870 		ksft_test_result_skip("%s all the huge page must not be written\n", __func__);
871 		ksft_test_result_skip("%s all the huge page must be written and clear\n", __func__);
872 		ksft_test_result_skip("%s only middle page written\n", __func__);
873 	}
874 
875 	/* 5. clear first half of huge page */
876 	map = gethugepage(map_size);
877 	if (map) {
878 		wp_init(map, map_size);
879 		wp_addr_range(map, map_size);
880 
881 		memset(map, 0, map_size);
882 
883 		wp_addr_range(map, map_size/2);
884 
885 		ret = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
886 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
887 		if (ret < 0)
888 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
889 
890 		ksft_test_result(ret == 1 && LEN(vec[0]) == vec_size/2 &&
891 				 vec[0].start == (uintptr_t)(map + map_size/2),
892 				 "%s clear first half of huge page\n", __func__);
893 		wp_free(map, map_size);
894 		free(map);
895 	} else {
896 		ksft_test_result_skip("%s clear first half of huge page\n", __func__);
897 	}
898 
899 	/* 6. clear first half of huge page with limited buffer */
900 	map = gethugepage(map_size);
901 	if (map) {
902 		wp_init(map, map_size);
903 		wp_addr_range(map, map_size);
904 
905 		memset(map, 0, map_size);
906 
907 		ret = pagemap_ioctl(map, map_size, vec, vec_size,
908 				    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
909 				    vec_size/2, PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
910 		if (ret < 0)
911 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
912 
913 		ret = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
914 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
915 		if (ret < 0)
916 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
917 
918 		ksft_test_result(ret == 1 && LEN(vec[0]) == vec_size/2 &&
919 				 vec[0].start == (uintptr_t)(map + map_size/2),
920 				 "%s clear first half of huge page with limited buffer\n",
921 				 __func__);
922 		wp_free(map, map_size);
923 		free(map);
924 	} else {
925 		ksft_test_result_skip("%s clear first half of huge page with limited buffer\n",
926 				      __func__);
927 	}
928 
929 	/* 7. clear second half of huge page */
930 	map = gethugepage(map_size);
931 	if (map) {
932 		wp_init(map, map_size);
933 		wp_addr_range(map, map_size);
934 
935 		memset(map, -1, map_size);
936 
937 		ret = pagemap_ioctl(map + map_size/2, map_size/2, vec, vec_size,
938 				    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC, vec_size/2,
939 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
940 		if (ret < 0)
941 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
942 
943 		ret = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
944 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
945 		if (ret < 0)
946 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
947 
948 		ksft_test_result(ret == 1 && LEN(vec[0]) == vec_size/2,
949 				 "%s clear second half huge page\n", __func__);
950 		wp_free(map, map_size);
951 		free(map);
952 	} else {
953 		ksft_test_result_skip("%s clear second half huge page\n", __func__);
954 	}
955 
956 	/* 8. get half huge page */
957 	map = gethugepage(map_size);
958 	if (map) {
959 		wp_init(map, map_size);
960 		wp_addr_range(map, map_size);
961 
962 		memset(map, -1, map_size);
963 		usleep(100);
964 
965 		ret = pagemap_ioctl(map, map_size, vec, 1,
966 				    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
967 				    hpage_size/(2*page_size), PAGE_IS_WRITTEN, 0, 0,
968 				    PAGE_IS_WRITTEN);
969 		if (ret < 0)
970 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
971 
972 		ksft_test_result(ret == 1 && LEN(vec[0]) == hpage_size/(2*page_size),
973 				 "%s get half huge page\n", __func__);
974 
975 		ret2 = pagemap_ioctl(map, map_size, vec, vec_size, 0, 0,
976 				    PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN);
977 		if (ret2 < 0)
978 			ksft_exit_fail_msg("error %d %d %s\n", ret2, errno, strerror(errno));
979 
980 		ksft_test_result(ret2 == 1 && LEN(vec[0]) == (map_size - hpage_size/2)/page_size,
981 				 "%s get half huge page\n", __func__);
982 
983 		wp_free(map, map_size);
984 		free(map);
985 	} else {
986 		ksft_test_result_skip("%s get half huge page\n", __func__);
987 		ksft_test_result_skip("%s get half huge page\n", __func__);
988 	}
989 
990 	free(vec);
991 	free(vec2);
992 	return 0;
993 }
994 
995 int unmapped_region_tests(void)
996 {
997 	void *start = (void *)0x10000000;
998 	int written, len = 0x00040000;
999 	long vec_size = len / page_size;
1000 	struct page_region *vec = malloc(sizeof(struct page_region) * vec_size);
1001 
1002 	/* 1. Get written pages */
1003 	written = pagemap_ioctl(start, len, vec, vec_size, 0, 0,
1004 				PAGEMAP_NON_WRITTEN_BITS, 0, 0, PAGEMAP_NON_WRITTEN_BITS);
1005 	if (written < 0)
1006 		ksft_exit_fail_msg("error %d %d %s\n", written, errno, strerror(errno));
1007 
1008 	ksft_test_result(written >= 0, "%s Get status of pages\n", __func__);
1009 
1010 	free(vec);
1011 	return 0;
1012 }
1013 
1014 static void test_simple(void)
1015 {
1016 	int i;
1017 	char *map;
1018 	struct page_region vec;
1019 
1020 	map = aligned_alloc(page_size, page_size);
1021 	if (!map)
1022 		ksft_exit_fail_msg("aligned_alloc failed\n");
1023 
1024 	wp_init(map, page_size);
1025 	wp_addr_range(map, page_size);
1026 
1027 	for (i = 0 ; i < TEST_ITERATIONS; i++) {
1028 		if (pagemap_ioctl(map, page_size, &vec, 1, 0, 0,
1029 				  PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) == 1) {
1030 			ksft_print_msg("written bit was 1, but should be 0 (i=%d)\n", i);
1031 			break;
1032 		}
1033 
1034 		wp_addr_range(map, page_size);
1035 		/* Write something to the page to get the written bit enabled on the page */
1036 		map[0]++;
1037 
1038 		if (pagemap_ioctl(map, page_size, &vec, 1, 0, 0,
1039 				  PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) == 0) {
1040 			ksft_print_msg("written bit was 0, but should be 1 (i=%d)\n", i);
1041 			break;
1042 		}
1043 
1044 		wp_addr_range(map, page_size);
1045 	}
1046 	wp_free(map, page_size);
1047 	free(map);
1048 
1049 	ksft_test_result(i == TEST_ITERATIONS, "Test %s\n", __func__);
1050 }
1051 
1052 int sanity_tests(void)
1053 {
1054 	unsigned long long mem_size, vec_size;
1055 	long ret, fd, i, buf_size;
1056 	struct page_region *vec;
1057 	char *mem, *fmem;
1058 	struct stat sbuf;
1059 	char *tmp_buf;
1060 
1061 	/* 1. wrong operation */
1062 	mem_size = 10 * page_size;
1063 	vec_size = mem_size / page_size;
1064 
1065 	vec = malloc(sizeof(struct page_region) * vec_size);
1066 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1067 	if (mem == MAP_FAILED || vec == MAP_FAILED)
1068 		ksft_exit_fail_msg("error nomem\n");
1069 
1070 	wp_init(mem, mem_size);
1071 	wp_addr_range(mem, mem_size);
1072 
1073 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size,
1074 				       PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC,
1075 				       0, PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) >= 0,
1076 			 "%s WP op can be specified with !PAGE_IS_WRITTEN\n", __func__);
1077 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1078 				       PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL) >= 0,
1079 			 "%s required_mask specified\n", __func__);
1080 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1081 				       0, PAGEMAP_BITS_ALL, 0, PAGEMAP_BITS_ALL) >= 0,
1082 			 "%s anyof_mask specified\n", __func__);
1083 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1084 				       0, 0, PAGEMAP_BITS_ALL, PAGEMAP_BITS_ALL) >= 0,
1085 			 "%s excluded_mask specified\n", __func__);
1086 	ksft_test_result(pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1087 				       PAGEMAP_BITS_ALL, PAGEMAP_BITS_ALL, 0,
1088 				       PAGEMAP_BITS_ALL) >= 0,
1089 			 "%s required_mask and anyof_mask specified\n", __func__);
1090 	wp_free(mem, mem_size);
1091 	munmap(mem, mem_size);
1092 
1093 	/* 2. Get sd and present pages with anyof_mask */
1094 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1095 	if (mem == MAP_FAILED)
1096 		ksft_exit_fail_msg("error nomem\n");
1097 	wp_init(mem, mem_size);
1098 	wp_addr_range(mem, mem_size);
1099 
1100 	memset(mem, 0, mem_size);
1101 
1102 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1103 			    0, PAGEMAP_BITS_ALL, 0, PAGEMAP_BITS_ALL);
1104 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)mem && LEN(vec[0]) == vec_size &&
1105 			 (vec[0].categories & (PAGE_IS_WRITTEN | PAGE_IS_PRESENT)) ==
1106 			 (PAGE_IS_WRITTEN | PAGE_IS_PRESENT),
1107 			 "%s Get sd and present pages with anyof_mask\n", __func__);
1108 
1109 	/* 3. Get sd and present pages with required_mask */
1110 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1111 			    PAGEMAP_BITS_ALL, 0, 0, PAGEMAP_BITS_ALL);
1112 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)mem && LEN(vec[0]) == vec_size &&
1113 			 (vec[0].categories & (PAGE_IS_WRITTEN | PAGE_IS_PRESENT)) ==
1114 			 (PAGE_IS_WRITTEN | PAGE_IS_PRESENT),
1115 			 "%s Get all the pages with required_mask\n", __func__);
1116 
1117 	/* 4. Get sd and present pages with required_mask and anyof_mask */
1118 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1119 			    PAGE_IS_WRITTEN, PAGE_IS_PRESENT, 0, PAGEMAP_BITS_ALL);
1120 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)mem && LEN(vec[0]) == vec_size &&
1121 			 (vec[0].categories & (PAGE_IS_WRITTEN | PAGE_IS_PRESENT)) ==
1122 			 (PAGE_IS_WRITTEN | PAGE_IS_PRESENT),
1123 			 "%s Get sd and present pages with required_mask and anyof_mask\n",
1124 			 __func__);
1125 
1126 	/* 5. Don't get sd pages */
1127 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1128 			    PAGE_IS_WRITTEN, 0, PAGE_IS_WRITTEN, PAGEMAP_BITS_ALL);
1129 	ksft_test_result(ret == 0, "%s Don't get sd pages\n", __func__);
1130 
1131 	/* 6. Don't get present pages */
1132 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size, 0, 0,
1133 			    PAGE_IS_PRESENT, 0, PAGE_IS_PRESENT, PAGEMAP_BITS_ALL);
1134 	ksft_test_result(ret == 0, "%s Don't get present pages\n", __func__);
1135 
1136 	wp_free(mem, mem_size);
1137 	munmap(mem, mem_size);
1138 
1139 	/* 8. Find written present pages with return mask */
1140 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1141 	if (mem == MAP_FAILED)
1142 		ksft_exit_fail_msg("error nomem\n");
1143 	wp_init(mem, mem_size);
1144 	wp_addr_range(mem, mem_size);
1145 
1146 	memset(mem, 0, mem_size);
1147 
1148 	ret = pagemap_ioctl(mem, mem_size, vec, vec_size,
1149 			    PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC, 0,
1150 			    0, PAGEMAP_BITS_ALL, 0, PAGE_IS_WRITTEN);
1151 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)mem && LEN(vec[0]) == vec_size &&
1152 			 vec[0].categories == PAGE_IS_WRITTEN,
1153 			 "%s Find written present pages with return mask\n", __func__);
1154 	wp_free(mem, mem_size);
1155 	munmap(mem, mem_size);
1156 
1157 	/* 9. Memory mapped file */
1158 	fd = open(progname, O_RDONLY);
1159 	if (fd < 0)
1160 		ksft_exit_fail_msg("%s Memory mapped file\n", __func__);
1161 
1162 	ret = stat(progname, &sbuf);
1163 	if (ret < 0)
1164 		ksft_exit_fail_msg("error %ld %d %s\n", ret, errno, strerror(errno));
1165 
1166 	fmem = mmap(NULL, sbuf.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
1167 	if (fmem == MAP_FAILED)
1168 		ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno));
1169 
1170 	tmp_buf = malloc(sbuf.st_size);
1171 	memcpy(tmp_buf, fmem, sbuf.st_size);
1172 
1173 	ret = pagemap_ioctl(fmem, sbuf.st_size, vec, vec_size, 0, 0,
1174 			    0, PAGEMAP_NON_WRITTEN_BITS, 0, PAGEMAP_NON_WRITTEN_BITS);
1175 
1176 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)fmem &&
1177 			 LEN(vec[0]) == ceilf((float)sbuf.st_size/page_size) &&
1178 			 (vec[0].categories & PAGE_IS_FILE),
1179 			 "%s Memory mapped file\n", __func__);
1180 
1181 	munmap(fmem, sbuf.st_size);
1182 	close(fd);
1183 
1184 	/* 10. Create and read/write to a memory mapped file */
1185 	buf_size = page_size * 10;
1186 
1187 	fd = open(__FILE__".tmp2", O_RDWR | O_CREAT, 0666);
1188 	if (fd < 0)
1189 		ksft_exit_fail_msg("Read/write to memory: %s\n",
1190 				   strerror(errno));
1191 
1192 	for (i = 0; i < buf_size; i++)
1193 		if (write(fd, "c", 1) < 0)
1194 			ksft_exit_fail_msg("Create and read/write to a memory mapped file\n");
1195 
1196 	fmem = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1197 	if (fmem == MAP_FAILED)
1198 		ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno));
1199 
1200 	wp_init(fmem, buf_size);
1201 	wp_addr_range(fmem, buf_size);
1202 
1203 	for (i = 0; i < buf_size; i++)
1204 		fmem[i] = 'z';
1205 
1206 	msync(fmem, buf_size, MS_SYNC);
1207 
1208 	ret = pagemap_ioctl(fmem, buf_size, vec, vec_size, 0, 0,
1209 			    PAGE_IS_WRITTEN, PAGE_IS_PRESENT | PAGE_IS_SWAPPED | PAGE_IS_FILE, 0,
1210 			    PAGEMAP_BITS_ALL);
1211 
1212 	ksft_test_result(ret >= 0 && vec[0].start == (uintptr_t)fmem &&
1213 			 LEN(vec[0]) == (buf_size/page_size) &&
1214 			 (vec[0].categories & PAGE_IS_WRITTEN),
1215 			 "%s Read/write to memory\n", __func__);
1216 
1217 	wp_free(fmem, buf_size);
1218 	munmap(fmem, buf_size);
1219 	close(fd);
1220 
1221 	free(vec);
1222 	return 0;
1223 }
1224 
1225 int mprotect_tests(void)
1226 {
1227 	int ret;
1228 	char *mem, *mem2;
1229 	struct page_region vec;
1230 	int pagemap_fd = open("/proc/self/pagemap", O_RDONLY);
1231 
1232 	if (pagemap_fd < 0) {
1233 		fprintf(stderr, "open() failed\n");
1234 		exit(1);
1235 	}
1236 
1237 	/* 1. Map two pages */
1238 	mem = mmap(0, 2 * page_size, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1239 	if (mem == MAP_FAILED)
1240 		ksft_exit_fail_msg("error nomem\n");
1241 	wp_init(mem, 2 * page_size);
1242 	wp_addr_range(mem, 2 * page_size);
1243 
1244 	/* Populate both pages. */
1245 	memset(mem, 1, 2 * page_size);
1246 
1247 	ret = pagemap_ioctl(mem, 2 * page_size, &vec, 1, 0, 0, PAGE_IS_WRITTEN,
1248 			    0, 0, PAGE_IS_WRITTEN);
1249 	if (ret < 0)
1250 		ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1251 
1252 	ksft_test_result(ret == 1 && LEN(vec) == 2, "%s Both pages written\n", __func__);
1253 
1254 	/* 2. Start tracking */
1255 	wp_addr_range(mem, 2 * page_size);
1256 
1257 	ksft_test_result(pagemap_ioctl(mem, 2 * page_size, &vec, 1, 0, 0,
1258 				       PAGE_IS_WRITTEN, 0, 0, PAGE_IS_WRITTEN) == 0,
1259 			 "%s Both pages are not written (dirty)\n", __func__);
1260 
1261 	/* 3. Remap the second page */
1262 	mem2 = mmap(mem + page_size, page_size, PROT_READ|PROT_WRITE,
1263 		    MAP_PRIVATE|MAP_ANON|MAP_FIXED, -1, 0);
1264 	if (mem2 == MAP_FAILED)
1265 		ksft_exit_fail_msg("error nomem\n");
1266 	wp_init(mem2, page_size);
1267 	wp_addr_range(mem2, page_size);
1268 
1269 	/* Protect + unprotect. */
1270 	mprotect(mem, page_size, PROT_NONE);
1271 	mprotect(mem, 2 * page_size, PROT_READ);
1272 	mprotect(mem, 2 * page_size, PROT_READ|PROT_WRITE);
1273 
1274 	/* Modify both pages. */
1275 	memset(mem, 2, 2 * page_size);
1276 
1277 	/* Protect + unprotect. */
1278 	mprotect(mem, page_size, PROT_NONE);
1279 	mprotect(mem, page_size, PROT_READ);
1280 	mprotect(mem, page_size, PROT_READ|PROT_WRITE);
1281 
1282 	ret = pagemap_ioctl(mem, 2 * page_size, &vec, 1, 0, 0, PAGE_IS_WRITTEN,
1283 			    0, 0, PAGE_IS_WRITTEN);
1284 	if (ret < 0)
1285 		ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1286 
1287 	ksft_test_result(ret == 1 && LEN(vec) == 2,
1288 			 "%s Both pages written after remap and mprotect\n", __func__);
1289 
1290 	/* 4. Clear and make the pages written */
1291 	wp_addr_range(mem, 2 * page_size);
1292 
1293 	memset(mem, 'A', 2 * page_size);
1294 
1295 	ret = pagemap_ioctl(mem, 2 * page_size, &vec, 1, 0, 0, PAGE_IS_WRITTEN,
1296 			    0, 0, PAGE_IS_WRITTEN);
1297 	if (ret < 0)
1298 		ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1299 
1300 	ksft_test_result(ret == 1 && LEN(vec) == 2,
1301 			 "%s Clear and make the pages written\n", __func__);
1302 
1303 	wp_free(mem, 2 * page_size);
1304 	munmap(mem, 2 * page_size);
1305 	return 0;
1306 }
1307 
1308 /* transact test */
1309 static const unsigned int nthreads = 6, pages_per_thread = 32, access_per_thread = 8;
1310 static pthread_barrier_t start_barrier, end_barrier;
1311 static unsigned int extra_thread_faults;
1312 static unsigned int iter_count = 1000;
1313 static volatile int finish;
1314 
1315 static ssize_t get_dirty_pages_reset(char *mem, unsigned int count,
1316 				     int reset, int page_size)
1317 {
1318 	struct pm_scan_arg arg = {0};
1319 	struct page_region rgns[256];
1320 	unsigned long long i, j;
1321 	long ret;
1322 	int cnt;
1323 
1324 	arg.size = sizeof(struct pm_scan_arg);
1325 	arg.start = (uintptr_t)mem;
1326 	arg.max_pages = count;
1327 	arg.end = (uintptr_t)(mem + count * page_size);
1328 	arg.vec = (uintptr_t)rgns;
1329 	arg.vec_len = sizeof(rgns) / sizeof(*rgns);
1330 	if (reset)
1331 		arg.flags |= PM_SCAN_WP_MATCHING | PM_SCAN_CHECK_WPASYNC;
1332 	arg.category_mask = PAGE_IS_WRITTEN;
1333 	arg.return_mask = PAGE_IS_WRITTEN;
1334 
1335 	ret = ioctl(pagemap_fd, PAGEMAP_SCAN, &arg);
1336 	if (ret < 0)
1337 		ksft_exit_fail_msg("ioctl failed\n");
1338 
1339 	cnt = 0;
1340 	for (i = 0; i < (unsigned long)ret; ++i) {
1341 		if (rgns[i].categories != PAGE_IS_WRITTEN)
1342 			ksft_exit_fail_msg("wrong flags\n");
1343 
1344 		for (j = 0; j < LEN(rgns[i]); ++j)
1345 			cnt++;
1346 	}
1347 
1348 	return cnt;
1349 }
1350 
1351 void *thread_proc(void *mem)
1352 {
1353 	int *m = mem;
1354 	long curr_faults, faults;
1355 	struct rusage r;
1356 	unsigned int i;
1357 	int ret;
1358 
1359 	if (getrusage(RUSAGE_THREAD, &r))
1360 		ksft_exit_fail_msg("getrusage\n");
1361 
1362 	curr_faults = r.ru_minflt;
1363 
1364 	while (!finish) {
1365 		ret = pthread_barrier_wait(&start_barrier);
1366 		if (ret && ret != PTHREAD_BARRIER_SERIAL_THREAD)
1367 			ksft_exit_fail_msg("pthread_barrier_wait\n");
1368 
1369 		for (i = 0; i < access_per_thread; ++i)
1370 			__atomic_add_fetch(m + i * (0x1000 / sizeof(*m)), 1, __ATOMIC_SEQ_CST);
1371 
1372 		ret = pthread_barrier_wait(&end_barrier);
1373 		if (ret && ret != PTHREAD_BARRIER_SERIAL_THREAD)
1374 			ksft_exit_fail_msg("pthread_barrier_wait\n");
1375 
1376 		if (getrusage(RUSAGE_THREAD, &r))
1377 			ksft_exit_fail_msg("getrusage\n");
1378 
1379 		faults = r.ru_minflt - curr_faults;
1380 		if (faults < access_per_thread)
1381 			ksft_exit_fail_msg("faults < access_per_thread");
1382 
1383 		__atomic_add_fetch(&extra_thread_faults, faults - access_per_thread,
1384 				   __ATOMIC_SEQ_CST);
1385 		curr_faults = r.ru_minflt;
1386 	}
1387 
1388 	return NULL;
1389 }
1390 
1391 static void transact_test(int page_size)
1392 {
1393 	unsigned int i, count, extra_pages;
1394 	unsigned int c;
1395 	pthread_t th;
1396 	char *mem;
1397 	int ret;
1398 
1399 	if (pthread_barrier_init(&start_barrier, NULL, nthreads + 1))
1400 		ksft_exit_fail_msg("pthread_barrier_init\n");
1401 
1402 	if (pthread_barrier_init(&end_barrier, NULL, nthreads + 1))
1403 		ksft_exit_fail_msg("pthread_barrier_init\n");
1404 
1405 	mem = mmap(NULL, 0x1000 * nthreads * pages_per_thread, PROT_READ | PROT_WRITE,
1406 		   MAP_ANONYMOUS | MAP_PRIVATE, -1, 0);
1407 	if (mem == MAP_FAILED)
1408 		ksft_exit_fail_msg("Error mmap %s.\n", strerror(errno));
1409 
1410 	wp_init(mem, 0x1000 * nthreads * pages_per_thread);
1411 	wp_addr_range(mem, 0x1000 * nthreads * pages_per_thread);
1412 
1413 	memset(mem, 0, 0x1000 * nthreads * pages_per_thread);
1414 
1415 	count = get_dirty_pages_reset(mem, nthreads * pages_per_thread, 1, page_size);
1416 	ksft_test_result(count > 0, "%s count %u\n", __func__, count);
1417 	count = get_dirty_pages_reset(mem, nthreads * pages_per_thread, 1, page_size);
1418 	ksft_test_result(count == 0, "%s count %u\n", __func__, count);
1419 
1420 	finish = 0;
1421 	for (i = 0; i < nthreads; ++i)
1422 		pthread_create(&th, NULL, thread_proc, mem + 0x1000 * i * pages_per_thread);
1423 
1424 	extra_pages = 0;
1425 	for (i = 0; i < iter_count; ++i) {
1426 		count = 0;
1427 
1428 		ret = pthread_barrier_wait(&start_barrier);
1429 		if (ret && ret != PTHREAD_BARRIER_SERIAL_THREAD)
1430 			ksft_exit_fail_msg("pthread_barrier_wait\n");
1431 
1432 		count = get_dirty_pages_reset(mem, nthreads * pages_per_thread, 1,
1433 					      page_size);
1434 
1435 		ret = pthread_barrier_wait(&end_barrier);
1436 		if (ret && ret != PTHREAD_BARRIER_SERIAL_THREAD)
1437 			ksft_exit_fail_msg("pthread_barrier_wait\n");
1438 
1439 		if (count > nthreads * access_per_thread)
1440 			ksft_exit_fail_msg("Too big count %u expected %u, iter %u\n",
1441 					   count, nthreads * access_per_thread, i);
1442 
1443 		c = get_dirty_pages_reset(mem, nthreads * pages_per_thread, 1, page_size);
1444 		count += c;
1445 
1446 		if (c > nthreads * access_per_thread) {
1447 			ksft_test_result_fail(" %s count > nthreads\n", __func__);
1448 			return;
1449 		}
1450 
1451 		if (count != nthreads * access_per_thread) {
1452 			/*
1453 			 * The purpose of the test is to make sure that no page updates are lost
1454 			 * when the page updates and read-resetting soft dirty flags are performed
1455 			 * in parallel. However, it is possible that the application will get the
1456 			 * soft dirty flags twice on the two consecutive read-resets. This seems
1457 			 * unavoidable as soft dirty flag is handled in software through page faults
1458 			 * in kernel. While the updating the flags is supposed to be synchronized
1459 			 * between page fault handling and read-reset, it is possible that
1460 			 * read-reset happens after page fault PTE update but before the application
1461 			 * re-executes write instruction. So read-reset gets the flag, clears write
1462 			 * access and application gets page fault again for the same write.
1463 			 */
1464 			if (count < nthreads * access_per_thread) {
1465 				ksft_test_result_fail("Lost update, iter %u, %u vs %u.\n", i, count,
1466 						      nthreads * access_per_thread);
1467 				return;
1468 			}
1469 
1470 			extra_pages += count - nthreads * access_per_thread;
1471 		}
1472 	}
1473 
1474 	pthread_barrier_wait(&start_barrier);
1475 	finish = 1;
1476 	pthread_barrier_wait(&end_barrier);
1477 
1478 	ksft_test_result_pass("%s Extra pages %u (%.1lf%%), extra thread faults %u.\n", __func__,
1479 			      extra_pages,
1480 			      100.0 * extra_pages / (iter_count * nthreads * access_per_thread),
1481 			      extra_thread_faults);
1482 }
1483 
1484 void zeropfn_tests(void)
1485 {
1486 	unsigned long long mem_size;
1487 	struct page_region vec;
1488 	int i, ret;
1489 	char *mmap_mem, *mem;
1490 
1491 	/* Test with normal memory */
1492 	mem_size = 10 * page_size;
1493 	mem = mmap(NULL, mem_size, PROT_READ, MAP_PRIVATE | MAP_ANON, -1, 0);
1494 	if (mem == MAP_FAILED)
1495 		ksft_exit_fail_msg("error nomem\n");
1496 
1497 	/* Touch each page to ensure it's mapped */
1498 	for (i = 0; i < mem_size; i += page_size)
1499 		(void)((volatile char *)mem)[i];
1500 
1501 	ret = pagemap_ioctl(mem, mem_size, &vec, 1, 0,
1502 			    (mem_size / page_size), PAGE_IS_PFNZERO, 0, 0, PAGE_IS_PFNZERO);
1503 	if (ret < 0)
1504 		ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1505 
1506 	ksft_test_result(ret == 1 && LEN(vec) == (mem_size / page_size),
1507 			 "%s all pages must have PFNZERO set\n", __func__);
1508 
1509 	munmap(mem, mem_size);
1510 
1511 	/* Test with huge page if user_zero_page is set to 1 */
1512 	if (!detect_huge_zeropage()) {
1513 		ksft_test_result_skip("%s use_zero_page not supported or set to 1\n", __func__);
1514 		return;
1515 	}
1516 
1517 	mem_size = 2 * hpage_size;
1518 	mmap_mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE,
1519 			MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
1520 	if (mmap_mem == MAP_FAILED)
1521 		ksft_exit_fail_msg("error nomem\n");
1522 
1523 	/* We need a THP-aligned memory area. */
1524 	mem = (char *)(((uintptr_t)mmap_mem + hpage_size) & ~(hpage_size - 1));
1525 
1526 	ret = madvise(mem, hpage_size, MADV_HUGEPAGE);
1527 	if (!ret) {
1528 		FORCE_READ(*mem);
1529 
1530 		ret = pagemap_ioctl(mem, hpage_size, &vec, 1, 0,
1531 				    0, PAGE_IS_PFNZERO, 0, 0, PAGE_IS_PFNZERO);
1532 		if (ret < 0)
1533 			ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1534 
1535 		ksft_test_result(ret == 1 && LEN(vec) == (hpage_size / page_size),
1536 				 "%s all huge pages must have PFNZERO set\n", __func__);
1537 	} else {
1538 		ksft_test_result_skip("%s huge page not supported\n", __func__);
1539 	}
1540 
1541 	munmap(mmap_mem, mem_size);
1542 }
1543 
1544 int main(int __attribute__((unused)) argc, char *argv[])
1545 {
1546 	int shmid, buf_size, fd, i, ret;
1547 	unsigned long long mem_size;
1548 	char *mem, *map, *fmem;
1549 	struct stat sbuf;
1550 
1551 	progname = argv[0];
1552 
1553 	ksft_print_header();
1554 
1555 	if (init_uffd())
1556 		ksft_exit_pass();
1557 
1558 	ksft_set_plan(117);
1559 
1560 	page_size = getpagesize();
1561 	hpage_size = read_pmd_pagesize();
1562 
1563 	pagemap_fd = open(PAGEMAP, O_RDONLY);
1564 	if (pagemap_fd < 0)
1565 		return -EINVAL;
1566 
1567 	/* 1. Sanity testing */
1568 	sanity_tests_sd();
1569 
1570 	/* 2. Normal page testing */
1571 	mem_size = 10 * page_size;
1572 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1573 	if (mem == MAP_FAILED)
1574 		ksft_exit_fail_msg("error nomem\n");
1575 	wp_init(mem, mem_size);
1576 	wp_addr_range(mem, mem_size);
1577 
1578 	base_tests("Page testing:", mem, mem_size, 0);
1579 
1580 	wp_free(mem, mem_size);
1581 	munmap(mem, mem_size);
1582 
1583 	/* 3. Large page testing */
1584 	mem_size = 512 * 10 * page_size;
1585 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANON, -1, 0);
1586 	if (mem == MAP_FAILED)
1587 		ksft_exit_fail_msg("error nomem\n");
1588 	wp_init(mem, mem_size);
1589 	wp_addr_range(mem, mem_size);
1590 
1591 	base_tests("Large Page testing:", mem, mem_size, 0);
1592 
1593 	wp_free(mem, mem_size);
1594 	munmap(mem, mem_size);
1595 
1596 	/* 4. Huge page testing */
1597 	map = gethugepage(hpage_size);
1598 	if (map) {
1599 		wp_init(map, hpage_size);
1600 		wp_addr_range(map, hpage_size);
1601 		base_tests("Huge page testing:", map, hpage_size, 0);
1602 		wp_free(map, hpage_size);
1603 		free(map);
1604 	} else {
1605 		base_tests("Huge page testing:", NULL, 0, 1);
1606 	}
1607 
1608 	/* 5. SHM Hugetlb page testing */
1609 	mem_size = 2*1024*1024;
1610 	mem = gethugetlb_mem(mem_size, &shmid);
1611 	if (mem) {
1612 		wp_init(mem, mem_size);
1613 		wp_addr_range(mem, mem_size);
1614 
1615 		base_tests("Hugetlb shmem testing:", mem, mem_size, 0);
1616 
1617 		wp_free(mem, mem_size);
1618 		shmctl(shmid, IPC_RMID, NULL);
1619 	} else {
1620 		base_tests("Hugetlb shmem testing:", NULL, 0, 1);
1621 	}
1622 
1623 	/* 6. Hugetlb page testing */
1624 	mem = gethugetlb_mem(mem_size, NULL);
1625 	if (mem) {
1626 		wp_init(mem, mem_size);
1627 		wp_addr_range(mem, mem_size);
1628 
1629 		base_tests("Hugetlb mem testing:", mem, mem_size, 0);
1630 
1631 		wp_free(mem, mem_size);
1632 	} else {
1633 		base_tests("Hugetlb mem testing:", NULL, 0, 1);
1634 	}
1635 
1636 	/* 7. File Hugetlb testing */
1637 	mem_size = 2*1024*1024;
1638 	fd = memfd_create("uffd-test", MFD_HUGETLB | MFD_NOEXEC_SEAL);
1639 	if (fd < 0)
1640 		ksft_exit_fail_msg("uffd-test creation failed %d %s\n", errno, strerror(errno));
1641 	mem = mmap(NULL, mem_size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0);
1642 	if (mem != MAP_FAILED) {
1643 		wp_init(mem, mem_size);
1644 		wp_addr_range(mem, mem_size);
1645 
1646 		base_tests("Hugetlb shmem testing:", mem, mem_size, 0);
1647 
1648 		wp_free(mem, mem_size);
1649 		shmctl(shmid, IPC_RMID, NULL);
1650 	} else {
1651 		base_tests("Hugetlb shmem testing:", NULL, 0, 1);
1652 	}
1653 	close(fd);
1654 
1655 	/* 8. File memory testing */
1656 	buf_size = page_size * 10;
1657 
1658 	fd = open(__FILE__".tmp0", O_RDWR | O_CREAT, 0777);
1659 	if (fd < 0)
1660 		ksft_exit_fail_msg("Create and read/write to a memory mapped file: %s\n",
1661 				   strerror(errno));
1662 
1663 	for (i = 0; i < buf_size; i++)
1664 		if (write(fd, "c", 1) < 0)
1665 			ksft_exit_fail_msg("Create and read/write to a memory mapped file\n");
1666 
1667 	ret = stat(__FILE__".tmp0", &sbuf);
1668 	if (ret < 0)
1669 		ksft_exit_fail_msg("error %d %d %s\n", ret, errno, strerror(errno));
1670 
1671 	fmem = mmap(NULL, sbuf.st_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1672 	if (fmem == MAP_FAILED)
1673 		ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno));
1674 
1675 	wp_init(fmem, sbuf.st_size);
1676 	wp_addr_range(fmem, sbuf.st_size);
1677 
1678 	base_tests("File memory testing:", fmem, sbuf.st_size, 0);
1679 
1680 	wp_free(fmem, sbuf.st_size);
1681 	munmap(fmem, sbuf.st_size);
1682 	close(fd);
1683 
1684 	/* 9. File memory testing */
1685 	buf_size = page_size * 10;
1686 
1687 	fd = memfd_create(__FILE__".tmp00", MFD_NOEXEC_SEAL);
1688 	if (fd < 0)
1689 		ksft_exit_fail_msg("Create and read/write to a memory mapped file: %s\n",
1690 				   strerror(errno));
1691 
1692 	if (ftruncate(fd, buf_size))
1693 		ksft_exit_fail_msg("Error ftruncate\n");
1694 
1695 	for (i = 0; i < buf_size; i++)
1696 		if (write(fd, "c", 1) < 0)
1697 			ksft_exit_fail_msg("Create and read/write to a memory mapped file\n");
1698 
1699 	fmem = mmap(NULL, buf_size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
1700 	if (fmem == MAP_FAILED)
1701 		ksft_exit_fail_msg("error nomem %d %s\n", errno, strerror(errno));
1702 
1703 	wp_init(fmem, buf_size);
1704 	wp_addr_range(fmem, buf_size);
1705 
1706 	base_tests("File anonymous memory testing:", fmem, buf_size, 0);
1707 
1708 	wp_free(fmem, buf_size);
1709 	munmap(fmem, buf_size);
1710 	close(fd);
1711 
1712 	/* 10. Huge page tests */
1713 	hpage_unit_tests();
1714 
1715 	/* 11. Iterative test */
1716 	test_simple();
1717 
1718 	/* 12. Mprotect test */
1719 	mprotect_tests();
1720 
1721 	/* 13. Transact test */
1722 	transact_test(page_size);
1723 
1724 	/* 14. Sanity testing */
1725 	sanity_tests();
1726 
1727 	/*15. Unmapped address test */
1728 	unmapped_region_tests();
1729 
1730 	/* 16. Userfaultfd tests */
1731 	userfaultfd_tests();
1732 
1733 	/* 17. ZEROPFN tests */
1734 	zeropfn_tests();
1735 
1736 	close(pagemap_fd);
1737 	ksft_exit_pass();
1738 }
1739