xref: /xnu-8019.80.24/osfmk/vm/vm_tests.c (revision a325d9c4a84054e40bbe985afedcb50ab80993ea)
1 /*
2  * Copyright (c) 2020 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #include <mach_assert.h>
30 
31 #include <mach/mach_types.h>
32 #include <mach/memory_object.h>
33 #include <mach/vm_map.h>
34 
35 #include <kern/ledger.h>
36 
37 #include <vm/memory_object.h>
38 #include <vm/vm_fault.h>
39 #include <vm/vm_map.h>
40 #include <vm/vm_object.h>
41 #include <vm/vm_protos.h>
42 
43 #include <mach/mach_vm.h>
44 extern ledger_template_t        task_ledger_template;
45 
46 extern kern_return_t
47 vm_map_copy_adjust_to_target(
48 	vm_map_copy_t           copy_map,
49 	vm_map_offset_t         offset,
50 	vm_map_size_t           size,
51 	vm_map_t                target_map,
52 	boolean_t               copy,
53 	vm_map_copy_t           *target_copy_map_p,
54 	vm_map_offset_t         *overmap_start_p,
55 	vm_map_offset_t         *overmap_end_p,
56 	vm_map_offset_t         *trimmed_start_p);
57 
58 #define VM_TEST_COLLAPSE_COMPRESSOR             0
59 #define VM_TEST_WIRE_AND_EXTRACT                0
60 #define VM_TEST_PAGE_WIRE_OVERFLOW_PANIC        0
61 #if __arm64__
62 #define VM_TEST_KERNEL_OBJECT_FAULT             0
63 #endif /* __arm64__ */
64 #define VM_TEST_DEVICE_PAGER_TRANSPOSE          (DEVELOPMENT || DEBUG)
65 
66 #if VM_TEST_COLLAPSE_COMPRESSOR
67 extern boolean_t vm_object_collapse_compressor_allowed;
68 #include <IOKit/IOLib.h>
69 static void
vm_test_collapse_compressor(void)70 vm_test_collapse_compressor(void)
71 {
72 	vm_object_size_t        backing_size, top_size;
73 	vm_object_t             backing_object, top_object;
74 	vm_map_offset_t         backing_offset, top_offset;
75 	unsigned char           *backing_address, *top_address;
76 	kern_return_t           kr;
77 
78 	printf("VM_TEST_COLLAPSE_COMPRESSOR:\n");
79 
80 	/* create backing object */
81 	backing_size = 15 * PAGE_SIZE;
82 	backing_object = vm_object_allocate(backing_size);
83 	assert(backing_object != VM_OBJECT_NULL);
84 	printf("VM_TEST_COLLAPSE_COMPRESSOR: created backing object %p\n",
85 	    backing_object);
86 	/* map backing object */
87 	backing_offset = 0;
88 	kr = vm_map_enter(kernel_map, &backing_offset, backing_size, 0,
89 	    VM_FLAGS_ANYWHERE, VM_MAP_KERNEL_FLAGS_NONE,
90 	    backing_object, 0, FALSE,
91 	    VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
92 	assert(kr == KERN_SUCCESS);
93 	backing_address = (unsigned char *) backing_offset;
94 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
95 	    "mapped backing object %p at 0x%llx\n",
96 	    backing_object, (uint64_t) backing_offset);
97 	/* populate with pages to be compressed in backing object */
98 	backing_address[0x1 * PAGE_SIZE] = 0xB1;
99 	backing_address[0x4 * PAGE_SIZE] = 0xB4;
100 	backing_address[0x7 * PAGE_SIZE] = 0xB7;
101 	backing_address[0xa * PAGE_SIZE] = 0xBA;
102 	backing_address[0xd * PAGE_SIZE] = 0xBD;
103 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
104 	    "populated pages to be compressed in "
105 	    "backing_object %p\n", backing_object);
106 	/* compress backing object */
107 	vm_object_pageout(backing_object);
108 	printf("VM_TEST_COLLAPSE_COMPRESSOR: compressing backing_object %p\n",
109 	    backing_object);
110 	/* wait for all the pages to be gone */
111 	while (*(volatile int *)&backing_object->resident_page_count != 0) {
112 		IODelay(10);
113 	}
114 	printf("VM_TEST_COLLAPSE_COMPRESSOR: backing_object %p compressed\n",
115 	    backing_object);
116 	/* populate with pages to be resident in backing object */
117 	backing_address[0x0 * PAGE_SIZE] = 0xB0;
118 	backing_address[0x3 * PAGE_SIZE] = 0xB3;
119 	backing_address[0x6 * PAGE_SIZE] = 0xB6;
120 	backing_address[0x9 * PAGE_SIZE] = 0xB9;
121 	backing_address[0xc * PAGE_SIZE] = 0xBC;
122 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
123 	    "populated pages to be resident in "
124 	    "backing_object %p\n", backing_object);
125 	/* leave the other pages absent */
126 	/* mess with the paging_offset of the backing_object */
127 	assert(backing_object->paging_offset == 0);
128 	backing_object->paging_offset = 3 * PAGE_SIZE;
129 
130 	/* create top object */
131 	top_size = 9 * PAGE_SIZE;
132 	top_object = vm_object_allocate(top_size);
133 	assert(top_object != VM_OBJECT_NULL);
134 	printf("VM_TEST_COLLAPSE_COMPRESSOR: created top object %p\n",
135 	    top_object);
136 	/* map top object */
137 	top_offset = 0;
138 	kr = vm_map_enter(kernel_map, &top_offset, top_size, 0,
139 	    VM_FLAGS_ANYWHERE, VM_MAP_KERNEL_FLAGS_NONE,
140 	    top_object, 0, FALSE,
141 	    VM_PROT_DEFAULT, VM_PROT_DEFAULT, VM_INHERIT_DEFAULT);
142 	assert(kr == KERN_SUCCESS);
143 	top_address = (unsigned char *) top_offset;
144 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
145 	    "mapped top object %p at 0x%llx\n",
146 	    top_object, (uint64_t) top_offset);
147 	/* populate with pages to be compressed in top object */
148 	top_address[0x3 * PAGE_SIZE] = 0xA3;
149 	top_address[0x4 * PAGE_SIZE] = 0xA4;
150 	top_address[0x5 * PAGE_SIZE] = 0xA5;
151 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
152 	    "populated pages to be compressed in "
153 	    "top_object %p\n", top_object);
154 	/* compress top object */
155 	vm_object_pageout(top_object);
156 	printf("VM_TEST_COLLAPSE_COMPRESSOR: compressing top_object %p\n",
157 	    top_object);
158 	/* wait for all the pages to be gone */
159 	while (top_object->resident_page_count != 0) {
160 		IODelay(10);
161 	}
162 	printf("VM_TEST_COLLAPSE_COMPRESSOR: top_object %p compressed\n",
163 	    top_object);
164 	/* populate with pages to be resident in top object */
165 	top_address[0x0 * PAGE_SIZE] = 0xA0;
166 	top_address[0x1 * PAGE_SIZE] = 0xA1;
167 	top_address[0x2 * PAGE_SIZE] = 0xA2;
168 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
169 	    "populated pages to be resident in "
170 	    "top_object %p\n", top_object);
171 	/* leave the other pages absent */
172 
173 	/* link the 2 objects */
174 	vm_object_reference(backing_object);
175 	top_object->shadow = backing_object;
176 	top_object->vo_shadow_offset = 3 * PAGE_SIZE;
177 	printf("VM_TEST_COLLAPSE_COMPRESSOR: linked %p and %p\n",
178 	    top_object, backing_object);
179 
180 	/* unmap backing object */
181 	vm_map_remove(kernel_map,
182 	    backing_offset,
183 	    backing_offset + backing_size,
184 	    VM_MAP_REMOVE_NO_FLAGS);
185 	printf("VM_TEST_COLLAPSE_COMPRESSOR: "
186 	    "unmapped backing_object %p [0x%llx:0x%llx]\n",
187 	    backing_object,
188 	    (uint64_t) backing_offset,
189 	    (uint64_t) (backing_offset + backing_size));
190 
191 	/* collapse */
192 	printf("VM_TEST_COLLAPSE_COMPRESSOR: collapsing %p\n", top_object);
193 	vm_object_lock(top_object);
194 	vm_object_collapse(top_object, 0, FALSE);
195 	vm_object_unlock(top_object);
196 	printf("VM_TEST_COLLAPSE_COMPRESSOR: collapsed %p\n", top_object);
197 
198 	/* did it work? */
199 	if (top_object->shadow != VM_OBJECT_NULL) {
200 		printf("VM_TEST_COLLAPSE_COMPRESSOR: not collapsed\n");
201 		printf("VM_TEST_COLLAPSE_COMPRESSOR: FAIL\n");
202 		if (vm_object_collapse_compressor_allowed) {
203 			panic("VM_TEST_COLLAPSE_COMPRESSOR: FAIL");
204 		}
205 	} else {
206 		/* check the contents of the mapping */
207 		unsigned char expect[9] =
208 		{ 0xA0, 0xA1, 0xA2,             /* resident in top */
209 		  0xA3, 0xA4, 0xA5,             /* compressed in top */
210 		  0xB9,         /* resident in backing + shadow_offset */
211 		  0xBD,         /* compressed in backing + shadow_offset + paging_offset */
212 		  0x00 };                       /* absent in both */
213 		unsigned char actual[9];
214 		unsigned int i, errors;
215 
216 		errors = 0;
217 		for (i = 0; i < sizeof(actual); i++) {
218 			actual[i] = (unsigned char) top_address[i * PAGE_SIZE];
219 			if (actual[i] != expect[i]) {
220 				errors++;
221 			}
222 		}
223 		printf("VM_TEST_COLLAPSE_COMPRESSOR: "
224 		    "actual [%x %x %x %x %x %x %x %x %x] "
225 		    "expect [%x %x %x %x %x %x %x %x %x] "
226 		    "%d errors\n",
227 		    actual[0], actual[1], actual[2], actual[3],
228 		    actual[4], actual[5], actual[6], actual[7],
229 		    actual[8],
230 		    expect[0], expect[1], expect[2], expect[3],
231 		    expect[4], expect[5], expect[6], expect[7],
232 		    expect[8],
233 		    errors);
234 		if (errors) {
235 			panic("VM_TEST_COLLAPSE_COMPRESSOR: FAIL");
236 		} else {
237 			printf("VM_TEST_COLLAPSE_COMPRESSOR: PASS\n");
238 		}
239 	}
240 }
241 #else /* VM_TEST_COLLAPSE_COMPRESSOR */
242 #define vm_test_collapse_compressor()
243 #endif /* VM_TEST_COLLAPSE_COMPRESSOR */
244 
245 #if VM_TEST_WIRE_AND_EXTRACT
246 extern ppnum_t vm_map_get_phys_page(vm_map_t map,
247     vm_offset_t offset);
248 static void
vm_test_wire_and_extract(void)249 vm_test_wire_and_extract(void)
250 {
251 	ledger_t                ledger;
252 	vm_map_t                user_map, wire_map;
253 	mach_vm_address_t       user_addr, wire_addr;
254 	mach_vm_size_t          user_size, wire_size;
255 	mach_vm_offset_t        cur_offset;
256 	vm_prot_t               cur_prot, max_prot;
257 	ppnum_t                 user_ppnum, wire_ppnum;
258 	kern_return_t           kr;
259 
260 	ledger = ledger_instantiate(task_ledger_template,
261 	    LEDGER_CREATE_ACTIVE_ENTRIES);
262 	pmap_t user_pmap = pmap_create_options(ledger, 0, PMAP_CREATE_64BIT);
263 	assert(user_pmap);
264 	user_map = vm_map_create(user_pmap,
265 	    0x100000000ULL,
266 	    0x200000000ULL,
267 	    TRUE);
268 	wire_map = vm_map_create(NULL,
269 	    0x100000000ULL,
270 	    0x200000000ULL,
271 	    TRUE);
272 	user_addr = 0;
273 	user_size = 0x10000;
274 	kr = mach_vm_allocate(user_map,
275 	    &user_addr,
276 	    user_size,
277 	    VM_FLAGS_ANYWHERE);
278 	assert(kr == KERN_SUCCESS);
279 	wire_addr = 0;
280 	wire_size = user_size;
281 	kr = mach_vm_remap(wire_map,
282 	    &wire_addr,
283 	    wire_size,
284 	    0,
285 	    VM_FLAGS_ANYWHERE,
286 	    user_map,
287 	    user_addr,
288 	    FALSE,
289 	    &cur_prot,
290 	    &max_prot,
291 	    VM_INHERIT_NONE);
292 	assert(kr == KERN_SUCCESS);
293 	for (cur_offset = 0;
294 	    cur_offset < wire_size;
295 	    cur_offset += PAGE_SIZE) {
296 		kr = vm_map_wire_and_extract(wire_map,
297 		    wire_addr + cur_offset,
298 		    VM_PROT_DEFAULT | VM_PROT_MEMORY_TAG_MAKE(VM_KERN_MEMORY_OSFMK),
299 		    TRUE,
300 		    &wire_ppnum);
301 		assert(kr == KERN_SUCCESS);
302 		user_ppnum = vm_map_get_phys_page(user_map,
303 		    user_addr + cur_offset);
304 		printf("VM_TEST_WIRE_AND_EXTRACT: kr=0x%x "
305 		    "user[%p:0x%llx:0x%x] wire[%p:0x%llx:0x%x]\n",
306 		    kr,
307 		    user_map, user_addr + cur_offset, user_ppnum,
308 		    wire_map, wire_addr + cur_offset, wire_ppnum);
309 		if (kr != KERN_SUCCESS ||
310 		    wire_ppnum == 0 ||
311 		    wire_ppnum != user_ppnum) {
312 			panic("VM_TEST_WIRE_AND_EXTRACT: FAIL");
313 		}
314 	}
315 	cur_offset -= PAGE_SIZE;
316 	kr = vm_map_wire_and_extract(wire_map,
317 	    wire_addr + cur_offset,
318 	    VM_PROT_DEFAULT,
319 	    TRUE,
320 	    &wire_ppnum);
321 	assert(kr == KERN_SUCCESS);
322 	printf("VM_TEST_WIRE_AND_EXTRACT: re-wire kr=0x%x "
323 	    "user[%p:0x%llx:0x%x] wire[%p:0x%llx:0x%x]\n",
324 	    kr,
325 	    user_map, user_addr + cur_offset, user_ppnum,
326 	    wire_map, wire_addr + cur_offset, wire_ppnum);
327 	if (kr != KERN_SUCCESS ||
328 	    wire_ppnum == 0 ||
329 	    wire_ppnum != user_ppnum) {
330 		panic("VM_TEST_WIRE_AND_EXTRACT: FAIL");
331 	}
332 
333 	printf("VM_TEST_WIRE_AND_EXTRACT: PASS\n");
334 }
335 #else /* VM_TEST_WIRE_AND_EXTRACT */
336 #define vm_test_wire_and_extract()
337 #endif /* VM_TEST_WIRE_AND_EXTRACT */
338 
339 #if VM_TEST_PAGE_WIRE_OVERFLOW_PANIC
340 static void
vm_test_page_wire_overflow_panic(void)341 vm_test_page_wire_overflow_panic(void)
342 {
343 	vm_object_t object;
344 	vm_page_t page;
345 
346 	printf("VM_TEST_PAGE_WIRE_OVERFLOW_PANIC: starting...\n");
347 
348 	object = vm_object_allocate(PAGE_SIZE);
349 	vm_object_lock(object);
350 	page = vm_page_alloc(object, 0x0);
351 	vm_page_lock_queues();
352 	do {
353 		vm_page_wire(page, 1, FALSE);
354 	} while (page->wire_count != 0);
355 	vm_page_unlock_queues();
356 	vm_object_unlock(object);
357 	panic("FBDP(%p,%p): wire_count overflow not detected",
358 	    object, page);
359 }
360 #else /* VM_TEST_PAGE_WIRE_OVERFLOW_PANIC */
361 #define vm_test_page_wire_overflow_panic()
362 #endif /* VM_TEST_PAGE_WIRE_OVERFLOW_PANIC */
363 
364 #if __arm64__ && VM_TEST_KERNEL_OBJECT_FAULT
365 extern int copyinframe(vm_address_t fp, char *frame, boolean_t is64bit);
366 static void
vm_test_kernel_object_fault(void)367 vm_test_kernel_object_fault(void)
368 {
369 	kern_return_t kr;
370 	vm_offset_t stack;
371 	uintptr_t frameb[2];
372 	int ret;
373 
374 	kr = kernel_memory_allocate(kernel_map, &stack,
375 	    kernel_stack_size + (2 * PAGE_SIZE),
376 	    0,
377 	    (KMA_KSTACK | KMA_KOBJECT |
378 	    KMA_GUARD_FIRST | KMA_GUARD_LAST),
379 	    VM_KERN_MEMORY_STACK);
380 	if (kr != KERN_SUCCESS) {
381 		panic("VM_TEST_KERNEL_OBJECT_FAULT: kernel_memory_allocate kr 0x%x", kr);
382 	}
383 	ret = copyinframe((uintptr_t)stack, (char *)frameb, TRUE);
384 	if (ret != 0) {
385 		printf("VM_TEST_KERNEL_OBJECT_FAULT: PASS\n");
386 	} else {
387 		printf("VM_TEST_KERNEL_OBJECT_FAULT: FAIL\n");
388 	}
389 	vm_map_remove(kernel_map,
390 	    stack,
391 	    stack + kernel_stack_size + (2 * PAGE_SIZE),
392 	    VM_MAP_REMOVE_KUNWIRE);
393 	stack = 0;
394 }
395 #else /* __arm64__ && VM_TEST_KERNEL_OBJECT_FAULT */
396 #define vm_test_kernel_object_fault()
397 #endif /* __arm64__ && VM_TEST_KERNEL_OBJECT_FAULT */
398 
399 #if VM_TEST_DEVICE_PAGER_TRANSPOSE
400 static void
vm_test_device_pager_transpose(void)401 vm_test_device_pager_transpose(void)
402 {
403 	memory_object_t device_pager;
404 	vm_object_t     anon_object, device_object;
405 	vm_size_t       size;
406 	vm_map_offset_t device_mapping;
407 	kern_return_t   kr;
408 
409 	size = 3 * PAGE_SIZE;
410 	anon_object = vm_object_allocate(size);
411 	assert(anon_object != VM_OBJECT_NULL);
412 	device_pager = device_pager_setup(NULL, 0, size, 0);
413 	assert(device_pager != NULL);
414 	device_object = memory_object_to_vm_object(device_pager);
415 	assert(device_object != VM_OBJECT_NULL);
416 #if 0
417 	/*
418 	 * Can't actually map this, since another thread might do a
419 	 * vm_map_enter() that gets coalesced into this object, which
420 	 * would cause the test to fail.
421 	 */
422 	vm_map_offset_t anon_mapping = 0;
423 	kr = vm_map_enter(kernel_map, &anon_mapping, size, 0,
424 	    VM_FLAGS_ANYWHERE, VM_MAP_KERNEL_FLAGS_NONE, VM_KERN_MEMORY_NONE,
425 	    anon_object, 0, FALSE, VM_PROT_DEFAULT, VM_PROT_ALL,
426 	    VM_INHERIT_DEFAULT);
427 	assert(kr == KERN_SUCCESS);
428 #endif
429 	device_mapping = 0;
430 	kr = vm_map_enter_mem_object(kernel_map, &device_mapping, size, 0,
431 	    VM_FLAGS_ANYWHERE,
432 	    VM_MAP_KERNEL_FLAGS_NONE,
433 	    VM_KERN_MEMORY_NONE,
434 	    (void *)device_pager, 0, FALSE,
435 	    VM_PROT_DEFAULT, VM_PROT_ALL,
436 	    VM_INHERIT_DEFAULT);
437 	assert(kr == KERN_SUCCESS);
438 	memory_object_deallocate(device_pager);
439 
440 	vm_object_lock(anon_object);
441 	vm_object_activity_begin(anon_object);
442 	anon_object->blocked_access = TRUE;
443 	vm_object_unlock(anon_object);
444 	vm_object_lock(device_object);
445 	vm_object_activity_begin(device_object);
446 	device_object->blocked_access = TRUE;
447 	vm_object_unlock(device_object);
448 
449 	assert(anon_object->ref_count == 1);
450 	assert(!anon_object->named);
451 	assert(device_object->ref_count == 2);
452 	assert(device_object->named);
453 
454 	kr = vm_object_transpose(device_object, anon_object, size);
455 	assert(kr == KERN_SUCCESS);
456 
457 	vm_object_lock(anon_object);
458 	vm_object_activity_end(anon_object);
459 	anon_object->blocked_access = FALSE;
460 	vm_object_unlock(anon_object);
461 	vm_object_lock(device_object);
462 	vm_object_activity_end(device_object);
463 	device_object->blocked_access = FALSE;
464 	vm_object_unlock(device_object);
465 
466 	assert(anon_object->ref_count == 2);
467 	assert(anon_object->named);
468 #if 0
469 	kr = vm_deallocate(kernel_map, anon_mapping, size);
470 	assert(kr == KERN_SUCCESS);
471 #endif
472 	assert(device_object->ref_count == 1);
473 	assert(!device_object->named);
474 	kr = vm_deallocate(kernel_map, device_mapping, size);
475 	assert(kr == KERN_SUCCESS);
476 
477 	printf("VM_TEST_DEVICE_PAGER_TRANSPOSE: PASS\n");
478 }
479 #else /* VM_TEST_DEVICE_PAGER_TRANSPOSE */
480 #define vm_test_device_pager_transpose()
481 #endif /* VM_TEST_DEVICE_PAGER_TRANSPOSE */
482 
483 #if PMAP_CREATE_FORCE_4K_PAGES && MACH_ASSERT
484 extern kern_return_t vm_allocate_external(vm_map_t        map,
485     vm_offset_t     *addr,
486     vm_size_t       size,
487     int             flags);
488 extern kern_return_t vm_remap_external(vm_map_t                target_map,
489     vm_offset_t             *address,
490     vm_size_t               size,
491     vm_offset_t             mask,
492     int                     flags,
493     vm_map_t                src_map,
494     vm_offset_t             memory_address,
495     boolean_t               copy,
496     vm_prot_t               *cur_protection,
497     vm_prot_t               *max_protection,
498     vm_inherit_t            inheritance);
499 extern int debug4k_panic_on_misaligned_sharing;
500 
501 void vm_test_4k(void);
502 void
vm_test_4k(void)503 vm_test_4k(void)
504 {
505 	pmap_t test_pmap;
506 	vm_map_t test_map;
507 	kern_return_t kr;
508 	vm_address_t expected_addr;
509 	vm_address_t alloc1_addr, alloc2_addr, alloc3_addr, alloc4_addr;
510 	vm_address_t alloc5_addr, dealloc_addr, remap_src_addr, remap_dst_addr;
511 	vm_size_t alloc1_size, alloc2_size, alloc3_size, alloc4_size;
512 	vm_size_t alloc5_size, remap_src_size;
513 	vm_address_t fault_addr;
514 	vm_prot_t cur_prot, max_prot;
515 	int saved_debug4k_panic_on_misaligned_sharing;
516 
517 	printf("\n\n\nVM_TEST_4K:%d creating 4K map...\n", __LINE__);
518 	test_pmap = pmap_create_options(NULL, 0, PMAP_CREATE_64BIT | PMAP_CREATE_FORCE_4K_PAGES);
519 	assert(test_pmap != NULL);
520 	test_map = vm_map_create(test_pmap,
521 	    MACH_VM_MIN_ADDRESS,
522 	    MACH_VM_MAX_ADDRESS,
523 	    TRUE);
524 	assert(test_map != VM_MAP_NULL);
525 	vm_map_set_page_shift(test_map, FOURK_PAGE_SHIFT);
526 	printf("VM_TEST_4K:%d map %p pmap %p page_size 0x%x\n", __LINE__, test_map, test_pmap, VM_MAP_PAGE_SIZE(test_map));
527 
528 	alloc1_addr = 0;
529 	alloc1_size = 1 * FOURK_PAGE_SIZE;
530 	expected_addr = 0x1000;
531 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc1_addr, alloc1_size);
532 	kr = vm_allocate_external(test_map,
533 	    &alloc1_addr,
534 	    alloc1_size,
535 	    VM_FLAGS_ANYWHERE);
536 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
537 	assertf(alloc1_addr == expected_addr, "alloc1_addr = 0x%lx expected 0x%lx", alloc1_addr, expected_addr);
538 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc1_addr);
539 	expected_addr += alloc1_size;
540 
541 	printf("VM_TEST_4K:%d vm_deallocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc1_addr, alloc1_size);
542 	kr = vm_deallocate(test_map, alloc1_addr, alloc1_size);
543 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
544 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc1_addr);
545 
546 	alloc1_addr = 0;
547 	alloc1_size = 1 * FOURK_PAGE_SIZE;
548 	expected_addr = 0x1000;
549 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc1_addr, alloc1_size);
550 	kr = vm_allocate_external(test_map,
551 	    &alloc1_addr,
552 	    alloc1_size,
553 	    VM_FLAGS_ANYWHERE);
554 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
555 	assertf(alloc1_addr == expected_addr, "alloc1_addr = 0x%lx expected 0x%lx", alloc1_addr, expected_addr);
556 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc1_addr);
557 	expected_addr += alloc1_size;
558 
559 	alloc2_addr = 0;
560 	alloc2_size = 3 * FOURK_PAGE_SIZE;
561 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc2_addr, alloc2_size);
562 	kr = vm_allocate_external(test_map,
563 	    &alloc2_addr,
564 	    alloc2_size,
565 	    VM_FLAGS_ANYWHERE);
566 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
567 	assertf(alloc2_addr == expected_addr, "alloc2_addr = 0x%lx expected 0x%lx", alloc2_addr, expected_addr);
568 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc2_addr);
569 	expected_addr += alloc2_size;
570 
571 	alloc3_addr = 0;
572 	alloc3_size = 18 * FOURK_PAGE_SIZE;
573 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc3_addr, alloc3_size);
574 	kr = vm_allocate_external(test_map,
575 	    &alloc3_addr,
576 	    alloc3_size,
577 	    VM_FLAGS_ANYWHERE);
578 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
579 	assertf(alloc3_addr == expected_addr, "alloc3_addr = 0x%lx expected 0x%lx\n", alloc3_addr, expected_addr);
580 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc3_addr);
581 	expected_addr += alloc3_size;
582 
583 	alloc4_addr = 0;
584 	alloc4_size = 1 * FOURK_PAGE_SIZE;
585 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc4_addr, alloc4_size);
586 	kr = vm_allocate_external(test_map,
587 	    &alloc4_addr,
588 	    alloc4_size,
589 	    VM_FLAGS_ANYWHERE);
590 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
591 	assertf(alloc4_addr == expected_addr, "alloc4_addr = 0x%lx expected 0x%lx", alloc4_addr, expected_addr);
592 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc3_addr);
593 	expected_addr += alloc4_size;
594 
595 	printf("VM_TEST_4K:%d vm_protect(%p, 0x%lx, 0x%lx, READ)...\n", __LINE__, test_map, alloc2_addr, (1UL * FOURK_PAGE_SIZE));
596 	kr = vm_protect(test_map,
597 	    alloc2_addr,
598 	    (1UL * FOURK_PAGE_SIZE),
599 	    FALSE,
600 	    VM_PROT_READ);
601 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
602 
603 	for (fault_addr = alloc1_addr;
604 	    fault_addr < alloc4_addr + alloc4_size + (2 * FOURK_PAGE_SIZE);
605 	    fault_addr += FOURK_PAGE_SIZE) {
606 		printf("VM_TEST_4K:%d write fault at 0x%lx...\n", __LINE__, fault_addr);
607 		kr = vm_fault(test_map,
608 		    fault_addr,
609 		    VM_PROT_WRITE,
610 		    FALSE,
611 		    VM_KERN_MEMORY_NONE,
612 		    THREAD_UNINT,
613 		    NULL,
614 		    0);
615 		printf("VM_TEST_4K:%d -> 0x%x\n", __LINE__, kr);
616 		if (fault_addr == alloc2_addr) {
617 			assertf(kr == KERN_PROTECTION_FAILURE, "fault_addr = 0x%lx kr = 0x%x expected 0x%x", fault_addr, kr, KERN_PROTECTION_FAILURE);
618 			printf("VM_TEST_4K:%d read fault at 0x%lx...\n", __LINE__, fault_addr);
619 			kr = vm_fault(test_map,
620 			    fault_addr,
621 			    VM_PROT_READ,
622 			    FALSE,
623 			    VM_KERN_MEMORY_NONE,
624 			    THREAD_UNINT,
625 			    NULL,
626 			    0);
627 			assertf(kr == KERN_SUCCESS, "fault_addr = 0x%lx kr = 0x%x expected 0x%x", fault_addr, kr, KERN_SUCCESS);
628 			printf("VM_TEST_4K:%d -> 0x%x\n", __LINE__, kr);
629 		} else if (fault_addr >= alloc4_addr + alloc4_size) {
630 			assertf(kr == KERN_INVALID_ADDRESS, "fault_addr = 0x%lx kr = 0x%x expected 0x%x", fault_addr, kr, KERN_INVALID_ADDRESS);
631 		} else {
632 			assertf(kr == KERN_SUCCESS, "fault_addr = 0x%lx kr = 0x%x expected 0x%x", fault_addr, kr, KERN_SUCCESS);
633 		}
634 	}
635 
636 	alloc5_addr = 0;
637 	alloc5_size = 7 * FOURK_PAGE_SIZE;
638 	printf("VM_TEST_4K:%d vm_allocate(%p, 0x%lx, 0x%lx)...\n", __LINE__, test_map, alloc5_addr, alloc5_size);
639 	kr = vm_allocate_external(test_map,
640 	    &alloc5_addr,
641 	    alloc5_size,
642 	    VM_FLAGS_ANYWHERE);
643 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
644 	assertf(alloc5_addr == expected_addr, "alloc5_addr = 0x%lx expected 0x%lx", alloc5_addr, expected_addr);
645 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, alloc5_addr);
646 	expected_addr += alloc5_size;
647 
648 	dealloc_addr = vm_map_round_page(alloc5_addr, PAGE_SHIFT);
649 	dealloc_addr += FOURK_PAGE_SIZE;
650 	printf("VM_TEST_4K:%d vm_deallocate(%p, 0x%lx, 0x%x)...\n", __LINE__, test_map, dealloc_addr, FOURK_PAGE_SIZE);
651 	kr = vm_deallocate(test_map, dealloc_addr, FOURK_PAGE_SIZE);
652 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
653 	printf("VM_TEST_4K:%d -> 0x%x\n", __LINE__, kr);
654 
655 	remap_src_addr = vm_map_round_page(alloc3_addr, PAGE_SHIFT);
656 	remap_src_addr += FOURK_PAGE_SIZE;
657 	remap_src_size = 2 * FOURK_PAGE_SIZE;
658 	remap_dst_addr = 0;
659 	printf("VM_TEST_4K:%d vm_remap(%p, 0x%lx, 0x%lx, 0x%lx, copy=0)...\n", __LINE__, test_map, remap_dst_addr, remap_src_size, remap_src_addr);
660 	kr = vm_remap_external(test_map,
661 	    &remap_dst_addr,
662 	    remap_src_size,
663 	    0,                    /* mask */
664 	    VM_FLAGS_ANYWHERE,
665 	    test_map,
666 	    remap_src_addr,
667 	    FALSE,                    /* copy */
668 	    &cur_prot,
669 	    &max_prot,
670 	    VM_INHERIT_DEFAULT);
671 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
672 	assertf(remap_dst_addr == expected_addr, "remap_dst_addr = 0x%lx expected 0x%lx", remap_dst_addr, expected_addr);
673 	printf("VM_TEST_4K:%d -> 0x%lx\n", __LINE__, remap_dst_addr);
674 	expected_addr += remap_src_size;
675 
676 	for (fault_addr = remap_dst_addr;
677 	    fault_addr < remap_dst_addr + remap_src_size;
678 	    fault_addr += 4096) {
679 		printf("VM_TEST_4K:%d write fault at 0x%lx...\n", __LINE__, fault_addr);
680 		kr = vm_fault(test_map,
681 		    fault_addr,
682 		    VM_PROT_WRITE,
683 		    FALSE,
684 		    VM_KERN_MEMORY_NONE,
685 		    THREAD_UNINT,
686 		    NULL,
687 		    0);
688 		assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
689 		printf("VM_TEST_4K:%d -> 0x%x\n", __LINE__, kr);
690 	}
691 
692 	printf("VM_TEST_4K:\n");
693 	remap_dst_addr = 0;
694 	remap_src_addr = alloc3_addr + 0xc000;
695 	remap_src_size = 0x5000;
696 	printf("VM_TEST_4K: vm_remap(%p, 0x%lx, 0x%lx, %p, copy=0) from 4K to 16K\n", test_map, remap_src_addr, remap_src_size, kernel_map);
697 	kr = vm_remap_external(kernel_map,
698 	    &remap_dst_addr,
699 	    remap_src_size,
700 	    0,                    /* mask */
701 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
702 	    test_map,
703 	    remap_src_addr,
704 	    FALSE,                    /* copy */
705 	    &cur_prot,
706 	    &max_prot,
707 	    VM_INHERIT_DEFAULT);
708 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
709 	printf("VM_TEST_4K: -> remapped (shared) in map %p at addr 0x%lx\n", kernel_map, remap_dst_addr);
710 
711 	printf("VM_TEST_4K:\n");
712 	remap_dst_addr = 0;
713 	remap_src_addr = alloc3_addr + 0xc000;
714 	remap_src_size = 0x5000;
715 	printf("VM_TEST_4K: vm_remap(%p, 0x%lx, 0x%lx, %p, copy=1) from 4K to 16K\n", test_map, remap_src_addr, remap_src_size, kernel_map);
716 	kr = vm_remap_external(kernel_map,
717 	    &remap_dst_addr,
718 	    remap_src_size,
719 	    0,                    /* mask */
720 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
721 	    test_map,
722 	    remap_src_addr,
723 	    TRUE,                    /* copy */
724 	    &cur_prot,
725 	    &max_prot,
726 	    VM_INHERIT_DEFAULT);
727 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
728 	printf("VM_TEST_4K: -> remapped (COW) in map %p at addr 0x%lx\n", kernel_map, remap_dst_addr);
729 
730 	printf("VM_TEST_4K:\n");
731 	saved_debug4k_panic_on_misaligned_sharing = debug4k_panic_on_misaligned_sharing;
732 	debug4k_panic_on_misaligned_sharing = 0;
733 	remap_dst_addr = 0;
734 	remap_src_addr = alloc1_addr;
735 	remap_src_size = alloc1_size + alloc2_size;
736 	printf("VM_TEST_4K: vm_remap(%p, 0x%lx, 0x%lx, %p, copy=0) from 4K to 16K\n", test_map, remap_src_addr, remap_src_size, kernel_map);
737 	kr = vm_remap_external(kernel_map,
738 	    &remap_dst_addr,
739 	    remap_src_size,
740 	    0,                    /* mask */
741 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
742 	    test_map,
743 	    remap_src_addr,
744 	    FALSE,                    /* copy */
745 	    &cur_prot,
746 	    &max_prot,
747 	    VM_INHERIT_DEFAULT);
748 	assertf(kr != KERN_SUCCESS, "kr = 0x%x", kr);
749 	printf("VM_TEST_4K: -> remap (SHARED) in map %p at addr 0x%lx kr=0x%x\n", kernel_map, remap_dst_addr, kr);
750 	debug4k_panic_on_misaligned_sharing = saved_debug4k_panic_on_misaligned_sharing;
751 
752 	printf("VM_TEST_4K:\n");
753 	remap_dst_addr = 0;
754 	remap_src_addr = alloc1_addr;
755 	remap_src_size = alloc1_size + alloc2_size;
756 	printf("VM_TEST_4K: vm_remap(%p, 0x%lx, 0x%lx, %p, copy=1) from 4K to 16K\n", test_map, remap_src_addr, remap_src_size, kernel_map);
757 	kr = vm_remap_external(kernel_map,
758 	    &remap_dst_addr,
759 	    remap_src_size,
760 	    0,                    /* mask */
761 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
762 	    test_map,
763 	    remap_src_addr,
764 	    TRUE,                    /* copy */
765 	    &cur_prot,
766 	    &max_prot,
767 	    VM_INHERIT_DEFAULT);
768 #if 000
769 	assertf(kr != KERN_SUCCESS, "kr = 0x%x", kr);
770 	printf("VM_TEST_4K: -> remap (COPY) in map %p at addr 0x%lx kr=0x%x\n", kernel_map, remap_dst_addr, kr);
771 #else /* 000 */
772 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
773 	printf("VM_TEST_4K: -> remap (COPY) in map %p at addr 0x%lx kr=0x%x\n", kernel_map, remap_dst_addr, kr);
774 #endif /* 000 */
775 
776 
777 #if 00
778 	printf("VM_TEST_4K:%d vm_map_remove(%p, 0x%llx, 0x%llx)...\n", __LINE__, test_map, test_map->min_offset, test_map->max_offset);
779 	kr = vm_map_remove(test_map,
780 	    test_map->min_offset,
781 	    test_map->max_offset,
782 	    VM_MAP_REMOVE_GAPS_OK);
783 	assertf(kr == KERN_SUCCESS, "kr = 0x%x", kr);
784 #endif
785 
786 	printf("VM_TEST_4K: PASS\n\n\n\n");
787 }
788 #endif /* PMAP_CREATE_FORCE_4K_PAGES && MACH_ASSERT */
789 
790 #if MACH_ASSERT
791 static void
vm_test_map_copy_adjust_to_target_one(vm_map_copy_t copy_map,vm_map_t target_map)792 vm_test_map_copy_adjust_to_target_one(
793 	vm_map_copy_t copy_map,
794 	vm_map_t target_map)
795 {
796 	kern_return_t kr;
797 	vm_map_copy_t target_copy;
798 	vm_map_offset_t overmap_start, overmap_end, trimmed_start;
799 
800 	target_copy = VM_MAP_COPY_NULL;
801 	/* size is 2 (4k) pages but range covers 3 pages */
802 	kr = vm_map_copy_adjust_to_target(copy_map,
803 	    0x0 + 0xfff,
804 	    0x1002,
805 	    target_map,
806 	    FALSE,
807 	    &target_copy,
808 	    &overmap_start,
809 	    &overmap_end,
810 	    &trimmed_start);
811 	assert(kr == KERN_SUCCESS);
812 	assert(overmap_start == 0);
813 	assert(overmap_end == 0);
814 	assert(trimmed_start == 0);
815 	assertf(target_copy->size == 0x3000,
816 	    "target_copy %p size 0x%llx\n",
817 	    target_copy, (uint64_t)target_copy->size);
818 	vm_map_copy_discard(target_copy);
819 
820 	/* 1. adjust_to_target() for bad offset -> error */
821 	/* 2. adjust_to_target() for bad size -> error */
822 	/* 3. adjust_to_target() for the whole thing -> unchanged */
823 	/* 4. adjust_to_target() to trim start by less than 1 page */
824 	/* 5. adjust_to_target() to trim end by less than 1 page */
825 	/* 6. adjust_to_target() to trim start and end by less than 1 page */
826 	/* 7. adjust_to_target() to trim start by more than 1 page */
827 	/* 8. adjust_to_target() to trim end by more than 1 page */
828 	/* 9. adjust_to_target() to trim start and end by more than 1 page */
829 	/* 10. adjust_to_target() to trim start by more than 1 entry */
830 	/* 11. adjust_to_target() to trim start by more than 1 entry */
831 	/* 12. adjust_to_target() to trim start and end by more than 1 entry */
832 	/* 13. adjust_to_target() to trim start and end down to 1 entry */
833 }
834 
835 static void
vm_test_map_copy_adjust_to_target(void)836 vm_test_map_copy_adjust_to_target(void)
837 {
838 	kern_return_t kr;
839 	vm_map_t map4k, map16k;
840 	vm_object_t obj1, obj2, obj3, obj4;
841 	vm_map_offset_t addr4k, addr16k;
842 	vm_map_size_t size4k, size16k;
843 	vm_map_copy_t copy4k, copy16k;
844 	vm_prot_t curprot, maxprot;
845 
846 	/* create a 4k map */
847 	map4k = vm_map_create(PMAP_NULL, 0, (uint32_t)-1, TRUE);
848 	vm_map_set_page_shift(map4k, 12);
849 
850 	/* create a 16k map */
851 	map16k = vm_map_create(PMAP_NULL, 0, (uint32_t)-1, TRUE);
852 	vm_map_set_page_shift(map16k, 14);
853 
854 	/* create 4 VM objects */
855 	obj1 = vm_object_allocate(0x100000);
856 	obj2 = vm_object_allocate(0x100000);
857 	obj3 = vm_object_allocate(0x100000);
858 	obj4 = vm_object_allocate(0x100000);
859 
860 	/* map objects in 4k map */
861 	vm_object_reference(obj1);
862 	addr4k = 0x1000;
863 	size4k = 0x3000;
864 	kr = vm_map_enter(map4k, &addr4k, size4k, 0, VM_FLAGS_ANYWHERE,
865 	    VM_MAP_KERNEL_FLAGS_NONE, 0, obj1, 0,
866 	    FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT,
867 	    VM_INHERIT_DEFAULT);
868 	assert(kr == KERN_SUCCESS);
869 	assert(addr4k == 0x1000);
870 
871 	/* map objects in 16k map */
872 	vm_object_reference(obj1);
873 	addr16k = 0x4000;
874 	size16k = 0x8000;
875 	kr = vm_map_enter(map16k, &addr16k, size16k, 0, VM_FLAGS_ANYWHERE,
876 	    VM_MAP_KERNEL_FLAGS_NONE, 0, obj1, 0,
877 	    FALSE, VM_PROT_DEFAULT, VM_PROT_DEFAULT,
878 	    VM_INHERIT_DEFAULT);
879 	assert(kr == KERN_SUCCESS);
880 	assert(addr16k == 0x4000);
881 
882 	/* test for <rdar://60959809> */
883 	ipc_port_t mem_entry;
884 	memory_object_size_t mem_entry_size;
885 	mach_vm_size_t map_size;
886 	mem_entry_size = 0x1002;
887 	mem_entry = IPC_PORT_NULL;
888 	kr = mach_make_memory_entry_64(map16k, &mem_entry_size, addr16k + 0x2fff,
889 	    MAP_MEM_VM_SHARE | MAP_MEM_USE_DATA_ADDR | VM_PROT_READ,
890 	    &mem_entry, IPC_PORT_NULL);
891 	assertf(kr == KERN_SUCCESS, "kr 0x%x\n", kr);
892 	assertf(mem_entry_size == 0x5001, "mem_entry_size 0x%llx\n", (uint64_t) mem_entry_size);
893 	map_size = 0;
894 	kr = mach_memory_entry_map_size(mem_entry, map4k, 0, 0x1002, &map_size);
895 	assertf(kr == KERN_SUCCESS, "kr 0x%x\n", kr);
896 	assertf(map_size == 0x3000, "mem_entry %p map_size 0x%llx\n", mem_entry, (uint64_t)map_size);
897 	mach_memory_entry_port_release(mem_entry);
898 
899 	/* create 4k copy map */
900 	curprot = VM_PROT_NONE;
901 	maxprot = VM_PROT_NONE;
902 	kr = vm_map_copy_extract(map4k, addr4k, 0x3000,
903 	    FALSE, &copy4k, &curprot, &maxprot,
904 	    VM_INHERIT_DEFAULT, VM_MAP_KERNEL_FLAGS_NONE);
905 	assert(kr == KERN_SUCCESS);
906 	assert(copy4k->size == 0x3000);
907 
908 	/* create 16k copy map */
909 	curprot = VM_PROT_NONE;
910 	maxprot = VM_PROT_NONE;
911 	kr = vm_map_copy_extract(map16k, addr16k, 0x4000,
912 	    FALSE, &copy16k, &curprot, &maxprot,
913 	    VM_INHERIT_DEFAULT, VM_MAP_KERNEL_FLAGS_NONE);
914 	assert(kr == KERN_SUCCESS);
915 	assert(copy16k->size == 0x4000);
916 
917 	/* test each combination */
918 //	vm_test_map_copy_adjust_to_target_one(copy4k, map4k);
919 //	vm_test_map_copy_adjust_to_target_one(copy16k, map16k);
920 //	vm_test_map_copy_adjust_to_target_one(copy4k, map16k);
921 	vm_test_map_copy_adjust_to_target_one(copy16k, map4k);
922 
923 	/* assert 1 ref on 4k map */
924 	assert(os_ref_get_count(&map4k->map_refcnt) == 1);
925 	/* release 4k map */
926 	vm_map_deallocate(map4k);
927 	/* assert 1 ref on 16k map */
928 	assert(os_ref_get_count(&map16k->map_refcnt) == 1);
929 	/* release 16k map */
930 	vm_map_deallocate(map16k);
931 	/* deallocate copy maps */
932 	vm_map_copy_discard(copy4k);
933 	vm_map_copy_discard(copy16k);
934 	/* assert 1 ref on all VM objects */
935 	assert(obj1->ref_count == 1);
936 	assert(obj2->ref_count == 1);
937 	assert(obj3->ref_count == 1);
938 	assert(obj4->ref_count == 1);
939 	/* release all VM objects */
940 	vm_object_deallocate(obj1);
941 	vm_object_deallocate(obj2);
942 	vm_object_deallocate(obj3);
943 	vm_object_deallocate(obj4);
944 }
945 #endif /* MACH_ASSERT */
946 
947 void vm_test_watch3_overmap(void);
948 void
vm_test_watch3_overmap(void)949 vm_test_watch3_overmap(void)
950 {
951 #if __arm && !__arm64__
952 	kern_return_t kr;
953 	ledger_t ledger;
954 	pmap_t user_pmap;
955 	vm_map_t user_map;
956 	vm_object_t object;
957 	vm_map_address_t address;
958 	int chunk;
959 
960 	if (PAGE_SIZE != FOURK_PAGE_SIZE) {
961 		printf("VM_TESTS: %s:%d SKIP (PAGE_SIZE 0x%x)\n",
962 		    __FUNCTION__, __LINE__, PAGE_SIZE);
963 		return;
964 	}
965 	printf("VM_TESTS: %s:%d\n", __FUNCTION__, __LINE__);
966 	ledger = ledger_instantiate(task_ledger_template,
967 	    LEDGER_CREATE_ACTIVE_ENTRIES);
968 	assert(ledger);
969 	user_pmap = pmap_create_options(ledger, 0, 0);
970 	assert(user_pmap);
971 	ledger_dereference(ledger);
972 	user_map = vm_map_create(user_pmap,
973 	    0x1000000ULL,
974 	    0x2000000ULL,
975 	    TRUE);
976 	assert(user_map);
977 	vm_map_set_page_shift(user_map, SIXTEENK_PAGE_SHIFT);
978 	object = vm_object_allocate(FOURK_PAGE_SIZE);
979 	assert(object);
980 	address = 0;
981 	kr = vm_map_enter(user_map,
982 	    &address,
983 	    SIXTEENK_PAGE_SIZE,
984 	    0,               /* mask */
985 	    VM_FLAGS_ANYWHERE,
986 	    VM_MAP_KERNEL_FLAGS_NONE,
987 	    0,               /* alias */
988 	    object,
989 	    0,               /* offset */
990 	    FALSE,
991 	    VM_PROT_DEFAULT,
992 	    VM_PROT_DEFAULT,
993 	    VM_INHERIT_DEFAULT);
994 	assertf(kr == KERN_SUCCESS, "kr 0x%x", kr);
995 	kr = vm_fault(user_map,
996 	    address,
997 	    VM_PROT_READ,
998 	    FALSE,
999 	    0,
1000 	    TRUE,
1001 	    NULL,
1002 	    0);
1003 	assert(kr == KERN_SUCCESS);
1004 	for (chunk = 1; chunk < 4; chunk++) {
1005 		kr = vm_fault(user_map,
1006 		    address + (chunk * FOURK_PAGE_SIZE),
1007 		    VM_PROT_READ,
1008 		    FALSE,
1009 		    0,
1010 		    TRUE,
1011 		    NULL,
1012 		    0);
1013 		assertf(kr == KERN_MEMORY_ERROR, "kr 0x%x", kr);
1014 	}
1015 	vm_map_deallocate(user_map);
1016 	printf("VM_TESTS: %s:%d PASS\n", __FUNCTION__, __LINE__);
1017 #endif /* __arm__ && !__arm64__ */
1018 }
1019 
1020 
1021 boolean_t vm_tests_in_progress = FALSE;
1022 
1023 kern_return_t
vm_tests(void)1024 vm_tests(void)
1025 {
1026 	vm_tests_in_progress = TRUE;
1027 
1028 	vm_test_collapse_compressor();
1029 	vm_test_wire_and_extract();
1030 	vm_test_page_wire_overflow_panic();
1031 	vm_test_kernel_object_fault();
1032 	vm_test_device_pager_transpose();
1033 #if MACH_ASSERT
1034 	vm_test_map_copy_adjust_to_target();
1035 #endif /* MACH_ASSERT */
1036 #if PMAP_CREATE_FORCE_4K_PAGES && MACH_ASSERT
1037 	vm_test_4k();
1038 #endif /* PMAP_CREATE_FORCE_4K_PAGES && MACH_ASSERT */
1039 	vm_test_watch3_overmap();
1040 
1041 	vm_tests_in_progress = FALSE;
1042 
1043 	return KERN_SUCCESS;
1044 }
1045