1 /*
2 * Copyright (c) 2024 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 /*
30 * vm/configurator_vm_wire.c
31 *
32 * Test vm_wire with many different VM states.
33 */
34
35 #include "configurator/vm_configurator_tests.h"
36
37 T_GLOBAL_META(
38 T_META_NAMESPACE("xnu.vm.configurator"),
39 T_META_RADAR_COMPONENT_NAME("xnu"),
40 T_META_RADAR_COMPONENT_VERSION("VM"),
41 T_META_RUN_CONCURRENTLY(true),
42 T_META_ALL_VALID_ARCHS(true),
43 T_META_ASROOT(true) /* root required for vm_wire on macOS */
44 );
45
46 /*
47 * Update checker state to mirror a successful call to
48 * vm_wire(PROT_NONE) a.k.a. unwire
49 */
50 static void
checker_perform_vm_unwire(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)51 checker_perform_vm_unwire(
52 checker_list_t *checker_list,
53 mach_vm_address_t start,
54 mach_vm_size_t size)
55 {
56 entry_checker_range_t limit = checker_list_find_and_clip(checker_list, start, size);
57 FOREACH_CHECKER(checker, limit) {
58 assert(checker->user_wired_count > 0);
59 checker->user_wired_count--;
60 }
61 checker_list_simplify(checker_list, start, size);
62 }
63
64
65 /*
66 * Update checker state to mirror a successful call to
67 * vm_wire(PROT_NONE) a.k.a. unwire
68 * of a range that includes holes.
69 */
70 static kern_return_t
checker_perform_vm_unwire_with_holes(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)71 checker_perform_vm_unwire_with_holes(
72 checker_list_t *checker_list,
73 mach_vm_address_t start,
74 mach_vm_size_t size)
75 {
76 entry_checker_range_t limit = checker_list_find_range_including_holes(checker_list, start, size);
77
78 if (limit.head && limit.head->kind == Allocation &&
79 checker_contains_address(limit.head, start)) {
80 /* range begins with an allocation - proceed normally */
81 } else {
82 /* range begins with a hole - do nothing, not even simplify */
83 return KERN_INVALID_ADDRESS;
84 }
85
86 FOREACH_CHECKER(checker, limit) {
87 if (checker->kind == Allocation) {
88 assert(checker->user_wired_count > 0);
89 checker->user_wired_count--;
90 }
91 }
92
93 checker_list_simplify(checker_list, start, size);
94 return KERN_SUCCESS;
95 }
96
97
98 /*
99 * Update checker state to mirrow a successful call to vm_wire.
100 */
101 static void
checker_perform_vm_wire(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,vm_prot_t wire_prot)102 checker_perform_vm_wire(
103 checker_list_t *checker_list,
104 mach_vm_address_t start,
105 mach_vm_size_t size,
106 vm_prot_t wire_prot)
107 {
108 assert(wire_prot != VM_PROT_NONE);
109
110 entry_checker_range_t limit;
111
112 /*
113 * Resolve null objects.
114 * vm_wire does this before clipping
115 */
116 limit = checker_list_find_range_including_holes(checker_list, start, size);
117 FOREACH_CHECKER(checker, limit) {
118 checker_resolve_null_vm_object(checker_list, checker);
119 }
120
121 /*
122 * Perform clipping.
123 */
124 limit = checker_list_find_range(checker_list, start, size);
125 checker_clip_left(checker_list, limit.head, start);
126 checker_clip_right(checker_list, limit.tail, start + size);
127
128 /*
129 * Fault and wire.
130 */
131
132 FOREACH_CHECKER(checker, limit) {
133 checker->user_wired_count++;
134 checker_fault_for_prot_not_cow(checker_list, checker, wire_prot);
135 }
136 checker_list_simplify(checker_list, start, size);
137 }
138
139
140 static void
checker_perform_failed_vm_wire(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size,vm_prot_t wire_prot)141 checker_perform_failed_vm_wire(
142 checker_list_t *checker_list,
143 mach_vm_address_t start,
144 mach_vm_size_t size,
145 vm_prot_t wire_prot)
146 {
147 assert(wire_prot != VM_PROT_NONE);
148
149 /*
150 * failed vm_wire clips entries and resolves null vm_objects
151 * one at a time until the entry that it couldn't change
152 *
153 * failed vm_wire doesn't simplify clipped entries on exit
154 *
155 * failed vm_wire is inconsistent about resident page counts
156 */
157
158 entry_checker_range_t limit =
159 checker_list_find_range_including_holes(checker_list, start, size);
160 FOREACH_CHECKER(checker, limit) {
161 if (checker->kind != Allocation) {
162 /* stop at holes */
163 break;
164 }
165
166 /* wire of executable entry fails early */
167 if (prot_contains_all(checker->protection, VM_PROT_EXECUTE)) {
168 // (fixme jit, tpro)
169 break;
170 }
171
172 /* null vm_objects are resolved before clipping */
173 checker_resolve_null_vm_object(checker_list, checker);
174
175 if (checker == limit.head) {
176 checker_clip_left(checker_list, checker, start);
177 }
178 if (checker == limit.tail) {
179 checker_clip_right(checker_list, checker, start + size);
180 }
181
182 if (!prot_contains_all(checker->protection, wire_prot)) {
183 /* stop at protection failures */
184 break;
185 }
186
187 if (checker != limit.tail && checker->next->kind != Allocation) {
188 /* stop if the *next* entry is in range and is an illegal hole */
189 break;
190 }
191
192 /*
193 * failed vm_wire simplifies and faults in,
194 * except for the cases already short-circuited above
195 */
196 checker_fault_for_prot_not_cow(checker_list, checker, wire_prot);
197 checker_simplify_left(checker_list, checker);
198 }
199 }
200
201
202 static test_result_t
successful_vm_wire_read_not_cow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)203 successful_vm_wire_read_not_cow(
204 checker_list_t *checker_list,
205 mach_vm_address_t start,
206 mach_vm_size_t size)
207 {
208 kern_return_t kr;
209
210 checker_perform_vm_wire(checker_list, start, size, VM_PROT_READ);
211 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_READ);
212 if (kr) {
213 T_FAIL("mach_vm_wire failed (%s)", name_for_kr(kr));
214 return TestFailed;
215 }
216
217 if (verify_vm_state(checker_list, "after vm_wire") != TestSucceeded) {
218 return TestFailed;
219 }
220
221 checker_perform_vm_unwire(checker_list, start, size);
222 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_NONE);
223 if (kr) {
224 T_FAIL("mach_vm_wire(unwire) failed (%s)", name_for_kr(kr));
225 return TestFailed;
226 }
227
228 if (verify_vm_state(checker_list, "after vm_unwire") != TestSucceeded) {
229 return TestFailed;
230 }
231
232 return TestSucceeded;
233 }
234
235 static test_result_t
failed_vm_wire_read_not_cow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)236 failed_vm_wire_read_not_cow(
237 checker_list_t *checker_list,
238 mach_vm_address_t start,
239 mach_vm_size_t size)
240 {
241 kern_return_t kr;
242
243 checker_perform_failed_vm_wire(checker_list, start, size, VM_PROT_READ);
244 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_READ);
245 if (kr == KERN_SUCCESS) {
246 T_FAIL("mach_vm_wire unexpectedly succeeded");
247 return TestFailed;
248 }
249
250 return verify_vm_state(checker_list, "after unsuccessful vm_wire");
251 }
252
253 static test_result_t
wire_shared_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)254 wire_shared_entry(
255 checker_list_t *checker_list,
256 mach_vm_address_t start,
257 mach_vm_size_t size)
258 {
259 /* two entries each sharing the same object */
260 vm_entry_checker_t *right_checker = checker_list_nth(checker_list, 1);
261
262 kern_return_t kr;
263
264 /*
265 * Wire the left entry. The right entry also faults in but
266 * stays at wire count zero.
267 */
268 checker_perform_vm_wire(checker_list, start, size, VM_PROT_READ);
269 checker_fault_for_prot_not_cow(checker_list, right_checker, VM_PROT_READ);
270 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_READ);
271 assert(kr == 0);
272
273 return verify_vm_state(checker_list, "after vm_wire shared");
274 }
275
276 static test_result_t
wire_shared_entry_discontiguous(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)277 wire_shared_entry_discontiguous(
278 checker_list_t *checker_list,
279 mach_vm_address_t start,
280 mach_vm_size_t size)
281 {
282 /*
283 * two entries each sharing the same object
284 * but only partially overlap inside that object.
285 * Wiring the left entry does not affect the right entry,
286 * so this looks like an ordinary vm_wire test.
287 */
288 return successful_vm_wire_read_not_cow(checker_list, start, size);
289 }
290
291 static test_result_t
wire_shared_entry_partial(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)292 wire_shared_entry_partial(
293 checker_list_t *checker_list,
294 mach_vm_address_t start,
295 mach_vm_size_t size)
296 {
297 /*
298 * two entries each sharing the same object
299 * but only partially overlap inside that object
300 */
301 vm_entry_checker_t *right_checker = checker_list_nth(checker_list, 1);
302 mach_vm_address_t right_offset = DEFAULT_PARTIAL_ENTRY_SIZE;
303
304 kern_return_t kr;
305
306 /*
307 * Wire the left entry. The right entry stays at wire count zero
308 * and only the overlapping section faults in.
309 */
310 checker_perform_vm_wire(checker_list, start, size, VM_PROT_READ);
311 right_checker->pages_resident = (uint32_t)((size - right_offset) / PAGE_SIZE);
312 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_READ);
313 assert(kr == 0);
314
315 return verify_vm_state(checker_list, "after vm_wire shared partial");
316 }
317
318 static void
checker_make_cow_private(checker_list_t * checker_list,vm_entry_checker_t * checker)319 checker_make_cow_private(
320 checker_list_t *checker_list,
321 vm_entry_checker_t *checker)
322 {
323 if (checker->object->self_ref_count == 1) {
324 /*
325 * COW but not shared with anything else.
326 * VM resolves COW by using the same object.
327 */
328 checker->needs_copy = false;
329 return;
330 }
331
332 /* make new object */
333 vm_object_checker_t *obj_checker = object_checker_clone(checker->object);
334 checker_list_append_object(checker_list, obj_checker);
335
336 /* change object and entry to private */
337 checker->needs_copy = false;
338
339 /* set new object (decreasing previous object's self_ref_count) */
340 checker_set_object(checker, obj_checker);
341 }
342
343 static test_result_t
wire_cow_entry(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)344 wire_cow_entry(
345 checker_list_t *checker_list,
346 mach_vm_address_t start,
347 mach_vm_size_t size)
348 {
349 /* Wiring a COW entry resolves COW but has no effect on other copies. */
350
351 vm_entry_checker_t *left_checker = checker_list_nth(checker_list, 0);
352 checker_make_cow_private(checker_list, left_checker);
353
354 return successful_vm_wire_read_not_cow(checker_list, start, size);
355 }
356
357 static test_result_t
wire_cow_nocow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)358 wire_cow_nocow(
359 checker_list_t *checker_list,
360 mach_vm_address_t start,
361 mach_vm_size_t size)
362 {
363 vm_entry_checker_t *left_checker = checker_list_nth(checker_list, 0);
364 checker_make_cow_private(checker_list, left_checker);
365
366 return successful_vm_wire_read_not_cow(checker_list, start, size);
367 }
368
369 static test_result_t
wire_nocow_cow(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)370 wire_nocow_cow(
371 checker_list_t *checker_list,
372 mach_vm_address_t start,
373 mach_vm_size_t size)
374 {
375 vm_entry_checker_t *left_checker = checker_list_nth(checker_list, 0);
376 vm_entry_checker_t *right_checker = left_checker->next;
377 checker_make_cow_private(checker_list, right_checker);
378
379 return successful_vm_wire_read_not_cow(checker_list, start, size);
380 }
381
382 static test_result_t
wire_cow_unreadable(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)383 wire_cow_unreadable(
384 checker_list_t *checker_list,
385 mach_vm_address_t start,
386 mach_vm_size_t size)
387 {
388 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
389 checker_make_shadow_object(checker_list, checker);
390 return failed_vm_wire_read_not_cow(checker_list, start, size);
391 }
392
393 static test_result_t
wire_cow_unwriteable(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)394 wire_cow_unwriteable(
395 checker_list_t *checker_list,
396 mach_vm_address_t start,
397 mach_vm_size_t size)
398 {
399 vm_entry_checker_t *checker = checker_list_nth(checker_list, 0);
400 checker_make_cow_private(checker_list, checker);
401
402 return successful_vm_wire_read_not_cow(checker_list, start, size);
403 }
404
405
406 /*
407 * Test vm_unwire with a range that includes holes.
408 * We wire each allocation separately, then unwire the entire range
409 * to test unwire's behavior across holes without reference to
410 * wire's behavior across holes.
411 */
412 static test_result_t
vm_unwire_holes(checker_list_t * checker_list,mach_vm_address_t start,mach_vm_size_t size)413 vm_unwire_holes(
414 checker_list_t *checker_list,
415 mach_vm_address_t start,
416 mach_vm_size_t size)
417 {
418 kern_return_t kr, expected_kr;
419
420 /*
421 * Wire each allocation separately,
422 * then unwire the entire range at once.
423 */
424
425 mach_vm_address_t end = start + size;
426
427 entry_checker_range_t limit =
428 checker_list_find_range_including_holes(checker_list, start, size);
429
430 FOREACH_CHECKER(checker, limit) {
431 if (checker->kind == Allocation) {
432 /*
433 * we manually "clip" our address range here
434 * because the real checker clipping must
435 * be done inside checker_perform_vm_wire()
436 * because wire's clip behavior is weird
437 */
438 mach_vm_address_t clipped_address = max(start, checker->address);
439 mach_vm_address_t clipped_end = min(checker_end_address(checker), end);
440 mach_vm_size_t clipped_size = clipped_end - clipped_address;
441 kr = mach_vm_wire(host_priv(), mach_task_self(),
442 clipped_address, clipped_size, VM_PROT_READ);
443 assert(kr == 0);
444 checker_perform_vm_wire(checker_list,
445 clipped_address, clipped_size, VM_PROT_READ);
446 }
447 }
448
449 if (verify_vm_state(checker_list, "before vm_unwire") != TestSucceeded) {
450 return TestFailed;
451 }
452
453 expected_kr = checker_perform_vm_unwire_with_holes(checker_list, start, size);
454 kr = mach_vm_wire(host_priv(), mach_task_self(), start, size, VM_PROT_NONE);
455 if (kr != expected_kr) {
456 T_FAIL("mach_vm_wire(unwire) returned %d (%s), expected %d (%s)\n",
457 kr, name_for_kr(kr), expected_kr, name_for_kr(expected_kr));
458 return TestFailed;
459 }
460
461 if (verify_vm_state(checker_list, "after vm_unwire") != TestSucceeded) {
462 return TestFailed;
463 }
464
465 return TestSucceeded;
466 }
467
468 T_DECL(vm_wire,
469 "run vm_wire with various vm configurations")
470 {
471 vm_tests_t tests = {
472 .single_entry_1 = successful_vm_wire_read_not_cow,
473 .single_entry_2 = successful_vm_wire_read_not_cow,
474 .single_entry_3 = successful_vm_wire_read_not_cow,
475 .single_entry_4 = successful_vm_wire_read_not_cow,
476
477 .multiple_entries_1 = successful_vm_wire_read_not_cow,
478 .multiple_entries_2 = successful_vm_wire_read_not_cow,
479 .multiple_entries_3 = successful_vm_wire_read_not_cow,
480 .multiple_entries_4 = successful_vm_wire_read_not_cow,
481 .multiple_entries_5 = successful_vm_wire_read_not_cow,
482 .multiple_entries_6 = successful_vm_wire_read_not_cow,
483
484 .some_holes_1 = failed_vm_wire_read_not_cow,
485 .some_holes_2 = failed_vm_wire_read_not_cow,
486 .some_holes_3 = failed_vm_wire_read_not_cow,
487 .some_holes_4 = failed_vm_wire_read_not_cow,
488 .some_holes_5 = failed_vm_wire_read_not_cow,
489 .some_holes_6 = failed_vm_wire_read_not_cow,
490 .some_holes_7 = failed_vm_wire_read_not_cow,
491 .some_holes_8 = failed_vm_wire_read_not_cow,
492 .some_holes_9 = failed_vm_wire_read_not_cow,
493 .some_holes_10 = failed_vm_wire_read_not_cow,
494 .some_holes_11 = failed_vm_wire_read_not_cow,
495 .some_holes_12 = failed_vm_wire_read_not_cow,
496
497 .all_holes_1 = failed_vm_wire_read_not_cow,
498 .all_holes_2 = failed_vm_wire_read_not_cow,
499 .all_holes_3 = failed_vm_wire_read_not_cow,
500 .all_holes_4 = failed_vm_wire_read_not_cow,
501
502 .null_entry = successful_vm_wire_read_not_cow,
503 .nonresident_entry = successful_vm_wire_read_not_cow,
504 .resident_entry = successful_vm_wire_read_not_cow,
505
506 .shared_entry = wire_shared_entry,
507 .shared_entry_discontiguous = wire_shared_entry_discontiguous,
508 .shared_entry_partial = wire_shared_entry_partial,
509 .shared_entry_pairs = successful_vm_wire_read_not_cow,
510 .shared_entry_x1000 = successful_vm_wire_read_not_cow,
511
512 .cow_entry = wire_cow_entry,
513 .cow_unreferenced = wire_cow_entry,
514 .cow_nocow = wire_cow_nocow,
515 .nocow_cow = wire_nocow_cow,
516 .cow_unreadable = wire_cow_unreadable,
517 .cow_unwriteable = wire_cow_unwriteable,
518
519 .permanent_entry = successful_vm_wire_read_not_cow,
520 .permanent_before_permanent = successful_vm_wire_read_not_cow,
521 .permanent_before_allocation = successful_vm_wire_read_not_cow,
522 .permanent_before_allocation_2 = successful_vm_wire_read_not_cow,
523 .permanent_before_hole = failed_vm_wire_read_not_cow,
524 .permanent_after_allocation = successful_vm_wire_read_not_cow,
525 .permanent_after_hole = failed_vm_wire_read_not_cow,
526
527 /* TODO: wire vs submaps */
528 .single_submap_single_entry = test_is_unimplemented,
529 .single_submap_single_entry_first_pages = test_is_unimplemented,
530 .single_submap_single_entry_last_pages = test_is_unimplemented,
531 .single_submap_single_entry_middle_pages = test_is_unimplemented,
532 .single_submap_oversize_entry_at_start = test_is_unimplemented,
533 .single_submap_oversize_entry_at_end = test_is_unimplemented,
534 .single_submap_oversize_entry_at_both = test_is_unimplemented,
535
536 .submap_before_allocation = test_is_unimplemented,
537 .submap_after_allocation = test_is_unimplemented,
538 .submap_before_hole = test_is_unimplemented,
539 .submap_after_hole = test_is_unimplemented,
540 .submap_allocation_submap_one_entry = test_is_unimplemented,
541 .submap_allocation_submap_two_entries = test_is_unimplemented,
542 .submap_allocation_submap_three_entries = test_is_unimplemented,
543
544 .submap_before_allocation_ro = test_is_unimplemented,
545 .submap_after_allocation_ro = test_is_unimplemented,
546 .submap_before_hole_ro = test_is_unimplemented,
547 .submap_after_hole_ro = test_is_unimplemented,
548 .submap_allocation_submap_one_entry_ro = test_is_unimplemented,
549 .submap_allocation_submap_two_entries_ro = test_is_unimplemented,
550 .submap_allocation_submap_three_entries_ro = test_is_unimplemented,
551
552 .protection_single_000_000 = failed_vm_wire_read_not_cow,
553 .protection_single_000_r00 = failed_vm_wire_read_not_cow,
554 .protection_single_000_0w0 = failed_vm_wire_read_not_cow,
555 .protection_single_000_rw0 = failed_vm_wire_read_not_cow,
556 .protection_single_r00_r00 = successful_vm_wire_read_not_cow,
557 .protection_single_r00_rw0 = successful_vm_wire_read_not_cow,
558 .protection_single_0w0_0w0 = failed_vm_wire_read_not_cow,
559 .protection_single_0w0_rw0 = failed_vm_wire_read_not_cow,
560 .protection_single_rw0_rw0 = successful_vm_wire_read_not_cow,
561
562 .protection_pairs_000_000 = failed_vm_wire_read_not_cow,
563 .protection_pairs_000_r00 = failed_vm_wire_read_not_cow,
564 .protection_pairs_000_0w0 = failed_vm_wire_read_not_cow,
565 .protection_pairs_000_rw0 = failed_vm_wire_read_not_cow,
566 .protection_pairs_r00_000 = failed_vm_wire_read_not_cow,
567 .protection_pairs_r00_r00 = successful_vm_wire_read_not_cow,
568 .protection_pairs_r00_0w0 = failed_vm_wire_read_not_cow,
569 .protection_pairs_r00_rw0 = successful_vm_wire_read_not_cow,
570 .protection_pairs_0w0_000 = failed_vm_wire_read_not_cow,
571 .protection_pairs_0w0_r00 = failed_vm_wire_read_not_cow,
572 .protection_pairs_0w0_0w0 = failed_vm_wire_read_not_cow,
573 .protection_pairs_0w0_rw0 = failed_vm_wire_read_not_cow,
574 .protection_pairs_rw0_000 = failed_vm_wire_read_not_cow,
575 .protection_pairs_rw0_r00 = successful_vm_wire_read_not_cow,
576 .protection_pairs_rw0_0w0 = failed_vm_wire_read_not_cow,
577 .protection_pairs_rw0_rw0 = successful_vm_wire_read_not_cow,
578 };
579
580 run_vm_tests("vm_wire", __FILE__, &tests, argc, argv);
581 }
582
583
584 T_DECL(vm_unwire,
585 "run vm_unwire with various vm configurations")
586 {
587 vm_tests_t tests = {
588 .single_entry_1 = test_is_unimplemented,
589 .single_entry_2 = test_is_unimplemented,
590 .single_entry_3 = test_is_unimplemented,
591 .single_entry_4 = test_is_unimplemented,
592
593 .multiple_entries_1 = test_is_unimplemented,
594 .multiple_entries_2 = test_is_unimplemented,
595 .multiple_entries_3 = test_is_unimplemented,
596 .multiple_entries_4 = test_is_unimplemented,
597 .multiple_entries_5 = test_is_unimplemented,
598 .multiple_entries_6 = test_is_unimplemented,
599
600 .some_holes_1 = vm_unwire_holes,
601 .some_holes_2 = vm_unwire_holes,
602 .some_holes_3 = vm_unwire_holes,
603 .some_holes_4 = vm_unwire_holes,
604 .some_holes_5 = vm_unwire_holes,
605 .some_holes_6 = vm_unwire_holes,
606 .some_holes_7 = vm_unwire_holes,
607 .some_holes_8 = vm_unwire_holes,
608 .some_holes_9 = vm_unwire_holes,
609 .some_holes_10 = vm_unwire_holes,
610 .some_holes_11 = vm_unwire_holes,
611 .some_holes_12 = vm_unwire_holes,
612
613 .all_holes_1 = vm_unwire_holes,
614 .all_holes_2 = vm_unwire_holes,
615 .all_holes_3 = vm_unwire_holes,
616 .all_holes_4 = vm_unwire_holes,
617
618 .null_entry = test_is_unimplemented,
619 .nonresident_entry = test_is_unimplemented,
620 .resident_entry = test_is_unimplemented,
621
622 .shared_entry = test_is_unimplemented,
623 .shared_entry_discontiguous = test_is_unimplemented,
624 .shared_entry_partial = test_is_unimplemented,
625 .shared_entry_pairs = test_is_unimplemented,
626 .shared_entry_x1000 = test_is_unimplemented,
627
628 .cow_entry = test_is_unimplemented,
629 .cow_unreferenced = test_is_unimplemented,
630 .cow_nocow = test_is_unimplemented,
631 .nocow_cow = test_is_unimplemented,
632 .cow_unreadable = test_is_unimplemented,
633 .cow_unwriteable = test_is_unimplemented,
634
635 .permanent_entry = test_is_unimplemented,
636 .permanent_before_permanent = test_is_unimplemented,
637 .permanent_before_allocation = test_is_unimplemented,
638 .permanent_before_allocation_2 = test_is_unimplemented,
639 .permanent_before_hole = test_is_unimplemented,
640 .permanent_after_allocation = test_is_unimplemented,
641 .permanent_after_hole = test_is_unimplemented,
642
643 .single_submap_single_entry = test_is_unimplemented,
644 .single_submap_single_entry_first_pages = test_is_unimplemented,
645 .single_submap_single_entry_last_pages = test_is_unimplemented,
646 .single_submap_single_entry_middle_pages = test_is_unimplemented,
647 .single_submap_oversize_entry_at_start = test_is_unimplemented,
648 .single_submap_oversize_entry_at_end = test_is_unimplemented,
649 .single_submap_oversize_entry_at_both = test_is_unimplemented,
650
651 .submap_before_allocation = test_is_unimplemented,
652 .submap_after_allocation = test_is_unimplemented,
653 .submap_before_hole = test_is_unimplemented,
654 .submap_after_hole = test_is_unimplemented,
655 .submap_allocation_submap_one_entry = test_is_unimplemented,
656 .submap_allocation_submap_two_entries = test_is_unimplemented,
657 .submap_allocation_submap_three_entries = test_is_unimplemented,
658
659 .submap_before_allocation_ro = test_is_unimplemented,
660 .submap_after_allocation_ro = test_is_unimplemented,
661 .submap_before_hole_ro = test_is_unimplemented,
662 .submap_after_hole_ro = test_is_unimplemented,
663 .submap_allocation_submap_one_entry_ro = test_is_unimplemented,
664 .submap_allocation_submap_two_entries_ro = test_is_unimplemented,
665 .submap_allocation_submap_three_entries_ro = test_is_unimplemented,
666
667 .protection_single_000_000 = test_is_unimplemented,
668 .protection_single_000_r00 = test_is_unimplemented,
669 .protection_single_000_0w0 = test_is_unimplemented,
670 .protection_single_000_rw0 = test_is_unimplemented,
671 .protection_single_r00_r00 = test_is_unimplemented,
672 .protection_single_r00_rw0 = test_is_unimplemented,
673 .protection_single_0w0_0w0 = test_is_unimplemented,
674 .protection_single_0w0_rw0 = test_is_unimplemented,
675 .protection_single_rw0_rw0 = test_is_unimplemented,
676
677 .protection_pairs_000_000 = test_is_unimplemented,
678 .protection_pairs_000_r00 = test_is_unimplemented,
679 .protection_pairs_000_0w0 = test_is_unimplemented,
680 .protection_pairs_000_rw0 = test_is_unimplemented,
681 .protection_pairs_r00_000 = test_is_unimplemented,
682 .protection_pairs_r00_r00 = test_is_unimplemented,
683 .protection_pairs_r00_0w0 = test_is_unimplemented,
684 .protection_pairs_r00_rw0 = test_is_unimplemented,
685 .protection_pairs_0w0_000 = test_is_unimplemented,
686 .protection_pairs_0w0_r00 = test_is_unimplemented,
687 .protection_pairs_0w0_0w0 = test_is_unimplemented,
688 .protection_pairs_0w0_rw0 = test_is_unimplemented,
689 .protection_pairs_rw0_000 = test_is_unimplemented,
690 .protection_pairs_rw0_r00 = test_is_unimplemented,
691 .protection_pairs_rw0_0w0 = test_is_unimplemented,
692 .protection_pairs_rw0_rw0 = test_is_unimplemented,
693 };
694
695 run_vm_tests("vm_unwire", __FILE__, &tests, argc, argv);
696 }
697