xref: /xnu-10063.121.3/tests/vm_test_mach_map.c (revision 2c2f96dc2b9a4408a43d3150ae9c105355ca3daa)
1*2c2f96dcSApple OSS Distributions /* Mach vm map miscellaneous unit tests
2*2c2f96dcSApple OSS Distributions  *
3*2c2f96dcSApple OSS Distributions  * This test program serves to be a regression test suite for legacy
4*2c2f96dcSApple OSS Distributions  * vm issues, ideally each test will be linked to a radar number and
5*2c2f96dcSApple OSS Distributions  * perform a set of certain validations.
6*2c2f96dcSApple OSS Distributions  *
7*2c2f96dcSApple OSS Distributions  */
8*2c2f96dcSApple OSS Distributions #include <darwintest.h>
9*2c2f96dcSApple OSS Distributions 
10*2c2f96dcSApple OSS Distributions #include <dlfcn.h>
11*2c2f96dcSApple OSS Distributions #include <errno.h>
12*2c2f96dcSApple OSS Distributions #include <ptrauth.h>
13*2c2f96dcSApple OSS Distributions #include <stdio.h>
14*2c2f96dcSApple OSS Distributions #include <stdlib.h>
15*2c2f96dcSApple OSS Distributions #include <string.h>
16*2c2f96dcSApple OSS Distributions #include <time.h>
17*2c2f96dcSApple OSS Distributions 
18*2c2f96dcSApple OSS Distributions #include <sys/mman.h>
19*2c2f96dcSApple OSS Distributions 
20*2c2f96dcSApple OSS Distributions #include <mach/mach_error.h>
21*2c2f96dcSApple OSS Distributions #include <mach/mach_init.h>
22*2c2f96dcSApple OSS Distributions #include <mach/mach_port.h>
23*2c2f96dcSApple OSS Distributions #include <mach/mach_vm.h>
24*2c2f96dcSApple OSS Distributions #include <mach/vm_map.h>
25*2c2f96dcSApple OSS Distributions #include <mach/task.h>
26*2c2f96dcSApple OSS Distributions #include <mach/task_info.h>
27*2c2f96dcSApple OSS Distributions #include <mach/shared_region.h>
28*2c2f96dcSApple OSS Distributions #include <machine/cpu_capabilities.h>
29*2c2f96dcSApple OSS Distributions 
30*2c2f96dcSApple OSS Distributions T_GLOBAL_META(
31*2c2f96dcSApple OSS Distributions 	T_META_NAMESPACE("xnu.vm"),
32*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_NAME("xnu"),
33*2c2f96dcSApple OSS Distributions 	T_META_RADAR_COMPONENT_VERSION("VM"),
34*2c2f96dcSApple OSS Distributions 	T_META_RUN_CONCURRENTLY(true));
35*2c2f96dcSApple OSS Distributions 
36*2c2f96dcSApple OSS Distributions static void
test_memory_entry_tagging(int override_tag)37*2c2f96dcSApple OSS Distributions test_memory_entry_tagging(int override_tag)
38*2c2f96dcSApple OSS Distributions {
39*2c2f96dcSApple OSS Distributions 	int                     pass;
40*2c2f96dcSApple OSS Distributions 	int                     do_copy;
41*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
42*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr_orig, vmaddr_shared, vmaddr_copied;
43*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize_orig, vmsize_shared, vmsize_copied;
44*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       *vmaddr_ptr;
45*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          *vmsize_ptr;
46*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr_chunk;
47*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize_chunk;
48*2c2f96dcSApple OSS Distributions 	mach_vm_offset_t        vmoff;
49*2c2f96dcSApple OSS Distributions 	mach_port_t             mem_entry_copied, mem_entry_shared;
50*2c2f96dcSApple OSS Distributions 	mach_port_t             *mem_entry_ptr;
51*2c2f96dcSApple OSS Distributions 	int                     i;
52*2c2f96dcSApple OSS Distributions 	vm_region_submap_short_info_data_64_t ri;
53*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t  ri_count;
54*2c2f96dcSApple OSS Distributions 	unsigned int            depth;
55*2c2f96dcSApple OSS Distributions 	int                     vm_flags;
56*2c2f96dcSApple OSS Distributions 	int                     expected_tag;
57*2c2f96dcSApple OSS Distributions 
58*2c2f96dcSApple OSS Distributions 	vmaddr_copied = 0;
59*2c2f96dcSApple OSS Distributions 	vmaddr_shared = 0;
60*2c2f96dcSApple OSS Distributions 	vmsize_copied = 0;
61*2c2f96dcSApple OSS Distributions 	vmsize_shared = 0;
62*2c2f96dcSApple OSS Distributions 	vmaddr_chunk = 0;
63*2c2f96dcSApple OSS Distributions 	vmsize_chunk = 16 * 1024;
64*2c2f96dcSApple OSS Distributions 	vmaddr_orig = 0;
65*2c2f96dcSApple OSS Distributions 	vmsize_orig = 3 * vmsize_chunk;
66*2c2f96dcSApple OSS Distributions 	mem_entry_copied = MACH_PORT_NULL;
67*2c2f96dcSApple OSS Distributions 	mem_entry_shared = MACH_PORT_NULL;
68*2c2f96dcSApple OSS Distributions 	pass = 0;
69*2c2f96dcSApple OSS Distributions 
70*2c2f96dcSApple OSS Distributions 	vmaddr_orig = 0;
71*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
72*2c2f96dcSApple OSS Distributions 	    &vmaddr_orig,
73*2c2f96dcSApple OSS Distributions 	    vmsize_orig,
74*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE);
75*2c2f96dcSApple OSS Distributions 	T_QUIET;
76*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d] vm_allocate(%lld)",
77*2c2f96dcSApple OSS Distributions 	    override_tag, vmsize_orig);
78*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
79*2c2f96dcSApple OSS Distributions 		goto done;
80*2c2f96dcSApple OSS Distributions 	}
81*2c2f96dcSApple OSS Distributions 
82*2c2f96dcSApple OSS Distributions 	for (i = 0; i < vmsize_orig / vmsize_chunk; i++) {
83*2c2f96dcSApple OSS Distributions 		vmaddr_chunk = vmaddr_orig + (i * vmsize_chunk);
84*2c2f96dcSApple OSS Distributions 		kr = mach_vm_allocate(mach_task_self(),
85*2c2f96dcSApple OSS Distributions 		    &vmaddr_chunk,
86*2c2f96dcSApple OSS Distributions 		    vmsize_chunk,
87*2c2f96dcSApple OSS Distributions 		    (VM_FLAGS_FIXED |
88*2c2f96dcSApple OSS Distributions 		    VM_FLAGS_OVERWRITE |
89*2c2f96dcSApple OSS Distributions 		    VM_MAKE_TAG(100 + i)));
90*2c2f96dcSApple OSS Distributions 		T_QUIET;
91*2c2f96dcSApple OSS Distributions 		T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d] vm_allocate(%lld)",
92*2c2f96dcSApple OSS Distributions 		    override_tag, vmsize_chunk);
93*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
94*2c2f96dcSApple OSS Distributions 			goto done;
95*2c2f96dcSApple OSS Distributions 		}
96*2c2f96dcSApple OSS Distributions 	}
97*2c2f96dcSApple OSS Distributions 
98*2c2f96dcSApple OSS Distributions 	for (vmoff = 0;
99*2c2f96dcSApple OSS Distributions 	    vmoff < vmsize_orig;
100*2c2f96dcSApple OSS Distributions 	    vmoff += PAGE_SIZE) {
101*2c2f96dcSApple OSS Distributions 		*((unsigned char *)(uintptr_t)(vmaddr_orig + vmoff)) = 'x';
102*2c2f96dcSApple OSS Distributions 	}
103*2c2f96dcSApple OSS Distributions 
104*2c2f96dcSApple OSS Distributions 	do_copy = time(NULL) & 1;
105*2c2f96dcSApple OSS Distributions again:
106*2c2f96dcSApple OSS Distributions 	*((unsigned char *)(uintptr_t)vmaddr_orig) = 'x';
107*2c2f96dcSApple OSS Distributions 	if (do_copy) {
108*2c2f96dcSApple OSS Distributions 		mem_entry_ptr = &mem_entry_copied;
109*2c2f96dcSApple OSS Distributions 		vmsize_copied = vmsize_orig;
110*2c2f96dcSApple OSS Distributions 		vmsize_ptr = &vmsize_copied;
111*2c2f96dcSApple OSS Distributions 		vmaddr_copied = 0;
112*2c2f96dcSApple OSS Distributions 		vmaddr_ptr = &vmaddr_copied;
113*2c2f96dcSApple OSS Distributions 		vm_flags = MAP_MEM_VM_COPY;
114*2c2f96dcSApple OSS Distributions 	} else {
115*2c2f96dcSApple OSS Distributions 		mem_entry_ptr = &mem_entry_shared;
116*2c2f96dcSApple OSS Distributions 		vmsize_shared = vmsize_orig;
117*2c2f96dcSApple OSS Distributions 		vmsize_ptr = &vmsize_shared;
118*2c2f96dcSApple OSS Distributions 		vmaddr_shared = 0;
119*2c2f96dcSApple OSS Distributions 		vmaddr_ptr = &vmaddr_shared;
120*2c2f96dcSApple OSS Distributions 		vm_flags = MAP_MEM_VM_SHARE;
121*2c2f96dcSApple OSS Distributions 	}
122*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
123*2c2f96dcSApple OSS Distributions 	    vmsize_ptr,
124*2c2f96dcSApple OSS Distributions 	    vmaddr_orig,                            /* offset */
125*2c2f96dcSApple OSS Distributions 	    (vm_flags |
126*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE),
127*2c2f96dcSApple OSS Distributions 	    mem_entry_ptr,
128*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
129*2c2f96dcSApple OSS Distributions 	T_QUIET;
130*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_make_memory_entry()",
131*2c2f96dcSApple OSS Distributions 	    override_tag, do_copy);
132*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
133*2c2f96dcSApple OSS Distributions 		goto done;
134*2c2f96dcSApple OSS Distributions 	}
135*2c2f96dcSApple OSS Distributions 	T_QUIET;
136*2c2f96dcSApple OSS Distributions 	T_EXPECT_EQ(*vmsize_ptr, vmsize_orig, "[override_tag:%d][do_copy:%d] vmsize (0x%llx) != vmsize_orig (0x%llx)",
137*2c2f96dcSApple OSS Distributions 	    override_tag, do_copy, (uint64_t) *vmsize_ptr, (uint64_t) vmsize_orig);
138*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
139*2c2f96dcSApple OSS Distributions 		goto done;
140*2c2f96dcSApple OSS Distributions 	}
141*2c2f96dcSApple OSS Distributions 	T_QUIET;
142*2c2f96dcSApple OSS Distributions 	T_EXPECT_NOTNULL(*mem_entry_ptr, "[override_tag:%d][do_copy:%d] mem_entry == 0x%x",
143*2c2f96dcSApple OSS Distributions 	    override_tag, do_copy, *mem_entry_ptr);
144*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
145*2c2f96dcSApple OSS Distributions 		goto done;
146*2c2f96dcSApple OSS Distributions 	}
147*2c2f96dcSApple OSS Distributions 
148*2c2f96dcSApple OSS Distributions 	*vmaddr_ptr = 0;
149*2c2f96dcSApple OSS Distributions 	if (override_tag) {
150*2c2f96dcSApple OSS Distributions 		vm_flags = VM_MAKE_TAG(200);
151*2c2f96dcSApple OSS Distributions 	} else {
152*2c2f96dcSApple OSS Distributions 		vm_flags = 0;
153*2c2f96dcSApple OSS Distributions 	}
154*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
155*2c2f96dcSApple OSS Distributions 	    vmaddr_ptr,
156*2c2f96dcSApple OSS Distributions 	    vmsize_orig,
157*2c2f96dcSApple OSS Distributions 	    0,              /* mask */
158*2c2f96dcSApple OSS Distributions 	    vm_flags | VM_FLAGS_ANYWHERE,
159*2c2f96dcSApple OSS Distributions 	    *mem_entry_ptr,
160*2c2f96dcSApple OSS Distributions 	    0,              /* offset */
161*2c2f96dcSApple OSS Distributions 	    FALSE,              /* copy */
162*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
163*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
164*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
165*2c2f96dcSApple OSS Distributions 	T_QUIET;
166*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_vm_map()",
167*2c2f96dcSApple OSS Distributions 	    override_tag, do_copy);
168*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
169*2c2f96dcSApple OSS Distributions 		goto done;
170*2c2f96dcSApple OSS Distributions 	}
171*2c2f96dcSApple OSS Distributions 
172*2c2f96dcSApple OSS Distributions 	*((unsigned char *)(uintptr_t)vmaddr_orig) = 'X';
173*2c2f96dcSApple OSS Distributions 	if (*(unsigned char *)(uintptr_t)*vmaddr_ptr == 'X') {
174*2c2f96dcSApple OSS Distributions 		T_QUIET;
175*2c2f96dcSApple OSS Distributions 		T_EXPECT_EQ(do_copy, 0, "[override_tag:%d][do_copy:%d] memory shared instead of copied",
176*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy);
177*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
178*2c2f96dcSApple OSS Distributions 			goto done;
179*2c2f96dcSApple OSS Distributions 		}
180*2c2f96dcSApple OSS Distributions 	} else {
181*2c2f96dcSApple OSS Distributions 		T_QUIET;
182*2c2f96dcSApple OSS Distributions 		T_EXPECT_NE(do_copy, 0, "[override_tag:%d][do_copy:%d] memory copied instead of shared",
183*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy);
184*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
185*2c2f96dcSApple OSS Distributions 			goto done;
186*2c2f96dcSApple OSS Distributions 		}
187*2c2f96dcSApple OSS Distributions 	}
188*2c2f96dcSApple OSS Distributions 
189*2c2f96dcSApple OSS Distributions 	for (i = 0; i < vmsize_orig / vmsize_chunk; i++) {
190*2c2f96dcSApple OSS Distributions 		mach_vm_address_t       vmaddr_info;
191*2c2f96dcSApple OSS Distributions 		mach_vm_size_t          vmsize_info;
192*2c2f96dcSApple OSS Distributions 
193*2c2f96dcSApple OSS Distributions 		vmaddr_info = *vmaddr_ptr + (i * vmsize_chunk);
194*2c2f96dcSApple OSS Distributions 		vmsize_info = 0;
195*2c2f96dcSApple OSS Distributions 		depth = 1;
196*2c2f96dcSApple OSS Distributions 		ri_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
197*2c2f96dcSApple OSS Distributions 		kr = mach_vm_region_recurse(mach_task_self(),
198*2c2f96dcSApple OSS Distributions 		    &vmaddr_info,
199*2c2f96dcSApple OSS Distributions 		    &vmsize_info,
200*2c2f96dcSApple OSS Distributions 		    &depth,
201*2c2f96dcSApple OSS Distributions 		    (vm_region_recurse_info_t) &ri,
202*2c2f96dcSApple OSS Distributions 		    &ri_count);
203*2c2f96dcSApple OSS Distributions 		T_QUIET;
204*2c2f96dcSApple OSS Distributions 		T_EXPECT_MACH_SUCCESS(kr, "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx)",
205*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk);
206*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
207*2c2f96dcSApple OSS Distributions 			goto done;
208*2c2f96dcSApple OSS Distributions 		}
209*2c2f96dcSApple OSS Distributions 		T_QUIET;
210*2c2f96dcSApple OSS Distributions 		T_EXPECT_EQ(vmaddr_info, *vmaddr_ptr + (i * vmsize_chunk), "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx) returned addr 0x%llx",
211*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk, vmaddr_info);
212*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
213*2c2f96dcSApple OSS Distributions 			goto done;
214*2c2f96dcSApple OSS Distributions 		}
215*2c2f96dcSApple OSS Distributions 		T_QUIET;
216*2c2f96dcSApple OSS Distributions 		T_EXPECT_EQ(vmsize_info, vmsize_chunk, "[override_tag:%d][do_copy:%d] mach_vm_region_recurse(0x%llx+0x%llx) returned size 0x%llx expected 0x%llx",
217*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy, *vmaddr_ptr, i * vmsize_chunk, vmsize_info, vmsize_chunk);
218*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
219*2c2f96dcSApple OSS Distributions 			goto done;
220*2c2f96dcSApple OSS Distributions 		}
221*2c2f96dcSApple OSS Distributions 		if (override_tag) {
222*2c2f96dcSApple OSS Distributions 			expected_tag = 200;
223*2c2f96dcSApple OSS Distributions 		} else {
224*2c2f96dcSApple OSS Distributions 			expected_tag = 100 + i;
225*2c2f96dcSApple OSS Distributions 		}
226*2c2f96dcSApple OSS Distributions 		T_QUIET;
227*2c2f96dcSApple OSS Distributions 		T_EXPECT_EQ(ri.user_tag, expected_tag, "[override_tag:%d][do_copy:%d] i=%d tag=%d expected %d",
228*2c2f96dcSApple OSS Distributions 		    override_tag, do_copy, i, ri.user_tag, expected_tag);
229*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
230*2c2f96dcSApple OSS Distributions 			goto done;
231*2c2f96dcSApple OSS Distributions 		}
232*2c2f96dcSApple OSS Distributions 	}
233*2c2f96dcSApple OSS Distributions 
234*2c2f96dcSApple OSS Distributions 	if (++pass < 2) {
235*2c2f96dcSApple OSS Distributions 		do_copy = !do_copy;
236*2c2f96dcSApple OSS Distributions 		goto again;
237*2c2f96dcSApple OSS Distributions 	}
238*2c2f96dcSApple OSS Distributions 
239*2c2f96dcSApple OSS Distributions done:
240*2c2f96dcSApple OSS Distributions 	if (vmaddr_orig != 0) {
241*2c2f96dcSApple OSS Distributions 		mach_vm_deallocate(mach_task_self(),
242*2c2f96dcSApple OSS Distributions 		    vmaddr_orig,
243*2c2f96dcSApple OSS Distributions 		    vmsize_orig);
244*2c2f96dcSApple OSS Distributions 		vmaddr_orig = 0;
245*2c2f96dcSApple OSS Distributions 		vmsize_orig = 0;
246*2c2f96dcSApple OSS Distributions 	}
247*2c2f96dcSApple OSS Distributions 	if (vmaddr_copied != 0) {
248*2c2f96dcSApple OSS Distributions 		mach_vm_deallocate(mach_task_self(),
249*2c2f96dcSApple OSS Distributions 		    vmaddr_copied,
250*2c2f96dcSApple OSS Distributions 		    vmsize_copied);
251*2c2f96dcSApple OSS Distributions 		vmaddr_copied = 0;
252*2c2f96dcSApple OSS Distributions 		vmsize_copied = 0;
253*2c2f96dcSApple OSS Distributions 	}
254*2c2f96dcSApple OSS Distributions 	if (vmaddr_shared != 0) {
255*2c2f96dcSApple OSS Distributions 		mach_vm_deallocate(mach_task_self(),
256*2c2f96dcSApple OSS Distributions 		    vmaddr_shared,
257*2c2f96dcSApple OSS Distributions 		    vmsize_shared);
258*2c2f96dcSApple OSS Distributions 		vmaddr_shared = 0;
259*2c2f96dcSApple OSS Distributions 		vmsize_shared = 0;
260*2c2f96dcSApple OSS Distributions 	}
261*2c2f96dcSApple OSS Distributions 	if (mem_entry_copied != MACH_PORT_NULL) {
262*2c2f96dcSApple OSS Distributions 		mach_port_deallocate(mach_task_self(), mem_entry_copied);
263*2c2f96dcSApple OSS Distributions 		mem_entry_copied = MACH_PORT_NULL;
264*2c2f96dcSApple OSS Distributions 	}
265*2c2f96dcSApple OSS Distributions 	if (mem_entry_shared != MACH_PORT_NULL) {
266*2c2f96dcSApple OSS Distributions 		mach_port_deallocate(mach_task_self(), mem_entry_shared);
267*2c2f96dcSApple OSS Distributions 		mem_entry_shared = MACH_PORT_NULL;
268*2c2f96dcSApple OSS Distributions 	}
269*2c2f96dcSApple OSS Distributions 
270*2c2f96dcSApple OSS Distributions 	return;
271*2c2f96dcSApple OSS Distributions }
272*2c2f96dcSApple OSS Distributions 
273*2c2f96dcSApple OSS Distributions static void
test_map_memory_entry(void)274*2c2f96dcSApple OSS Distributions test_map_memory_entry(void)
275*2c2f96dcSApple OSS Distributions {
276*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
277*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr1, vmaddr2;
278*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize1, vmsize2;
279*2c2f96dcSApple OSS Distributions 	mach_port_t             mem_entry;
280*2c2f96dcSApple OSS Distributions 	unsigned char           *cp1, *cp2;
281*2c2f96dcSApple OSS Distributions 
282*2c2f96dcSApple OSS Distributions 	vmaddr1 = 0;
283*2c2f96dcSApple OSS Distributions 	vmsize1 = 0;
284*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
285*2c2f96dcSApple OSS Distributions 	vmsize2 = 0;
286*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
287*2c2f96dcSApple OSS Distributions 
288*2c2f96dcSApple OSS Distributions 	vmsize1 = 1;
289*2c2f96dcSApple OSS Distributions 	vmaddr1 = 0;
290*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
291*2c2f96dcSApple OSS Distributions 	    &vmaddr1,
292*2c2f96dcSApple OSS Distributions 	    vmsize1,
293*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE);
294*2c2f96dcSApple OSS Distributions 	T_QUIET;
295*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "vm_allocate(%lld)", vmsize1);
296*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
297*2c2f96dcSApple OSS Distributions 		goto done;
298*2c2f96dcSApple OSS Distributions 	}
299*2c2f96dcSApple OSS Distributions 
300*2c2f96dcSApple OSS Distributions 	cp1 = (unsigned char *)(uintptr_t)vmaddr1;
301*2c2f96dcSApple OSS Distributions 	*cp1 = '1';
302*2c2f96dcSApple OSS Distributions 
303*2c2f96dcSApple OSS Distributions 	vmsize2 = 1;
304*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
305*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
306*2c2f96dcSApple OSS Distributions 	    &vmsize2,
307*2c2f96dcSApple OSS Distributions 	    vmaddr1,                            /* offset */
308*2c2f96dcSApple OSS Distributions 	    (MAP_MEM_VM_COPY |
309*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE),
310*2c2f96dcSApple OSS Distributions 	    &mem_entry,
311*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
312*2c2f96dcSApple OSS Distributions 	T_QUIET;
313*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry()");
314*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
315*2c2f96dcSApple OSS Distributions 		goto done;
316*2c2f96dcSApple OSS Distributions 	}
317*2c2f96dcSApple OSS Distributions 	T_QUIET;
318*2c2f96dcSApple OSS Distributions 	T_EXPECT_GE(vmsize2, vmsize1, "vmsize2 (0x%llx) < vmsize1 (0x%llx)",
319*2c2f96dcSApple OSS Distributions 	    (uint64_t) vmsize2, (uint64_t) vmsize1);
320*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
321*2c2f96dcSApple OSS Distributions 		goto done;
322*2c2f96dcSApple OSS Distributions 	}
323*2c2f96dcSApple OSS Distributions 	T_QUIET;
324*2c2f96dcSApple OSS Distributions 	T_EXPECT_NOTNULL(mem_entry, "mem_entry == 0x%x", mem_entry);
325*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
326*2c2f96dcSApple OSS Distributions 		goto done;
327*2c2f96dcSApple OSS Distributions 	}
328*2c2f96dcSApple OSS Distributions 
329*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
330*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
331*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
332*2c2f96dcSApple OSS Distributions 	    vmsize2,
333*2c2f96dcSApple OSS Distributions 	    0,              /* mask */
334*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
335*2c2f96dcSApple OSS Distributions 	    mem_entry,
336*2c2f96dcSApple OSS Distributions 	    0,              /* offset */
337*2c2f96dcSApple OSS Distributions 	    TRUE,              /* copy */
338*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
339*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
340*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
341*2c2f96dcSApple OSS Distributions 	T_QUIET;
342*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "mach_vm_map()");
343*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
344*2c2f96dcSApple OSS Distributions 		goto done;
345*2c2f96dcSApple OSS Distributions 	}
346*2c2f96dcSApple OSS Distributions 
347*2c2f96dcSApple OSS Distributions 	cp2 = (unsigned char *)(uintptr_t)vmaddr2;
348*2c2f96dcSApple OSS Distributions 	T_QUIET;
349*2c2f96dcSApple OSS Distributions 	T_EXPECT_TRUE(((*cp1 == '1') && (*cp2 == '1')), "*cp1/*cp2 0x%x/0x%x expected 0x%x/0x%x",
350*2c2f96dcSApple OSS Distributions 	    *cp1, *cp2, '1', '1');
351*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
352*2c2f96dcSApple OSS Distributions 		goto done;
353*2c2f96dcSApple OSS Distributions 	}
354*2c2f96dcSApple OSS Distributions 
355*2c2f96dcSApple OSS Distributions 	*cp2 = '2';
356*2c2f96dcSApple OSS Distributions 	T_QUIET;
357*2c2f96dcSApple OSS Distributions 	T_EXPECT_TRUE(((*cp1 == '1') && (*cp2 == '2')), "*cp1/*cp2 0x%x/0x%x expected 0x%x/0x%x",
358*2c2f96dcSApple OSS Distributions 	    *cp1, *cp2, '1', '2');
359*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
360*2c2f96dcSApple OSS Distributions 		goto done;
361*2c2f96dcSApple OSS Distributions 	}
362*2c2f96dcSApple OSS Distributions 
363*2c2f96dcSApple OSS Distributions done:
364*2c2f96dcSApple OSS Distributions 	if (vmaddr1 != 0) {
365*2c2f96dcSApple OSS Distributions 		mach_vm_deallocate(mach_task_self(), vmaddr1, vmsize1);
366*2c2f96dcSApple OSS Distributions 		vmaddr1 = 0;
367*2c2f96dcSApple OSS Distributions 		vmsize1 = 0;
368*2c2f96dcSApple OSS Distributions 	}
369*2c2f96dcSApple OSS Distributions 	if (vmaddr2 != 0) {
370*2c2f96dcSApple OSS Distributions 		mach_vm_deallocate(mach_task_self(), vmaddr2, vmsize2);
371*2c2f96dcSApple OSS Distributions 		vmaddr2 = 0;
372*2c2f96dcSApple OSS Distributions 		vmsize2 = 0;
373*2c2f96dcSApple OSS Distributions 	}
374*2c2f96dcSApple OSS Distributions 	if (mem_entry != MACH_PORT_NULL) {
375*2c2f96dcSApple OSS Distributions 		mach_port_deallocate(mach_task_self(), mem_entry);
376*2c2f96dcSApple OSS Distributions 		mem_entry = MACH_PORT_NULL;
377*2c2f96dcSApple OSS Distributions 	}
378*2c2f96dcSApple OSS Distributions 
379*2c2f96dcSApple OSS Distributions 	return;
380*2c2f96dcSApple OSS Distributions }
381*2c2f96dcSApple OSS Distributions 
382*2c2f96dcSApple OSS Distributions T_DECL(memory_entry_tagging, "test mem entry tag for rdar://problem/23334087 \
383*2c2f96dcSApple OSS Distributions     VM memory tags should be propagated through memory entries",
384*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
385*2c2f96dcSApple OSS Distributions {
386*2c2f96dcSApple OSS Distributions 	test_memory_entry_tagging(0);
387*2c2f96dcSApple OSS Distributions 	test_memory_entry_tagging(1);
388*2c2f96dcSApple OSS Distributions }
389*2c2f96dcSApple OSS Distributions 
390*2c2f96dcSApple OSS Distributions T_DECL(map_memory_entry, "test mapping mem entry for rdar://problem/22611816 \
391*2c2f96dcSApple OSS Distributions     mach_make_memory_entry(MAP_MEM_VM_COPY) should never use a KERNEL_BUFFER \
392*2c2f96dcSApple OSS Distributions     copy", T_META_ALL_VALID_ARCHS(true))
393*2c2f96dcSApple OSS Distributions {
394*2c2f96dcSApple OSS Distributions 	test_map_memory_entry();
395*2c2f96dcSApple OSS Distributions }
396*2c2f96dcSApple OSS Distributions 
397*2c2f96dcSApple OSS Distributions static char *vm_purgable_state[4] = { "NONVOLATILE", "VOLATILE", "EMPTY", "DENY" };
398*2c2f96dcSApple OSS Distributions 
399*2c2f96dcSApple OSS Distributions static uint64_t
task_footprint(void)400*2c2f96dcSApple OSS Distributions task_footprint(void)
401*2c2f96dcSApple OSS Distributions {
402*2c2f96dcSApple OSS Distributions 	task_vm_info_data_t ti;
403*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
404*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t count;
405*2c2f96dcSApple OSS Distributions 
406*2c2f96dcSApple OSS Distributions 	count = TASK_VM_INFO_COUNT;
407*2c2f96dcSApple OSS Distributions 	kr = task_info(mach_task_self(),
408*2c2f96dcSApple OSS Distributions 	    TASK_VM_INFO,
409*2c2f96dcSApple OSS Distributions 	    (task_info_t) &ti,
410*2c2f96dcSApple OSS Distributions 	    &count);
411*2c2f96dcSApple OSS Distributions 	T_QUIET;
412*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "task_info()");
413*2c2f96dcSApple OSS Distributions #if defined(__arm64__)
414*2c2f96dcSApple OSS Distributions 	T_QUIET;
415*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(count, TASK_VM_INFO_COUNT, "task_info() count = %d (expected %d)",
416*2c2f96dcSApple OSS Distributions 	    count, TASK_VM_INFO_COUNT);
417*2c2f96dcSApple OSS Distributions #endif /* defined(__arm64__) */
418*2c2f96dcSApple OSS Distributions 	return ti.phys_footprint;
419*2c2f96dcSApple OSS Distributions }
420*2c2f96dcSApple OSS Distributions 
421*2c2f96dcSApple OSS Distributions T_DECL(purgeable_empty_to_volatile, "test task physical footprint when \
422*2c2f96dcSApple OSS Distributions     emptying, volatilizing purgeable vm")
423*2c2f96dcSApple OSS Distributions {
424*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
425*2c2f96dcSApple OSS Distributions 	mach_vm_address_t vm_addr;
426*2c2f96dcSApple OSS Distributions 	mach_vm_size_t vm_size;
427*2c2f96dcSApple OSS Distributions 	char *cp;
428*2c2f96dcSApple OSS Distributions 	int ret;
429*2c2f96dcSApple OSS Distributions 	vm_purgable_t state;
430*2c2f96dcSApple OSS Distributions 	uint64_t footprint[8];
431*2c2f96dcSApple OSS Distributions 
432*2c2f96dcSApple OSS Distributions 	vm_addr = 0;
433*2c2f96dcSApple OSS Distributions 	vm_size = 1 * 1024 * 1024;
434*2c2f96dcSApple OSS Distributions 	T_LOG("--> allocate %llu bytes", vm_size);
435*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
436*2c2f96dcSApple OSS Distributions 	    &vm_addr,
437*2c2f96dcSApple OSS Distributions 	    vm_size,
438*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
439*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
440*2c2f96dcSApple OSS Distributions 
441*2c2f96dcSApple OSS Distributions 	/* footprint0 */
442*2c2f96dcSApple OSS Distributions 	footprint[0] = task_footprint();
443*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[0] = %llu", footprint[0]);
444*2c2f96dcSApple OSS Distributions 
445*2c2f96dcSApple OSS Distributions 	T_LOG("--> access %llu bytes", vm_size);
446*2c2f96dcSApple OSS Distributions 	for (cp = (char *) vm_addr;
447*2c2f96dcSApple OSS Distributions 	    cp < (char *) (vm_addr + vm_size);
448*2c2f96dcSApple OSS Distributions 	    cp += vm_kernel_page_size) {
449*2c2f96dcSApple OSS Distributions 		*cp = 'x';
450*2c2f96dcSApple OSS Distributions 	}
451*2c2f96dcSApple OSS Distributions 	/* footprint1 == footprint0 + vm_size */
452*2c2f96dcSApple OSS Distributions 	footprint[1] = task_footprint();
453*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[1] = %llu", footprint[1]);
454*2c2f96dcSApple OSS Distributions 	if (footprint[1] != footprint[0] + vm_size) {
455*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[1] != footprint[0] + vm_size");
456*2c2f96dcSApple OSS Distributions 	}
457*2c2f96dcSApple OSS Distributions 
458*2c2f96dcSApple OSS Distributions 	T_LOG("--> wire %llu bytes", vm_size / 2);
459*2c2f96dcSApple OSS Distributions 	ret = mlock((char *)vm_addr, (size_t) (vm_size / 2));
460*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "mlock()");
461*2c2f96dcSApple OSS Distributions 
462*2c2f96dcSApple OSS Distributions 	/* footprint2 == footprint1 */
463*2c2f96dcSApple OSS Distributions 	footprint[2] = task_footprint();
464*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[2] = %llu", footprint[2]);
465*2c2f96dcSApple OSS Distributions 	if (footprint[2] != footprint[1]) {
466*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[2] != footprint[1]");
467*2c2f96dcSApple OSS Distributions 	}
468*2c2f96dcSApple OSS Distributions 
469*2c2f96dcSApple OSS Distributions 	T_LOG("--> VOLATILE");
470*2c2f96dcSApple OSS Distributions 	state = VM_PURGABLE_VOLATILE;
471*2c2f96dcSApple OSS Distributions 	kr = mach_vm_purgable_control(mach_task_self(),
472*2c2f96dcSApple OSS Distributions 	    vm_addr,
473*2c2f96dcSApple OSS Distributions 	    VM_PURGABLE_SET_STATE,
474*2c2f96dcSApple OSS Distributions 	    &state);
475*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(VOLATILE)");
476*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(state, VM_PURGABLE_NONVOLATILE, "NONVOLATILE->VOLATILE: state was %s",
477*2c2f96dcSApple OSS Distributions 	    vm_purgable_state[state]);
478*2c2f96dcSApple OSS Distributions 	/* footprint3 == footprint2 - (vm_size / 2) */
479*2c2f96dcSApple OSS Distributions 	footprint[3] = task_footprint();
480*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[3] = %llu", footprint[3]);
481*2c2f96dcSApple OSS Distributions 	if (footprint[3] != footprint[2] - (vm_size / 2)) {
482*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[3] != footprint[2] - (vm_size / 2)");
483*2c2f96dcSApple OSS Distributions 	}
484*2c2f96dcSApple OSS Distributions 
485*2c2f96dcSApple OSS Distributions 	T_LOG("--> EMPTY");
486*2c2f96dcSApple OSS Distributions 	state = VM_PURGABLE_EMPTY;
487*2c2f96dcSApple OSS Distributions 	kr = mach_vm_purgable_control(mach_task_self(),
488*2c2f96dcSApple OSS Distributions 	    vm_addr,
489*2c2f96dcSApple OSS Distributions 	    VM_PURGABLE_SET_STATE,
490*2c2f96dcSApple OSS Distributions 	    &state);
491*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(EMPTY)");
492*2c2f96dcSApple OSS Distributions 	if (state != VM_PURGABLE_VOLATILE &&
493*2c2f96dcSApple OSS Distributions 	    state != VM_PURGABLE_EMPTY) {
494*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("VOLATILE->EMPTY: state was %s",
495*2c2f96dcSApple OSS Distributions 		    vm_purgable_state[state]);
496*2c2f96dcSApple OSS Distributions 	}
497*2c2f96dcSApple OSS Distributions 	/* footprint4 == footprint3 */
498*2c2f96dcSApple OSS Distributions 	footprint[4] = task_footprint();
499*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[4] = %llu", footprint[4]);
500*2c2f96dcSApple OSS Distributions 	if (footprint[4] != footprint[3]) {
501*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[4] != footprint[3]");
502*2c2f96dcSApple OSS Distributions 	}
503*2c2f96dcSApple OSS Distributions 
504*2c2f96dcSApple OSS Distributions 	T_LOG("--> unwire %llu bytes", vm_size / 2);
505*2c2f96dcSApple OSS Distributions 	ret = munlock((char *)vm_addr, (size_t) (vm_size / 2));
506*2c2f96dcSApple OSS Distributions 	T_ASSERT_POSIX_SUCCESS(ret, "munlock()");
507*2c2f96dcSApple OSS Distributions 
508*2c2f96dcSApple OSS Distributions 	/* footprint5 == footprint4 - (vm_size/2) (unless memory pressure) */
509*2c2f96dcSApple OSS Distributions 	/* footprint5 == footprint0 */
510*2c2f96dcSApple OSS Distributions 	footprint[5] = task_footprint();
511*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[5] = %llu", footprint[5]);
512*2c2f96dcSApple OSS Distributions 	if (footprint[5] != footprint[4] - (vm_size / 2)) {
513*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[5] != footprint[4] - (vm_size/2)");
514*2c2f96dcSApple OSS Distributions 	}
515*2c2f96dcSApple OSS Distributions 	if (footprint[5] != footprint[0]) {
516*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[5] != footprint[0]");
517*2c2f96dcSApple OSS Distributions 	}
518*2c2f96dcSApple OSS Distributions 
519*2c2f96dcSApple OSS Distributions 	T_LOG("--> VOLATILE");
520*2c2f96dcSApple OSS Distributions 	state = VM_PURGABLE_VOLATILE;
521*2c2f96dcSApple OSS Distributions 	kr = mach_vm_purgable_control(mach_task_self(),
522*2c2f96dcSApple OSS Distributions 	    vm_addr,
523*2c2f96dcSApple OSS Distributions 	    VM_PURGABLE_SET_STATE,
524*2c2f96dcSApple OSS Distributions 	    &state);
525*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(VOLATILE)");
526*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(state, VM_PURGABLE_EMPTY, "EMPTY->VOLATILE: state == %s",
527*2c2f96dcSApple OSS Distributions 	    vm_purgable_state[state]);
528*2c2f96dcSApple OSS Distributions 	/* footprint6 == footprint5 */
529*2c2f96dcSApple OSS Distributions 	/* footprint6 == footprint0 */
530*2c2f96dcSApple OSS Distributions 	footprint[6] = task_footprint();
531*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[6] = %llu", footprint[6]);
532*2c2f96dcSApple OSS Distributions 	if (footprint[6] != footprint[5]) {
533*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[6] != footprint[5]");
534*2c2f96dcSApple OSS Distributions 	}
535*2c2f96dcSApple OSS Distributions 	if (footprint[6] != footprint[0]) {
536*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[6] != footprint[0]");
537*2c2f96dcSApple OSS Distributions 	}
538*2c2f96dcSApple OSS Distributions 
539*2c2f96dcSApple OSS Distributions 	T_LOG("--> NONVOLATILE");
540*2c2f96dcSApple OSS Distributions 	state = VM_PURGABLE_NONVOLATILE;
541*2c2f96dcSApple OSS Distributions 	kr = mach_vm_purgable_control(mach_task_self(),
542*2c2f96dcSApple OSS Distributions 	    vm_addr,
543*2c2f96dcSApple OSS Distributions 	    VM_PURGABLE_SET_STATE,
544*2c2f96dcSApple OSS Distributions 	    &state);
545*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_purgable_control(NONVOLATILE)");
546*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(state, VM_PURGABLE_EMPTY, "EMPTY->NONVOLATILE: state == %s",
547*2c2f96dcSApple OSS Distributions 	    vm_purgable_state[state]);
548*2c2f96dcSApple OSS Distributions 	/* footprint7 == footprint6 */
549*2c2f96dcSApple OSS Distributions 	/* footprint7 == footprint0 */
550*2c2f96dcSApple OSS Distributions 	footprint[7] = task_footprint();
551*2c2f96dcSApple OSS Distributions 	T_LOG("    footprint[7] = %llu", footprint[7]);
552*2c2f96dcSApple OSS Distributions 	if (footprint[7] != footprint[6]) {
553*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[7] != footprint[6]");
554*2c2f96dcSApple OSS Distributions 	}
555*2c2f96dcSApple OSS Distributions 	if (footprint[7] != footprint[0]) {
556*2c2f96dcSApple OSS Distributions 		T_LOG("WARN: footprint[7] != footprint[0]");
557*2c2f96dcSApple OSS Distributions 	}
558*2c2f96dcSApple OSS Distributions }
559*2c2f96dcSApple OSS Distributions 
560*2c2f96dcSApple OSS Distributions kern_return_t
get_reusable_size(uint64_t * reusable)561*2c2f96dcSApple OSS Distributions get_reusable_size(uint64_t *reusable)
562*2c2f96dcSApple OSS Distributions {
563*2c2f96dcSApple OSS Distributions 	task_vm_info_data_t     ti;
564*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t  ti_count = TASK_VM_INFO_COUNT;
565*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
566*2c2f96dcSApple OSS Distributions 
567*2c2f96dcSApple OSS Distributions 	kr = task_info(mach_task_self(),
568*2c2f96dcSApple OSS Distributions 	    TASK_VM_INFO,
569*2c2f96dcSApple OSS Distributions 	    (task_info_t) &ti,
570*2c2f96dcSApple OSS Distributions 	    &ti_count);
571*2c2f96dcSApple OSS Distributions 	T_QUIET;
572*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "task_info()");
573*2c2f96dcSApple OSS Distributions 	T_QUIET;
574*2c2f96dcSApple OSS Distributions 	*reusable = ti.reusable;
575*2c2f96dcSApple OSS Distributions 	return kr;
576*2c2f96dcSApple OSS Distributions }
577*2c2f96dcSApple OSS Distributions 
578*2c2f96dcSApple OSS Distributions T_DECL(madvise_shared, "test madvise shared for rdar://problem/2295713 logging \
579*2c2f96dcSApple OSS Distributions     rethink needs madvise(MADV_FREE_HARDER)",
580*2c2f96dcSApple OSS Distributions     T_META_RUN_CONCURRENTLY(false),
581*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
582*2c2f96dcSApple OSS Distributions {
583*2c2f96dcSApple OSS Distributions 	vm_address_t            vmaddr = 0, vmaddr2 = 0;
584*2c2f96dcSApple OSS Distributions 	vm_size_t               vmsize, vmsize1, vmsize2;
585*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
586*2c2f96dcSApple OSS Distributions 	char                    *cp;
587*2c2f96dcSApple OSS Distributions 	vm_prot_t               curprot, maxprot;
588*2c2f96dcSApple OSS Distributions 	int                     ret;
589*2c2f96dcSApple OSS Distributions 	int                     vmflags;
590*2c2f96dcSApple OSS Distributions 	uint64_t                footprint_before, footprint_after;
591*2c2f96dcSApple OSS Distributions 	uint64_t                reusable_before, reusable_after, reusable_expected;
592*2c2f96dcSApple OSS Distributions 
593*2c2f96dcSApple OSS Distributions 
594*2c2f96dcSApple OSS Distributions 	vmsize1 = 64 * 1024; /* 64KB to madvise() */
595*2c2f96dcSApple OSS Distributions 	vmsize2 = 32 * 1024; /* 32KB to mlock() */
596*2c2f96dcSApple OSS Distributions 	vmsize = vmsize1 + vmsize2;
597*2c2f96dcSApple OSS Distributions 	vmflags = VM_FLAGS_ANYWHERE;
598*2c2f96dcSApple OSS Distributions 	VM_SET_FLAGS_ALIAS(vmflags, VM_MEMORY_MALLOC);
599*2c2f96dcSApple OSS Distributions 
600*2c2f96dcSApple OSS Distributions 	kr = get_reusable_size(&reusable_before);
601*2c2f96dcSApple OSS Distributions 	if (kr) {
602*2c2f96dcSApple OSS Distributions 		goto done;
603*2c2f96dcSApple OSS Distributions 	}
604*2c2f96dcSApple OSS Distributions 
605*2c2f96dcSApple OSS Distributions 	kr = vm_allocate(mach_task_self(),
606*2c2f96dcSApple OSS Distributions 	    &vmaddr,
607*2c2f96dcSApple OSS Distributions 	    vmsize,
608*2c2f96dcSApple OSS Distributions 	    vmflags);
609*2c2f96dcSApple OSS Distributions 	T_QUIET;
610*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "vm_allocate()");
611*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
612*2c2f96dcSApple OSS Distributions 		goto done;
613*2c2f96dcSApple OSS Distributions 	}
614*2c2f96dcSApple OSS Distributions 
615*2c2f96dcSApple OSS Distributions 	for (cp = (char *)(uintptr_t)vmaddr;
616*2c2f96dcSApple OSS Distributions 	    cp < (char *)(uintptr_t)(vmaddr + vmsize);
617*2c2f96dcSApple OSS Distributions 	    cp++) {
618*2c2f96dcSApple OSS Distributions 		*cp = 'x';
619*2c2f96dcSApple OSS Distributions 	}
620*2c2f96dcSApple OSS Distributions 
621*2c2f96dcSApple OSS Distributions 	kr = vm_remap(mach_task_self(),
622*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
623*2c2f96dcSApple OSS Distributions 	    vmsize,
624*2c2f96dcSApple OSS Distributions 	    0,           /* mask */
625*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
626*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
627*2c2f96dcSApple OSS Distributions 	    vmaddr,
628*2c2f96dcSApple OSS Distributions 	    FALSE,           /* copy */
629*2c2f96dcSApple OSS Distributions 	    &curprot,
630*2c2f96dcSApple OSS Distributions 	    &maxprot,
631*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
632*2c2f96dcSApple OSS Distributions 	T_QUIET;
633*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "vm_remap()");
634*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
635*2c2f96dcSApple OSS Distributions 		goto done;
636*2c2f96dcSApple OSS Distributions 	}
637*2c2f96dcSApple OSS Distributions 
638*2c2f96dcSApple OSS Distributions 	for (cp = (char *)(uintptr_t)vmaddr2;
639*2c2f96dcSApple OSS Distributions 	    cp < (char *)(uintptr_t)(vmaddr2 + vmsize);
640*2c2f96dcSApple OSS Distributions 	    cp++) {
641*2c2f96dcSApple OSS Distributions 		T_QUIET;
642*2c2f96dcSApple OSS Distributions 		T_EXPECT_EQ(*cp, 'x', "vmaddr=%p vmaddr2=%p %p:0x%x",
643*2c2f96dcSApple OSS Distributions 		    (void *)(uintptr_t)vmaddr,
644*2c2f96dcSApple OSS Distributions 		    (void *)(uintptr_t)vmaddr2,
645*2c2f96dcSApple OSS Distributions 		    (void *)cp,
646*2c2f96dcSApple OSS Distributions 		    (unsigned char)*cp);
647*2c2f96dcSApple OSS Distributions 		if (T_RESULT == T_RESULT_FAIL) {
648*2c2f96dcSApple OSS Distributions 			goto done;
649*2c2f96dcSApple OSS Distributions 		}
650*2c2f96dcSApple OSS Distributions 	}
651*2c2f96dcSApple OSS Distributions 	cp = (char *)(uintptr_t)vmaddr;
652*2c2f96dcSApple OSS Distributions 	*cp = 'X';
653*2c2f96dcSApple OSS Distributions 	cp = (char *)(uintptr_t)vmaddr2;
654*2c2f96dcSApple OSS Distributions 	T_QUIET;
655*2c2f96dcSApple OSS Distributions 	T_EXPECT_EQ(*cp, 'X', "memory was not properly shared");
656*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
657*2c2f96dcSApple OSS Distributions 		goto done;
658*2c2f96dcSApple OSS Distributions 	}
659*2c2f96dcSApple OSS Distributions 
660*2c2f96dcSApple OSS Distributions #if defined(__x86_64__) || defined(__i386__)
661*2c2f96dcSApple OSS Distributions 	if (COMM_PAGE_READ(uint64_t, CPU_CAPABILITIES64) & kIsTranslated) {
662*2c2f96dcSApple OSS Distributions 		T_LOG("Skipping madvise reusable tests because we're running under translation.");
663*2c2f96dcSApple OSS Distributions 		goto done;
664*2c2f96dcSApple OSS Distributions 	}
665*2c2f96dcSApple OSS Distributions #endif /* defined(__x86_64__) || defined(__i386__) */
666*2c2f96dcSApple OSS Distributions 
667*2c2f96dcSApple OSS Distributions 	ret = mlock((char *)(uintptr_t)(vmaddr2 + vmsize1),
668*2c2f96dcSApple OSS Distributions 	    vmsize2);
669*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_POSIX_SUCCESS(ret, "mlock()");
670*2c2f96dcSApple OSS Distributions 
671*2c2f96dcSApple OSS Distributions 	footprint_before = task_footprint();
672*2c2f96dcSApple OSS Distributions 
673*2c2f96dcSApple OSS Distributions 	ret = madvise((char *)(uintptr_t)vmaddr,
674*2c2f96dcSApple OSS Distributions 	    vmsize1,
675*2c2f96dcSApple OSS Distributions 	    MADV_FREE_REUSABLE);
676*2c2f96dcSApple OSS Distributions 	T_QUIET;
677*2c2f96dcSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ret, "madvise()");
678*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
679*2c2f96dcSApple OSS Distributions 		goto done;
680*2c2f96dcSApple OSS Distributions 	}
681*2c2f96dcSApple OSS Distributions 
682*2c2f96dcSApple OSS Distributions 	footprint_after = task_footprint();
683*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(footprint_after, footprint_before - 2 * vmsize1, NULL);
684*2c2f96dcSApple OSS Distributions 
685*2c2f96dcSApple OSS Distributions 	kr = get_reusable_size(&reusable_after);
686*2c2f96dcSApple OSS Distributions 	if (kr) {
687*2c2f96dcSApple OSS Distributions 		goto done;
688*2c2f96dcSApple OSS Distributions 	}
689*2c2f96dcSApple OSS Distributions 	reusable_expected = 2ULL * vmsize1 + reusable_before;
690*2c2f96dcSApple OSS Distributions 	T_EXPECT_EQ(reusable_after, reusable_expected, "actual=%lld expected %lld",
691*2c2f96dcSApple OSS Distributions 	    reusable_after, reusable_expected);
692*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
693*2c2f96dcSApple OSS Distributions 		goto done;
694*2c2f96dcSApple OSS Distributions 	}
695*2c2f96dcSApple OSS Distributions 
696*2c2f96dcSApple OSS Distributions done:
697*2c2f96dcSApple OSS Distributions 	if (vmaddr != 0) {
698*2c2f96dcSApple OSS Distributions 		vm_deallocate(mach_task_self(), vmaddr, vmsize);
699*2c2f96dcSApple OSS Distributions 		vmaddr = 0;
700*2c2f96dcSApple OSS Distributions 	}
701*2c2f96dcSApple OSS Distributions 	if (vmaddr2 != 0) {
702*2c2f96dcSApple OSS Distributions 		vm_deallocate(mach_task_self(), vmaddr2, vmsize);
703*2c2f96dcSApple OSS Distributions 		vmaddr2 = 0;
704*2c2f96dcSApple OSS Distributions 	}
705*2c2f96dcSApple OSS Distributions }
706*2c2f96dcSApple OSS Distributions 
707*2c2f96dcSApple OSS Distributions T_DECL(madvise_purgeable_can_reuse, "test madvise purgeable can reuse for \
708*2c2f96dcSApple OSS Distributions     rdar://problem/37476183 Preview Footprint memory regressions ~100MB \
709*2c2f96dcSApple OSS Distributions     [ purgeable_malloc became eligible for reuse ]",
710*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
711*2c2f96dcSApple OSS Distributions {
712*2c2f96dcSApple OSS Distributions #if defined(__x86_64__) || defined(__i386__)
713*2c2f96dcSApple OSS Distributions 	if (COMM_PAGE_READ(uint64_t, CPU_CAPABILITIES64) & kIsTranslated) {
714*2c2f96dcSApple OSS Distributions 		T_SKIP("madvise reusable is not supported under Rosetta translation. Skipping.)");
715*2c2f96dcSApple OSS Distributions 	}
716*2c2f96dcSApple OSS Distributions #endif /* defined(__x86_64__) || defined(__i386__) */
717*2c2f96dcSApple OSS Distributions 	vm_address_t            vmaddr = 0;
718*2c2f96dcSApple OSS Distributions 	vm_size_t               vmsize;
719*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
720*2c2f96dcSApple OSS Distributions 	char                    *cp;
721*2c2f96dcSApple OSS Distributions 	int                     ret;
722*2c2f96dcSApple OSS Distributions 
723*2c2f96dcSApple OSS Distributions 	vmsize = 10 * 1024 * 1024; /* 10MB */
724*2c2f96dcSApple OSS Distributions 	kr = vm_allocate(mach_task_self(),
725*2c2f96dcSApple OSS Distributions 	    &vmaddr,
726*2c2f96dcSApple OSS Distributions 	    vmsize,
727*2c2f96dcSApple OSS Distributions 	    (VM_FLAGS_ANYWHERE |
728*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_PURGABLE |
729*2c2f96dcSApple OSS Distributions 	    VM_MAKE_TAG(VM_MEMORY_MALLOC)));
730*2c2f96dcSApple OSS Distributions 	T_QUIET;
731*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "vm_allocate()");
732*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
733*2c2f96dcSApple OSS Distributions 		goto done;
734*2c2f96dcSApple OSS Distributions 	}
735*2c2f96dcSApple OSS Distributions 
736*2c2f96dcSApple OSS Distributions 	for (cp = (char *)(uintptr_t)vmaddr;
737*2c2f96dcSApple OSS Distributions 	    cp < (char *)(uintptr_t)(vmaddr + vmsize);
738*2c2f96dcSApple OSS Distributions 	    cp++) {
739*2c2f96dcSApple OSS Distributions 		*cp = 'x';
740*2c2f96dcSApple OSS Distributions 	}
741*2c2f96dcSApple OSS Distributions 
742*2c2f96dcSApple OSS Distributions 	ret = madvise((char *)(uintptr_t)vmaddr,
743*2c2f96dcSApple OSS Distributions 	    vmsize,
744*2c2f96dcSApple OSS Distributions 	    MADV_CAN_REUSE);
745*2c2f96dcSApple OSS Distributions 	T_QUIET;
746*2c2f96dcSApple OSS Distributions 	T_EXPECT_TRUE(((ret == -1) && (errno == EINVAL)), "madvise(): purgeable vm can't be adviced to reuse");
747*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
748*2c2f96dcSApple OSS Distributions 		goto done;
749*2c2f96dcSApple OSS Distributions 	}
750*2c2f96dcSApple OSS Distributions 
751*2c2f96dcSApple OSS Distributions done:
752*2c2f96dcSApple OSS Distributions 	if (vmaddr != 0) {
753*2c2f96dcSApple OSS Distributions 		vm_deallocate(mach_task_self(), vmaddr, vmsize);
754*2c2f96dcSApple OSS Distributions 		vmaddr = 0;
755*2c2f96dcSApple OSS Distributions 	}
756*2c2f96dcSApple OSS Distributions }
757*2c2f96dcSApple OSS Distributions 
758*2c2f96dcSApple OSS Distributions static bool
validate_memory_is_zero(vm_address_t start,vm_size_t vmsize,vm_address_t * non_zero_addr)759*2c2f96dcSApple OSS Distributions validate_memory_is_zero(
760*2c2f96dcSApple OSS Distributions 	vm_address_t            start,
761*2c2f96dcSApple OSS Distributions 	vm_size_t               vmsize,
762*2c2f96dcSApple OSS Distributions 	vm_address_t           *non_zero_addr)
763*2c2f96dcSApple OSS Distributions {
764*2c2f96dcSApple OSS Distributions 	for (vm_size_t sz = 0; sz < vmsize; sz += sizeof(uint64_t)) {
765*2c2f96dcSApple OSS Distributions 		vm_address_t addr = start + sz;
766*2c2f96dcSApple OSS Distributions 
767*2c2f96dcSApple OSS Distributions 		if (*(uint64_t *)(addr) != 0) {
768*2c2f96dcSApple OSS Distributions 			*non_zero_addr = addr;
769*2c2f96dcSApple OSS Distributions 			return false;
770*2c2f96dcSApple OSS Distributions 		}
771*2c2f96dcSApple OSS Distributions 	}
772*2c2f96dcSApple OSS Distributions 	return true;
773*2c2f96dcSApple OSS Distributions }
774*2c2f96dcSApple OSS Distributions 
775*2c2f96dcSApple OSS Distributions T_DECL(madvise_zero, "test madvise zero")
776*2c2f96dcSApple OSS Distributions {
777*2c2f96dcSApple OSS Distributions 	vm_address_t            vmaddr = 0;
778*2c2f96dcSApple OSS Distributions 	vm_size_t               vmsize = PAGE_SIZE * 3;
779*2c2f96dcSApple OSS Distributions 	vm_address_t            non_zero_addr = 0;
780*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
781*2c2f96dcSApple OSS Distributions 	int                     ret;
782*2c2f96dcSApple OSS Distributions 	unsigned char           vec;
783*2c2f96dcSApple OSS Distributions 
784*2c2f96dcSApple OSS Distributions 	kr = vm_allocate(mach_task_self(),
785*2c2f96dcSApple OSS Distributions 	    &vmaddr,
786*2c2f96dcSApple OSS Distributions 	    vmsize,
787*2c2f96dcSApple OSS Distributions 	    (VM_FLAGS_ANYWHERE |
788*2c2f96dcSApple OSS Distributions 	    VM_MAKE_TAG(VM_MEMORY_MALLOC)));
789*2c2f96dcSApple OSS Distributions 	T_QUIET;
790*2c2f96dcSApple OSS Distributions 	T_EXPECT_MACH_SUCCESS(kr, "vm_allocate()");
791*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
792*2c2f96dcSApple OSS Distributions 		goto done;
793*2c2f96dcSApple OSS Distributions 	}
794*2c2f96dcSApple OSS Distributions 
795*2c2f96dcSApple OSS Distributions 	memset((void *)vmaddr, 'A', vmsize);
796*2c2f96dcSApple OSS Distributions 	ret = madvise(vmaddr, vmsize, MADV_FREE_REUSABLE);
797*2c2f96dcSApple OSS Distributions 	T_QUIET;
798*2c2f96dcSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ret, "madvise(MADV_FREE_REUSABLE)");
799*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
800*2c2f96dcSApple OSS Distributions 		goto done;
801*2c2f96dcSApple OSS Distributions 	}
802*2c2f96dcSApple OSS Distributions 
803*2c2f96dcSApple OSS Distributions 	memset((void *)vmaddr, 'B', PAGE_SIZE);
804*2c2f96dcSApple OSS Distributions 	ret = madvise(vmaddr, vmsize, MADV_ZERO);
805*2c2f96dcSApple OSS Distributions 	T_QUIET;
806*2c2f96dcSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ret, "madvise(MADV_ZERO)");
807*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
808*2c2f96dcSApple OSS Distributions 		goto done;
809*2c2f96dcSApple OSS Distributions 	}
810*2c2f96dcSApple OSS Distributions 
811*2c2f96dcSApple OSS Distributions 	T_QUIET;
812*2c2f96dcSApple OSS Distributions 	T_EXPECT_EQ(validate_memory_is_zero(vmaddr, vmsize, &non_zero_addr), true,
813*2c2f96dcSApple OSS Distributions 	    "madvise(%p, %llu, MADV_ZERO) returned non zero mem at %p",
814*2c2f96dcSApple OSS Distributions 	    (void *)vmaddr, vmsize, (void *)non_zero_addr);
815*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
816*2c2f96dcSApple OSS Distributions 		goto done;
817*2c2f96dcSApple OSS Distributions 	}
818*2c2f96dcSApple OSS Distributions 
819*2c2f96dcSApple OSS Distributions 	memset((void *)vmaddr, 'C', PAGE_SIZE);
820*2c2f96dcSApple OSS Distributions 	ret = madvise(vmaddr, vmsize, MADV_PAGEOUT);
821*2c2f96dcSApple OSS Distributions 	T_QUIET;
822*2c2f96dcSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ret, "madvise(MADV_PAGEOUT)");
823*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
824*2c2f96dcSApple OSS Distributions 		goto done;
825*2c2f96dcSApple OSS Distributions 	}
826*2c2f96dcSApple OSS Distributions 
827*2c2f96dcSApple OSS Distributions 	/* wait for the pages to be (asynchronously) compressed */
828*2c2f96dcSApple OSS Distributions 	T_QUIET; T_LOG("waiting for first page to be paged out");
829*2c2f96dcSApple OSS Distributions 	do {
830*2c2f96dcSApple OSS Distributions 		ret = mincore(vmaddr, 1, &vec);
831*2c2f96dcSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "mincore(1st)");
832*2c2f96dcSApple OSS Distributions 	} while (vec & MINCORE_INCORE);
833*2c2f96dcSApple OSS Distributions 	T_QUIET; T_LOG("waiting for last page to be paged out");
834*2c2f96dcSApple OSS Distributions 	do {
835*2c2f96dcSApple OSS Distributions 		ret = mincore((vmaddr + vmsize - 1), 1, (char *)&vec);
836*2c2f96dcSApple OSS Distributions 		T_QUIET; T_ASSERT_POSIX_SUCCESS(ret, "mincore(last)");
837*2c2f96dcSApple OSS Distributions 	} while (vec & MINCORE_INCORE);
838*2c2f96dcSApple OSS Distributions 
839*2c2f96dcSApple OSS Distributions 	ret = madvise(vmaddr, vmsize, MADV_ZERO);
840*2c2f96dcSApple OSS Distributions 	T_QUIET;
841*2c2f96dcSApple OSS Distributions 	T_EXPECT_POSIX_SUCCESS(ret, "madvise(MADV_ZERO)");
842*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
843*2c2f96dcSApple OSS Distributions 		goto done;
844*2c2f96dcSApple OSS Distributions 	}
845*2c2f96dcSApple OSS Distributions 	T_QUIET;
846*2c2f96dcSApple OSS Distributions 	T_EXPECT_EQ(validate_memory_is_zero(vmaddr, vmsize, &non_zero_addr), true,
847*2c2f96dcSApple OSS Distributions 	    "madvise(%p, %llu, MADV_ZERO) returned non zero mem at %p",
848*2c2f96dcSApple OSS Distributions 	    (void *)vmaddr, vmsize, (void *)non_zero_addr);
849*2c2f96dcSApple OSS Distributions 	if (T_RESULT == T_RESULT_FAIL) {
850*2c2f96dcSApple OSS Distributions 		goto done;
851*2c2f96dcSApple OSS Distributions 	}
852*2c2f96dcSApple OSS Distributions 
853*2c2f96dcSApple OSS Distributions done:
854*2c2f96dcSApple OSS Distributions 	if (vmaddr != 0) {
855*2c2f96dcSApple OSS Distributions 		vm_deallocate(mach_task_self(), vmaddr, vmsize);
856*2c2f96dcSApple OSS Distributions 		vmaddr = 0;
857*2c2f96dcSApple OSS Distributions 	}
858*2c2f96dcSApple OSS Distributions }
859*2c2f96dcSApple OSS Distributions 
860*2c2f96dcSApple OSS Distributions #define DEST_PATTERN 0xFEDCBA98
861*2c2f96dcSApple OSS Distributions 
862*2c2f96dcSApple OSS Distributions T_DECL(map_read_overwrite, "test overwriting vm map from other map - \
863*2c2f96dcSApple OSS Distributions     rdar://31075370",
864*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
865*2c2f96dcSApple OSS Distributions {
866*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
867*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr1, vmaddr2;
868*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize1, vmsize2;
869*2c2f96dcSApple OSS Distributions 	int                     *ip;
870*2c2f96dcSApple OSS Distributions 	int                     i;
871*2c2f96dcSApple OSS Distributions 
872*2c2f96dcSApple OSS Distributions 	vmaddr1 = 0;
873*2c2f96dcSApple OSS Distributions 	vmsize1 = 4 * 4096;
874*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
875*2c2f96dcSApple OSS Distributions 	    &vmaddr1,
876*2c2f96dcSApple OSS Distributions 	    vmsize1,
877*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE);
878*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
879*2c2f96dcSApple OSS Distributions 
880*2c2f96dcSApple OSS Distributions 	ip = (int *)(uintptr_t)vmaddr1;
881*2c2f96dcSApple OSS Distributions 	for (i = 0; i < vmsize1 / sizeof(*ip); i++) {
882*2c2f96dcSApple OSS Distributions 		ip[i] = i;
883*2c2f96dcSApple OSS Distributions 	}
884*2c2f96dcSApple OSS Distributions 
885*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
886*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
887*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
888*2c2f96dcSApple OSS Distributions 	    vmsize1,
889*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE);
890*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
891*2c2f96dcSApple OSS Distributions 
892*2c2f96dcSApple OSS Distributions 	ip = (int *)(uintptr_t)vmaddr2;
893*2c2f96dcSApple OSS Distributions 	for (i = 0; i < vmsize1 / sizeof(*ip); i++) {
894*2c2f96dcSApple OSS Distributions 		ip[i] = DEST_PATTERN;
895*2c2f96dcSApple OSS Distributions 	}
896*2c2f96dcSApple OSS Distributions 
897*2c2f96dcSApple OSS Distributions 	vmsize2 = vmsize1 - 2 * (sizeof(*ip));
898*2c2f96dcSApple OSS Distributions 	kr = mach_vm_read_overwrite(mach_task_self(),
899*2c2f96dcSApple OSS Distributions 	    vmaddr1 + sizeof(*ip),
900*2c2f96dcSApple OSS Distributions 	    vmsize2,
901*2c2f96dcSApple OSS Distributions 	    vmaddr2 + sizeof(*ip),
902*2c2f96dcSApple OSS Distributions 	    &vmsize2);
903*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_read_overwrite()");
904*2c2f96dcSApple OSS Distributions 
905*2c2f96dcSApple OSS Distributions 	ip = (int *)(uintptr_t)vmaddr2;
906*2c2f96dcSApple OSS Distributions 	for (i = 0; i < 1; i++) {
907*2c2f96dcSApple OSS Distributions 		T_QUIET;
908*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(ip[i], DEST_PATTERN, "vmaddr2[%d] = 0x%x instead of 0x%x",
909*2c2f96dcSApple OSS Distributions 		    i, ip[i], DEST_PATTERN);
910*2c2f96dcSApple OSS Distributions 	}
911*2c2f96dcSApple OSS Distributions 	for (; i < (vmsize1 - 2) / sizeof(*ip); i++) {
912*2c2f96dcSApple OSS Distributions 		T_QUIET;
913*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(ip[i], i, "vmaddr2[%d] = 0x%x instead of 0x%x",
914*2c2f96dcSApple OSS Distributions 		    i, ip[i], i);
915*2c2f96dcSApple OSS Distributions 	}
916*2c2f96dcSApple OSS Distributions 	for (; i < vmsize1 / sizeof(*ip); i++) {
917*2c2f96dcSApple OSS Distributions 		T_QUIET;
918*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(ip[i], DEST_PATTERN, "vmaddr2[%d] = 0x%x instead of 0x%x",
919*2c2f96dcSApple OSS Distributions 		    i, ip[i], DEST_PATTERN);
920*2c2f96dcSApple OSS Distributions 	}
921*2c2f96dcSApple OSS Distributions }
922*2c2f96dcSApple OSS Distributions 
923*2c2f96dcSApple OSS Distributions T_DECL(copy_none_use_pmap, "test copy-on-write remapping of COPY_NONE vm \
924*2c2f96dcSApple OSS Distributions     objects - rdar://35610377",
925*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
926*2c2f96dcSApple OSS Distributions {
927*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
928*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr1, vmaddr2, vmaddr3;
929*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize;
930*2c2f96dcSApple OSS Distributions 	vm_prot_t               curprot, maxprot;
931*2c2f96dcSApple OSS Distributions 
932*2c2f96dcSApple OSS Distributions 	vmsize = 32 * 1024 * 1024;
933*2c2f96dcSApple OSS Distributions 
934*2c2f96dcSApple OSS Distributions 	vmaddr1 = 0;
935*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
936*2c2f96dcSApple OSS Distributions 	    &vmaddr1,
937*2c2f96dcSApple OSS Distributions 	    vmsize,
938*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
939*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
940*2c2f96dcSApple OSS Distributions 
941*2c2f96dcSApple OSS Distributions 	memset((void *)(uintptr_t)vmaddr1, 'x', vmsize);
942*2c2f96dcSApple OSS Distributions 
943*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
944*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
945*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
946*2c2f96dcSApple OSS Distributions 	    vmsize,
947*2c2f96dcSApple OSS Distributions 	    0,                /* mask */
948*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
949*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
950*2c2f96dcSApple OSS Distributions 	    vmaddr1,
951*2c2f96dcSApple OSS Distributions 	    TRUE,                /* copy */
952*2c2f96dcSApple OSS Distributions 	    &curprot,
953*2c2f96dcSApple OSS Distributions 	    &maxprot,
954*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
955*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_remap() #1");
956*2c2f96dcSApple OSS Distributions 
957*2c2f96dcSApple OSS Distributions 	vmaddr3 = 0;
958*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
959*2c2f96dcSApple OSS Distributions 	    &vmaddr3,
960*2c2f96dcSApple OSS Distributions 	    vmsize,
961*2c2f96dcSApple OSS Distributions 	    0,                /* mask */
962*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
963*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
964*2c2f96dcSApple OSS Distributions 	    vmaddr2,
965*2c2f96dcSApple OSS Distributions 	    TRUE,                /* copy */
966*2c2f96dcSApple OSS Distributions 	    &curprot,
967*2c2f96dcSApple OSS Distributions 	    &maxprot,
968*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
969*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_remap() #2");
970*2c2f96dcSApple OSS Distributions }
971*2c2f96dcSApple OSS Distributions 
972*2c2f96dcSApple OSS Distributions T_DECL(purgable_deny, "test purgeable memory is not allowed to be converted to \
973*2c2f96dcSApple OSS Distributions     non-purgeable - rdar://31990033",
974*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
975*2c2f96dcSApple OSS Distributions {
976*2c2f96dcSApple OSS Distributions 	kern_return_t   kr;
977*2c2f96dcSApple OSS Distributions 	vm_address_t    vmaddr;
978*2c2f96dcSApple OSS Distributions 	vm_purgable_t   state;
979*2c2f96dcSApple OSS Distributions 
980*2c2f96dcSApple OSS Distributions 	vmaddr = 0;
981*2c2f96dcSApple OSS Distributions 	kr = vm_allocate(mach_task_self(), &vmaddr, 1,
982*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE | VM_FLAGS_PURGABLE);
983*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
984*2c2f96dcSApple OSS Distributions 
985*2c2f96dcSApple OSS Distributions 	state = VM_PURGABLE_DENY;
986*2c2f96dcSApple OSS Distributions 	kr = vm_purgable_control(mach_task_self(), vmaddr,
987*2c2f96dcSApple OSS Distributions 	    VM_PURGABLE_SET_STATE, &state);
988*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT,
989*2c2f96dcSApple OSS Distributions 	    "vm_purgable_control(VM_PURGABLE_DENY) -> 0x%x (%s)",
990*2c2f96dcSApple OSS Distributions 	    kr, mach_error_string(kr));
991*2c2f96dcSApple OSS Distributions 
992*2c2f96dcSApple OSS Distributions 	kr = vm_deallocate(mach_task_self(), vmaddr, 1);
993*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_deallocate()");
994*2c2f96dcSApple OSS Distributions }
995*2c2f96dcSApple OSS Distributions 
996*2c2f96dcSApple OSS Distributions #define VMSIZE 0x10000
997*2c2f96dcSApple OSS Distributions 
998*2c2f96dcSApple OSS Distributions T_DECL(vm_remap_zero, "test vm map of zero size - rdar://33114981",
999*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
1000*2c2f96dcSApple OSS Distributions {
1001*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
1002*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr1, vmaddr2;
1003*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize;
1004*2c2f96dcSApple OSS Distributions 	vm_prot_t               curprot, maxprot;
1005*2c2f96dcSApple OSS Distributions 
1006*2c2f96dcSApple OSS Distributions 	vmaddr1 = 0;
1007*2c2f96dcSApple OSS Distributions 	vmsize = VMSIZE;
1008*2c2f96dcSApple OSS Distributions 	kr = mach_vm_allocate(mach_task_self(),
1009*2c2f96dcSApple OSS Distributions 	    &vmaddr1,
1010*2c2f96dcSApple OSS Distributions 	    vmsize,
1011*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE);
1012*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_allocate()");
1013*2c2f96dcSApple OSS Distributions 
1014*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
1015*2c2f96dcSApple OSS Distributions 	vmsize = 0;
1016*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
1017*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
1018*2c2f96dcSApple OSS Distributions 	    vmsize,
1019*2c2f96dcSApple OSS Distributions 	    0,
1020*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1021*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1022*2c2f96dcSApple OSS Distributions 	    vmaddr1,
1023*2c2f96dcSApple OSS Distributions 	    FALSE,
1024*2c2f96dcSApple OSS Distributions 	    &curprot,
1025*2c2f96dcSApple OSS Distributions 	    &maxprot,
1026*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1027*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT, "vm_remap(size=0x%llx) 0x%x (%s)",
1028*2c2f96dcSApple OSS Distributions 	    vmsize, kr, mach_error_string(kr));
1029*2c2f96dcSApple OSS Distributions 
1030*2c2f96dcSApple OSS Distributions 	vmaddr2 = 0;
1031*2c2f96dcSApple OSS Distributions 	vmsize = (mach_vm_size_t)-2;
1032*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
1033*2c2f96dcSApple OSS Distributions 	    &vmaddr2,
1034*2c2f96dcSApple OSS Distributions 	    vmsize,
1035*2c2f96dcSApple OSS Distributions 	    0,
1036*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1037*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1038*2c2f96dcSApple OSS Distributions 	    vmaddr1,
1039*2c2f96dcSApple OSS Distributions 	    FALSE,
1040*2c2f96dcSApple OSS Distributions 	    &curprot,
1041*2c2f96dcSApple OSS Distributions 	    &maxprot,
1042*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1043*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_INVALID_ARGUMENT, "vm_remap(size=0x%llx) 0x%x (%s)",
1044*2c2f96dcSApple OSS Distributions 	    vmsize, kr, mach_error_string(kr));
1045*2c2f96dcSApple OSS Distributions }
1046*2c2f96dcSApple OSS Distributions 
1047*2c2f96dcSApple OSS Distributions extern int __shared_region_check_np(uint64_t *);
1048*2c2f96dcSApple OSS Distributions 
1049*2c2f96dcSApple OSS Distributions T_DECL(nested_pmap_trigger, "nested pmap should only be triggered from kernel \
1050*2c2f96dcSApple OSS Distributions     - rdar://problem/41481703",
1051*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
1052*2c2f96dcSApple OSS Distributions {
1053*2c2f96dcSApple OSS Distributions 	int                     ret;
1054*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
1055*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       sr_start;
1056*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize;
1057*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr;
1058*2c2f96dcSApple OSS Distributions 	mach_port_t             mem_entry;
1059*2c2f96dcSApple OSS Distributions 
1060*2c2f96dcSApple OSS Distributions 	ret = __shared_region_check_np(&sr_start);
1061*2c2f96dcSApple OSS Distributions 	if (ret != 0) {
1062*2c2f96dcSApple OSS Distributions 		int saved_errno;
1063*2c2f96dcSApple OSS Distributions 		saved_errno = errno;
1064*2c2f96dcSApple OSS Distributions 
1065*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(saved_errno, ENOMEM, "__shared_region_check_np() %d (%s)",
1066*2c2f96dcSApple OSS Distributions 		    saved_errno, strerror(saved_errno));
1067*2c2f96dcSApple OSS Distributions 		T_END;
1068*2c2f96dcSApple OSS Distributions 	}
1069*2c2f96dcSApple OSS Distributions 
1070*2c2f96dcSApple OSS Distributions 	vmsize = PAGE_SIZE;
1071*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
1072*2c2f96dcSApple OSS Distributions 	    &vmsize,
1073*2c2f96dcSApple OSS Distributions 	    sr_start,
1074*2c2f96dcSApple OSS Distributions 	    MAP_MEM_VM_SHARE | VM_PROT_READ,
1075*2c2f96dcSApple OSS Distributions 	    &mem_entry,
1076*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
1077*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "make_memory_entry(0x%llx)", sr_start);
1078*2c2f96dcSApple OSS Distributions 
1079*2c2f96dcSApple OSS Distributions 	vmaddr = 0;
1080*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
1081*2c2f96dcSApple OSS Distributions 	    &vmaddr,
1082*2c2f96dcSApple OSS Distributions 	    vmsize,
1083*2c2f96dcSApple OSS Distributions 	    0,
1084*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1085*2c2f96dcSApple OSS Distributions 	    mem_entry,
1086*2c2f96dcSApple OSS Distributions 	    0,
1087*2c2f96dcSApple OSS Distributions 	    FALSE,
1088*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ,
1089*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ,
1090*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1091*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1092*2c2f96dcSApple OSS Distributions }
1093*2c2f96dcSApple OSS Distributions 
1094*2c2f96dcSApple OSS Distributions static const char *prot_str[] = { "---", "r--", "-w-", "rw-", "--x", "r-x", "-wx", "rwx" };
1095*2c2f96dcSApple OSS Distributions static const char *share_mode_str[] = { "---", "COW", "PRIVATE", "EMPTY", "SHARED", "TRUESHARED", "PRIVATE_ALIASED", "SHARED_ALIASED", "LARGE_PAGE" };
1096*2c2f96dcSApple OSS Distributions 
1097*2c2f96dcSApple OSS Distributions T_DECL(shared_region_share_writable, "sharing a writable mapping of the shared region shoudl not give write access to shared region - rdar://problem/74469953",
1098*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
1099*2c2f96dcSApple OSS Distributions {
1100*2c2f96dcSApple OSS Distributions 	int ret;
1101*2c2f96dcSApple OSS Distributions 	uint64_t sr_start;
1102*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
1103*2c2f96dcSApple OSS Distributions 	mach_vm_address_t address, tmp_address, remap_address;
1104*2c2f96dcSApple OSS Distributions 	mach_vm_size_t size, tmp_size, remap_size;
1105*2c2f96dcSApple OSS Distributions 	uint32_t depth;
1106*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t count;
1107*2c2f96dcSApple OSS Distributions 	vm_region_submap_info_data_64_t info;
1108*2c2f96dcSApple OSS Distributions 	vm_prot_t cur_prot, max_prot;
1109*2c2f96dcSApple OSS Distributions 	uint32_t before, after, remap;
1110*2c2f96dcSApple OSS Distributions 	mach_port_t mem_entry;
1111*2c2f96dcSApple OSS Distributions 
1112*2c2f96dcSApple OSS Distributions 	ret = __shared_region_check_np(&sr_start);
1113*2c2f96dcSApple OSS Distributions 	if (ret != 0) {
1114*2c2f96dcSApple OSS Distributions 		int saved_errno;
1115*2c2f96dcSApple OSS Distributions 		saved_errno = errno;
1116*2c2f96dcSApple OSS Distributions 
1117*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(saved_errno, ENOMEM, "__shared_region_check_np() %d (%s)",
1118*2c2f96dcSApple OSS Distributions 		    saved_errno, strerror(saved_errno));
1119*2c2f96dcSApple OSS Distributions 		T_END;
1120*2c2f96dcSApple OSS Distributions 	}
1121*2c2f96dcSApple OSS Distributions 	T_LOG("SHARED_REGION_BASE 0x%llx", SHARED_REGION_BASE);
1122*2c2f96dcSApple OSS Distributions 	T_LOG("SHARED_REGION_SIZE 0x%llx", SHARED_REGION_SIZE);
1123*2c2f96dcSApple OSS Distributions 	T_LOG("shared region starts at 0x%llx", sr_start);
1124*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GE(sr_start, SHARED_REGION_BASE,
1125*2c2f96dcSApple OSS Distributions 	    "shared region starts below BASE");
1126*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_LT(sr_start, SHARED_REGION_BASE + SHARED_REGION_SIZE,
1127*2c2f96dcSApple OSS Distributions 	    "shared region starts above BASE+SIZE");
1128*2c2f96dcSApple OSS Distributions 
1129*2c2f96dcSApple OSS Distributions 	/*
1130*2c2f96dcSApple OSS Distributions 	 * Step 1 - check that one can not get write access to a read-only
1131*2c2f96dcSApple OSS Distributions 	 * mapping in the shared region.
1132*2c2f96dcSApple OSS Distributions 	 */
1133*2c2f96dcSApple OSS Distributions 	size = 0;
1134*2c2f96dcSApple OSS Distributions 	for (address = SHARED_REGION_BASE;
1135*2c2f96dcSApple OSS Distributions 	    address < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1136*2c2f96dcSApple OSS Distributions 	    address += size) {
1137*2c2f96dcSApple OSS Distributions 		size = 0;
1138*2c2f96dcSApple OSS Distributions 		depth = 99;
1139*2c2f96dcSApple OSS Distributions 		count = VM_REGION_SUBMAP_INFO_COUNT_64;
1140*2c2f96dcSApple OSS Distributions 		kr = mach_vm_region_recurse(mach_task_self(),
1141*2c2f96dcSApple OSS Distributions 		    &address,
1142*2c2f96dcSApple OSS Distributions 		    &size,
1143*2c2f96dcSApple OSS Distributions 		    &depth,
1144*2c2f96dcSApple OSS Distributions 		    (vm_region_recurse_info_t)&info,
1145*2c2f96dcSApple OSS Distributions 		    &count);
1146*2c2f96dcSApple OSS Distributions 		T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_region_recurse()");
1147*2c2f96dcSApple OSS Distributions 		if (kr == KERN_INVALID_ADDRESS) {
1148*2c2f96dcSApple OSS Distributions 			T_SKIP("could not find read-only nested mapping");
1149*2c2f96dcSApple OSS Distributions 			T_END;
1150*2c2f96dcSApple OSS Distributions 		}
1151*2c2f96dcSApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1152*2c2f96dcSApple OSS Distributions 		T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1153*2c2f96dcSApple OSS Distributions 		    address, address + size, depth,
1154*2c2f96dcSApple OSS Distributions 		    prot_str[info.protection],
1155*2c2f96dcSApple OSS Distributions 		    prot_str[info.max_protection],
1156*2c2f96dcSApple OSS Distributions 		    share_mode_str[info.share_mode],
1157*2c2f96dcSApple OSS Distributions 		    info.object_id);
1158*2c2f96dcSApple OSS Distributions 		if (depth > 0 &&
1159*2c2f96dcSApple OSS Distributions 		    (info.protection == VM_PROT_READ) &&
1160*2c2f96dcSApple OSS Distributions 		    (info.max_protection == VM_PROT_READ)) {
1161*2c2f96dcSApple OSS Distributions 			/* nested and read-only: bingo! */
1162*2c2f96dcSApple OSS Distributions 			break;
1163*2c2f96dcSApple OSS Distributions 		}
1164*2c2f96dcSApple OSS Distributions 	}
1165*2c2f96dcSApple OSS Distributions 	if (address >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1166*2c2f96dcSApple OSS Distributions 		T_SKIP("could not find read-only nested mapping");
1167*2c2f96dcSApple OSS Distributions 		T_END;
1168*2c2f96dcSApple OSS Distributions 	}
1169*2c2f96dcSApple OSS Distributions 
1170*2c2f96dcSApple OSS Distributions 	/* test vm_remap() of RO */
1171*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1172*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1173*2c2f96dcSApple OSS Distributions 	remap_size = size;
1174*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
1175*2c2f96dcSApple OSS Distributions 	    &remap_address,
1176*2c2f96dcSApple OSS Distributions 	    remap_size,
1177*2c2f96dcSApple OSS Distributions 	    0,
1178*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
1179*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1180*2c2f96dcSApple OSS Distributions 	    address,
1181*2c2f96dcSApple OSS Distributions 	    FALSE,
1182*2c2f96dcSApple OSS Distributions 	    &cur_prot,
1183*2c2f96dcSApple OSS Distributions 	    &max_prot,
1184*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1185*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap()");
1186*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(cur_prot, VM_PROT_READ, "cur_prot is read-only");
1187*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(max_prot, VM_PROT_READ, "max_prot is read-only");
1188*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1189*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1190*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1191*2c2f96dcSApple OSS Distributions 	depth = 99;
1192*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1193*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1194*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1195*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1196*2c2f96dcSApple OSS Distributions 	    &depth,
1197*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1198*2c2f96dcSApple OSS Distributions 	    &count);
1199*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1200*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1201*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1202*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1203*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1204*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1205*2c2f96dcSApple OSS Distributions 	    info.object_id);
1206*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1207*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1208*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1209*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1210*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1211*2c2f96dcSApple OSS Distributions 	/* check that new mapping is read-only */
1212*2c2f96dcSApple OSS Distributions 	tmp_address = remap_address;
1213*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1214*2c2f96dcSApple OSS Distributions 	depth = 99;
1215*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1216*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1217*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1218*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1219*2c2f96dcSApple OSS Distributions 	    &depth,
1220*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1221*2c2f96dcSApple OSS Distributions 	    &count);
1222*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1223*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1224*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1225*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1226*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1227*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1228*2c2f96dcSApple OSS Distributions 	    info.object_id);
1229*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, remap_address, "address hasn't changed");
1230*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1231*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "new cur_prot read-only");
1232*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "new max_prot read-only");
1233*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1234*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1235*2c2f96dcSApple OSS Distributions // this would crash if actually read-only:
1236*2c2f96dcSApple OSS Distributions //	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1237*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1238*2c2f96dcSApple OSS Distributions 	T_LOG("vm_remap(): 0x%llx 0x%x -> 0x%x", address, before, after);
1239*2c2f96dcSApple OSS Distributions //	*(uint32_t *)(uintptr_t)remap_address = before;
1240*2c2f96dcSApple OSS Distributions 	if (before != after) {
1241*2c2f96dcSApple OSS Distributions 		T_FAIL("vm_remap() bypassed copy-on-write");
1242*2c2f96dcSApple OSS Distributions 	} else {
1243*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap() did not bypass copy-on-write");
1244*2c2f96dcSApple OSS Distributions 	}
1245*2c2f96dcSApple OSS Distributions 	/* cleanup */
1246*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1247*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1248*2c2f96dcSApple OSS Distributions 	T_PASS("vm_remap() read-only");
1249*2c2f96dcSApple OSS Distributions 
1250*2c2f96dcSApple OSS Distributions #if defined(VM_MEMORY_ROSETTA)
1251*2c2f96dcSApple OSS Distributions 	if (dlsym(RTLD_DEFAULT, "mach_vm_remap_new") == NULL) {
1252*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap_new() is not present");
1253*2c2f96dcSApple OSS Distributions 		goto skip_vm_remap_new_ro;
1254*2c2f96dcSApple OSS Distributions 	}
1255*2c2f96dcSApple OSS Distributions 	/* test vm_remap_new() of RO */
1256*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1257*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1258*2c2f96dcSApple OSS Distributions 	remap_size = size;
1259*2c2f96dcSApple OSS Distributions 	cur_prot = VM_PROT_READ | VM_PROT_WRITE;
1260*2c2f96dcSApple OSS Distributions 	max_prot = VM_PROT_READ | VM_PROT_WRITE;
1261*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap_new(mach_task_self(),
1262*2c2f96dcSApple OSS Distributions 	    &remap_address,
1263*2c2f96dcSApple OSS Distributions 	    remap_size,
1264*2c2f96dcSApple OSS Distributions 	    0,
1265*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1266*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1267*2c2f96dcSApple OSS Distributions 	    address,
1268*2c2f96dcSApple OSS Distributions 	    FALSE,
1269*2c2f96dcSApple OSS Distributions 	    &cur_prot,
1270*2c2f96dcSApple OSS Distributions 	    &max_prot,
1271*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1272*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_remap_new()");
1273*2c2f96dcSApple OSS Distributions 	if (kr == KERN_PROTECTION_FAILURE) {
1274*2c2f96dcSApple OSS Distributions 		/* wrong but not a security issue... */
1275*2c2f96dcSApple OSS Distributions 		goto skip_vm_remap_new_ro;
1276*2c2f96dcSApple OSS Distributions 	}
1277*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap_new()");
1278*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1279*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1280*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1281*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1282*2c2f96dcSApple OSS Distributions 	T_LOG("vm_remap_new(): 0x%llx 0x%x -> 0x%x", address, before, after);
1283*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1284*2c2f96dcSApple OSS Distributions 	if (before != after) {
1285*2c2f96dcSApple OSS Distributions 		T_FAIL("vm_remap_new() bypassed copy-on-write");
1286*2c2f96dcSApple OSS Distributions 	} else {
1287*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap_new() did not bypass copy-on-write");
1288*2c2f96dcSApple OSS Distributions 	}
1289*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1290*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1291*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1292*2c2f96dcSApple OSS Distributions 	depth = 99;
1293*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1294*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1295*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1296*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1297*2c2f96dcSApple OSS Distributions 	    &depth,
1298*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1299*2c2f96dcSApple OSS Distributions 	    &count);
1300*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1301*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1302*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1303*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1304*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1305*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1306*2c2f96dcSApple OSS Distributions 	    info.object_id);
1307*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1308*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1309*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1310*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1311*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1312*2c2f96dcSApple OSS Distributions 	T_PASS("vm_remap_new() read-only");
1313*2c2f96dcSApple OSS Distributions skip_vm_remap_new_ro:
1314*2c2f96dcSApple OSS Distributions #else /* defined(VM_MEMORY_ROSETTA) */
1315*2c2f96dcSApple OSS Distributions 	/* pre-BigSur SDK: no vm_remap_new() */
1316*2c2f96dcSApple OSS Distributions 	T_LOG("No vm_remap_new() to test");
1317*2c2f96dcSApple OSS Distributions #endif /* defined(VM_MEMORY_ROSETTA) */
1318*2c2f96dcSApple OSS Distributions 
1319*2c2f96dcSApple OSS Distributions 	/* test mach_make_memory_entry_64(VM_SHARE) of RO */
1320*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1321*2c2f96dcSApple OSS Distributions 	remap_size = size;
1322*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
1323*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
1324*2c2f96dcSApple OSS Distributions 	    &remap_size,
1325*2c2f96dcSApple OSS Distributions 	    address,
1326*2c2f96dcSApple OSS Distributions 	    MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
1327*2c2f96dcSApple OSS Distributions 	    &mem_entry,
1328*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
1329*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1330*2c2f96dcSApple OSS Distributions 	if (kr == KERN_PROTECTION_FAILURE) {
1331*2c2f96dcSApple OSS Distributions 		/* wrong but not a security issue... */
1332*2c2f96dcSApple OSS Distributions 		goto skip_mem_entry_vm_share_ro;
1333*2c2f96dcSApple OSS Distributions 	}
1334*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1335*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1336*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
1337*2c2f96dcSApple OSS Distributions 	    &remap_address,
1338*2c2f96dcSApple OSS Distributions 	    remap_size,
1339*2c2f96dcSApple OSS Distributions 	    0,              /* mask */
1340*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1341*2c2f96dcSApple OSS Distributions 	    mem_entry,
1342*2c2f96dcSApple OSS Distributions 	    0,              /* offset */
1343*2c2f96dcSApple OSS Distributions 	    FALSE,              /* copy */
1344*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1345*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1346*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1347*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1348*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1349*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1350*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1351*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1352*2c2f96dcSApple OSS Distributions 	T_LOG("mem_entry(VM_SHARE): 0x%llx 0x%x -> 0x%x", address, before, after);
1353*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1354*2c2f96dcSApple OSS Distributions 	if (before != after) {
1355*2c2f96dcSApple OSS Distributions 		T_FAIL("mem_entry(VM_SHARE) bypassed copy-on-write");
1356*2c2f96dcSApple OSS Distributions 	} else {
1357*2c2f96dcSApple OSS Distributions 		T_PASS("mem_entry(VM_SHARE) did not bypass copy-on-write");
1358*2c2f96dcSApple OSS Distributions 	}
1359*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1360*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1361*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1362*2c2f96dcSApple OSS Distributions 	depth = 99;
1363*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1364*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1365*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1366*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1367*2c2f96dcSApple OSS Distributions 	    &depth,
1368*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1369*2c2f96dcSApple OSS Distributions 	    &count);
1370*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1371*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1372*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1373*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1374*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1375*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1376*2c2f96dcSApple OSS Distributions 	    info.object_id);
1377*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1378*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1379*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1380*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1381*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1382*2c2f96dcSApple OSS Distributions 	/* check that new mapping is a copy */
1383*2c2f96dcSApple OSS Distributions 	tmp_address = remap_address;
1384*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1385*2c2f96dcSApple OSS Distributions 	depth = 99;
1386*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1387*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1388*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1389*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1390*2c2f96dcSApple OSS Distributions 	    &depth,
1391*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1392*2c2f96dcSApple OSS Distributions 	    &count);
1393*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1394*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1395*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1396*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1397*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1398*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1399*2c2f96dcSApple OSS Distributions 	    info.object_id);
1400*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, remap_address, "address hasn't changed");
1401*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1402*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(depth, 0, "new mapping is unnested");
1403*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "new cur_prot read-only");
1404*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "new max_prot read-only");
1405*2c2f96dcSApple OSS Distributions 	/* cleanup */
1406*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1407*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1408*2c2f96dcSApple OSS Distributions 	T_PASS("mem_entry(VM_SHARE) read-only");
1409*2c2f96dcSApple OSS Distributions skip_mem_entry_vm_share_ro:
1410*2c2f96dcSApple OSS Distributions 
1411*2c2f96dcSApple OSS Distributions 	/* test mach_make_memory_entry_64() of RO */
1412*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1413*2c2f96dcSApple OSS Distributions 	remap_size = size;
1414*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
1415*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
1416*2c2f96dcSApple OSS Distributions 	    &remap_size,
1417*2c2f96dcSApple OSS Distributions 	    address,
1418*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1419*2c2f96dcSApple OSS Distributions 	    &mem_entry,
1420*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
1421*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(kr, KERN_PROTECTION_FAILURE, "mach_make_memory_entry_64()");
1422*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1423*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1424*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1425*2c2f96dcSApple OSS Distributions 	depth = 99;
1426*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1427*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1428*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1429*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1430*2c2f96dcSApple OSS Distributions 	    &depth,
1431*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1432*2c2f96dcSApple OSS Distributions 	    &count);
1433*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1434*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1435*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1436*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1437*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1438*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1439*2c2f96dcSApple OSS Distributions 	    info.object_id);
1440*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1441*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1442*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1443*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_READ, "cur_prot still read-only");
1444*2c2f96dcSApple OSS Distributions 	if (depth > 0) {
1445*2c2f96dcSApple OSS Distributions 		T_QUIET; T_ASSERT_EQ(info.max_protection, VM_PROT_READ, "max_prot still read-only");
1446*2c2f96dcSApple OSS Distributions 	}
1447*2c2f96dcSApple OSS Distributions 	T_PASS("mem_entry() read-only");
1448*2c2f96dcSApple OSS Distributions 
1449*2c2f96dcSApple OSS Distributions 
1450*2c2f96dcSApple OSS Distributions 	/*
1451*2c2f96dcSApple OSS Distributions 	 * Step 2 - check that one can not share write access with a writable
1452*2c2f96dcSApple OSS Distributions 	 * mapping in the shared region.
1453*2c2f96dcSApple OSS Distributions 	 */
1454*2c2f96dcSApple OSS Distributions 	size = 0;
1455*2c2f96dcSApple OSS Distributions 	for (address = SHARED_REGION_BASE;
1456*2c2f96dcSApple OSS Distributions 	    address < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1457*2c2f96dcSApple OSS Distributions 	    address += size) {
1458*2c2f96dcSApple OSS Distributions 		size = 0;
1459*2c2f96dcSApple OSS Distributions 		depth = 99;
1460*2c2f96dcSApple OSS Distributions 		count = VM_REGION_SUBMAP_INFO_COUNT_64;
1461*2c2f96dcSApple OSS Distributions 		kr = mach_vm_region_recurse(mach_task_self(),
1462*2c2f96dcSApple OSS Distributions 		    &address,
1463*2c2f96dcSApple OSS Distributions 		    &size,
1464*2c2f96dcSApple OSS Distributions 		    &depth,
1465*2c2f96dcSApple OSS Distributions 		    (vm_region_recurse_info_t)&info,
1466*2c2f96dcSApple OSS Distributions 		    &count);
1467*2c2f96dcSApple OSS Distributions 		T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_region_recurse()");
1468*2c2f96dcSApple OSS Distributions 		if (kr == KERN_INVALID_ADDRESS) {
1469*2c2f96dcSApple OSS Distributions 			T_SKIP("could not find writable nested mapping");
1470*2c2f96dcSApple OSS Distributions 			T_END;
1471*2c2f96dcSApple OSS Distributions 		}
1472*2c2f96dcSApple OSS Distributions 		T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1473*2c2f96dcSApple OSS Distributions 		T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1474*2c2f96dcSApple OSS Distributions 		    address, address + size, depth,
1475*2c2f96dcSApple OSS Distributions 		    prot_str[info.protection],
1476*2c2f96dcSApple OSS Distributions 		    prot_str[info.max_protection],
1477*2c2f96dcSApple OSS Distributions 		    share_mode_str[info.share_mode],
1478*2c2f96dcSApple OSS Distributions 		    info.object_id);
1479*2c2f96dcSApple OSS Distributions 		if (depth > 0 && (info.protection & VM_PROT_WRITE)) {
1480*2c2f96dcSApple OSS Distributions 			/* nested and writable: bingo! */
1481*2c2f96dcSApple OSS Distributions 			break;
1482*2c2f96dcSApple OSS Distributions 		}
1483*2c2f96dcSApple OSS Distributions 	}
1484*2c2f96dcSApple OSS Distributions 	if (address >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1485*2c2f96dcSApple OSS Distributions 		T_SKIP("could not find writable nested mapping");
1486*2c2f96dcSApple OSS Distributions 		T_END;
1487*2c2f96dcSApple OSS Distributions 	}
1488*2c2f96dcSApple OSS Distributions 
1489*2c2f96dcSApple OSS Distributions 	/* test vm_remap() of RW */
1490*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1491*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1492*2c2f96dcSApple OSS Distributions 	remap_size = size;
1493*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
1494*2c2f96dcSApple OSS Distributions 	    &remap_address,
1495*2c2f96dcSApple OSS Distributions 	    remap_size,
1496*2c2f96dcSApple OSS Distributions 	    0,
1497*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE | VM_FLAGS_RETURN_DATA_ADDR,
1498*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1499*2c2f96dcSApple OSS Distributions 	    address,
1500*2c2f96dcSApple OSS Distributions 	    FALSE,
1501*2c2f96dcSApple OSS Distributions 	    &cur_prot,
1502*2c2f96dcSApple OSS Distributions 	    &max_prot,
1503*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1504*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap()");
1505*2c2f96dcSApple OSS Distributions 	if (!(cur_prot & VM_PROT_WRITE)) {
1506*2c2f96dcSApple OSS Distributions 		T_LOG("vm_remap(): 0x%llx not writable %s/%s",
1507*2c2f96dcSApple OSS Distributions 		    remap_address, prot_str[cur_prot], prot_str[max_prot]);
1508*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("vm_remap() remapping not writable");
1509*2c2f96dcSApple OSS Distributions 	}
1510*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1511*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1512*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1513*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1514*2c2f96dcSApple OSS Distributions 	T_LOG("vm_remap(): 0x%llx 0x%x -> 0x%x", address, before, after);
1515*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1516*2c2f96dcSApple OSS Distributions 	if (before != after) {
1517*2c2f96dcSApple OSS Distributions 		T_FAIL("vm_remap() bypassed copy-on-write");
1518*2c2f96dcSApple OSS Distributions 	} else {
1519*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap() did not bypass copy-on-write");
1520*2c2f96dcSApple OSS Distributions 	}
1521*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1522*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1523*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1524*2c2f96dcSApple OSS Distributions 	depth = 99;
1525*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1526*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1527*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1528*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1529*2c2f96dcSApple OSS Distributions 	    &depth,
1530*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1531*2c2f96dcSApple OSS Distributions 	    &count);
1532*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1533*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1534*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1535*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1536*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1537*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1538*2c2f96dcSApple OSS Distributions 	    info.object_id);
1539*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1540*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1541*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1542*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1543*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1544*2c2f96dcSApple OSS Distributions 	/* cleanup */
1545*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1546*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1547*2c2f96dcSApple OSS Distributions 
1548*2c2f96dcSApple OSS Distributions #if defined(VM_MEMORY_ROSETTA)
1549*2c2f96dcSApple OSS Distributions 	if (dlsym(RTLD_DEFAULT, "mach_vm_remap_new") == NULL) {
1550*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap_new() is not present");
1551*2c2f96dcSApple OSS Distributions 		goto skip_vm_remap_new_rw;
1552*2c2f96dcSApple OSS Distributions 	}
1553*2c2f96dcSApple OSS Distributions 	/* test vm_remap_new() of RW */
1554*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1555*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1556*2c2f96dcSApple OSS Distributions 	remap_size = size;
1557*2c2f96dcSApple OSS Distributions 	cur_prot = VM_PROT_READ | VM_PROT_WRITE;
1558*2c2f96dcSApple OSS Distributions 	max_prot = VM_PROT_READ | VM_PROT_WRITE;
1559*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap_new(mach_task_self(),
1560*2c2f96dcSApple OSS Distributions 	    &remap_address,
1561*2c2f96dcSApple OSS Distributions 	    remap_size,
1562*2c2f96dcSApple OSS Distributions 	    0,
1563*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1564*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1565*2c2f96dcSApple OSS Distributions 	    address,
1566*2c2f96dcSApple OSS Distributions 	    FALSE,
1567*2c2f96dcSApple OSS Distributions 	    &cur_prot,
1568*2c2f96dcSApple OSS Distributions 	    &max_prot,
1569*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1570*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_remap_new()");
1571*2c2f96dcSApple OSS Distributions 	if (kr == KERN_PROTECTION_FAILURE) {
1572*2c2f96dcSApple OSS Distributions 		/* wrong but not a security issue... */
1573*2c2f96dcSApple OSS Distributions 		goto skip_vm_remap_new_rw;
1574*2c2f96dcSApple OSS Distributions 	}
1575*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_remap_new()");
1576*2c2f96dcSApple OSS Distributions 	if (!(cur_prot & VM_PROT_WRITE)) {
1577*2c2f96dcSApple OSS Distributions 		T_LOG("vm_remap_new(): 0x%llx not writable %s/%s",
1578*2c2f96dcSApple OSS Distributions 		    remap_address, prot_str[cur_prot], prot_str[max_prot]);
1579*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("vm_remap_new() remapping not writable");
1580*2c2f96dcSApple OSS Distributions 	}
1581*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1582*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1583*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1584*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1585*2c2f96dcSApple OSS Distributions 	T_LOG("vm_remap_new(): 0x%llx 0x%x -> 0x%x", address, before, after);
1586*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1587*2c2f96dcSApple OSS Distributions 	if (before != after) {
1588*2c2f96dcSApple OSS Distributions 		T_FAIL("vm_remap_new() bypassed copy-on-write");
1589*2c2f96dcSApple OSS Distributions 	} else {
1590*2c2f96dcSApple OSS Distributions 		T_PASS("vm_remap_new() did not bypass copy-on-write");
1591*2c2f96dcSApple OSS Distributions 	}
1592*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1593*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1594*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1595*2c2f96dcSApple OSS Distributions 	depth = 99;
1596*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1597*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1598*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1599*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1600*2c2f96dcSApple OSS Distributions 	    &depth,
1601*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1602*2c2f96dcSApple OSS Distributions 	    &count);
1603*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1604*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1605*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1606*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1607*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1608*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1609*2c2f96dcSApple OSS Distributions 	    info.object_id);
1610*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1611*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1612*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1613*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1614*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1615*2c2f96dcSApple OSS Distributions 	/* cleanup */
1616*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1617*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1618*2c2f96dcSApple OSS Distributions skip_vm_remap_new_rw:
1619*2c2f96dcSApple OSS Distributions #else /* defined(VM_MEMORY_ROSETTA) */
1620*2c2f96dcSApple OSS Distributions 	/* pre-BigSur SDK: no vm_remap_new() */
1621*2c2f96dcSApple OSS Distributions 	T_LOG("No vm_remap_new() to test");
1622*2c2f96dcSApple OSS Distributions #endif /* defined(VM_MEMORY_ROSETTA) */
1623*2c2f96dcSApple OSS Distributions 
1624*2c2f96dcSApple OSS Distributions 	/* test mach_make_memory_entry_64(VM_SHARE) of RW */
1625*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1626*2c2f96dcSApple OSS Distributions 	remap_size = size;
1627*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
1628*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
1629*2c2f96dcSApple OSS Distributions 	    &remap_size,
1630*2c2f96dcSApple OSS Distributions 	    address,
1631*2c2f96dcSApple OSS Distributions 	    MAP_MEM_VM_SHARE | VM_PROT_READ | VM_PROT_WRITE,
1632*2c2f96dcSApple OSS Distributions 	    &mem_entry,
1633*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
1634*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1635*2c2f96dcSApple OSS Distributions 	if (kr == KERN_PROTECTION_FAILURE) {
1636*2c2f96dcSApple OSS Distributions 		/* wrong but not a security issue... */
1637*2c2f96dcSApple OSS Distributions 		goto skip_mem_entry_vm_share_rw;
1638*2c2f96dcSApple OSS Distributions 	}
1639*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64(VM_SHARE)");
1640*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap_size, size, "mem_entry(VM_SHARE) should cover whole mapping");
1641*2c2f96dcSApple OSS Distributions //	T_LOG("AFTER MAKE_MEM_ENTRY(VM_SHARE) 0x%llx...", address); fflush(stdout); fflush(stderr); getchar();
1642*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1643*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
1644*2c2f96dcSApple OSS Distributions 	    &remap_address,
1645*2c2f96dcSApple OSS Distributions 	    remap_size,
1646*2c2f96dcSApple OSS Distributions 	    0,              /* mask */
1647*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1648*2c2f96dcSApple OSS Distributions 	    mem_entry,
1649*2c2f96dcSApple OSS Distributions 	    0,              /* offset */
1650*2c2f96dcSApple OSS Distributions 	    FALSE,              /* copy */
1651*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1652*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1653*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1654*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1655*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1656*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1657*2c2f96dcSApple OSS Distributions //	T_LOG("AFTER VM_MAP 0x%llx...", remap_address); fflush(stdout); fflush(stderr); getchar();
1658*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1659*2c2f96dcSApple OSS Distributions //	T_LOG("AFTER WRITE 0x%llx...", remap_address); fflush(stdout); fflush(stderr); getchar();
1660*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1661*2c2f96dcSApple OSS Distributions 	T_LOG("mem_entry(VM_SHARE): 0x%llx 0x%x -> 0x%x", address, before, after);
1662*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1663*2c2f96dcSApple OSS Distributions 	if (before != after) {
1664*2c2f96dcSApple OSS Distributions 		T_FAIL("mem_entry(VM_SHARE) bypassed copy-on-write");
1665*2c2f96dcSApple OSS Distributions 	} else {
1666*2c2f96dcSApple OSS Distributions 		T_PASS("mem_entry(VM_SHARE) did not bypass copy-on-write");
1667*2c2f96dcSApple OSS Distributions 	}
1668*2c2f96dcSApple OSS Distributions 	/* check that region is still nested */
1669*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1670*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1671*2c2f96dcSApple OSS Distributions 	depth = 99;
1672*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1673*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1674*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1675*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1676*2c2f96dcSApple OSS Distributions 	    &depth,
1677*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1678*2c2f96dcSApple OSS Distributions 	    &count);
1679*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1680*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1681*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1682*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1683*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1684*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1685*2c2f96dcSApple OSS Distributions 	    info.object_id);
1686*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1687*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1688*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_GT(depth, 0, "still nested");
1689*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1690*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1691*2c2f96dcSApple OSS Distributions 	/* cleanup */
1692*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1693*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1694*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), mem_entry);
1695*2c2f96dcSApple OSS Distributions skip_mem_entry_vm_share_rw:
1696*2c2f96dcSApple OSS Distributions 
1697*2c2f96dcSApple OSS Distributions 	/* test mach_make_memory_entry_64() of RW */
1698*2c2f96dcSApple OSS Distributions 	before = *(uint32_t *)(uintptr_t)address;
1699*2c2f96dcSApple OSS Distributions 	remap_size = size;
1700*2c2f96dcSApple OSS Distributions 	mem_entry = MACH_PORT_NULL;
1701*2c2f96dcSApple OSS Distributions 	kr = mach_make_memory_entry_64(mach_task_self(),
1702*2c2f96dcSApple OSS Distributions 	    &remap_size,
1703*2c2f96dcSApple OSS Distributions 	    address,
1704*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1705*2c2f96dcSApple OSS Distributions 	    &mem_entry,
1706*2c2f96dcSApple OSS Distributions 	    MACH_PORT_NULL);
1707*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "mach_make_memory_entry_64()");
1708*2c2f96dcSApple OSS Distributions 	remap_address = 0;
1709*2c2f96dcSApple OSS Distributions 	kr = mach_vm_map(mach_task_self(),
1710*2c2f96dcSApple OSS Distributions 	    &remap_address,
1711*2c2f96dcSApple OSS Distributions 	    remap_size,
1712*2c2f96dcSApple OSS Distributions 	    0,              /* mask */
1713*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1714*2c2f96dcSApple OSS Distributions 	    mem_entry,
1715*2c2f96dcSApple OSS Distributions 	    0,              /* offset */
1716*2c2f96dcSApple OSS Distributions 	    FALSE,              /* copy */
1717*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1718*2c2f96dcSApple OSS Distributions 	    VM_PROT_READ | VM_PROT_WRITE,
1719*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1720*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_map()");
1721*2c2f96dcSApple OSS Distributions 	remap = *(uint32_t *)(uintptr_t)remap_address;
1722*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(remap, before, "remap matches original");
1723*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before + 1;
1724*2c2f96dcSApple OSS Distributions 	after = *(uint32_t *)(uintptr_t)address;
1725*2c2f96dcSApple OSS Distributions 	T_LOG("mem_entry(): 0x%llx 0x%x -> 0x%x", address, before, after);
1726*2c2f96dcSApple OSS Distributions 	*(uint32_t *)(uintptr_t)remap_address = before;
1727*2c2f96dcSApple OSS Distributions 	/* check that region is no longer nested */
1728*2c2f96dcSApple OSS Distributions 	tmp_address = address;
1729*2c2f96dcSApple OSS Distributions 	tmp_size = 0;
1730*2c2f96dcSApple OSS Distributions 	depth = 99;
1731*2c2f96dcSApple OSS Distributions 	count = VM_REGION_SUBMAP_INFO_COUNT_64;
1732*2c2f96dcSApple OSS Distributions 	kr = mach_vm_region_recurse(mach_task_self(),
1733*2c2f96dcSApple OSS Distributions 	    &tmp_address,
1734*2c2f96dcSApple OSS Distributions 	    &tmp_size,
1735*2c2f96dcSApple OSS Distributions 	    &depth,
1736*2c2f96dcSApple OSS Distributions 	    (vm_region_recurse_info_t)&info,
1737*2c2f96dcSApple OSS Distributions 	    &count);
1738*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse()");
1739*2c2f96dcSApple OSS Distributions 	T_LOG("0x%llx - 0x%llx depth:%d %s/%s %s 0x%x",
1740*2c2f96dcSApple OSS Distributions 	    tmp_address, tmp_address + tmp_size, depth,
1741*2c2f96dcSApple OSS Distributions 	    prot_str[info.protection],
1742*2c2f96dcSApple OSS Distributions 	    prot_str[info.max_protection],
1743*2c2f96dcSApple OSS Distributions 	    share_mode_str[info.share_mode],
1744*2c2f96dcSApple OSS Distributions 	    info.object_id);
1745*2c2f96dcSApple OSS Distributions 	if (before != after) {
1746*2c2f96dcSApple OSS Distributions 		if (depth == 0) {
1747*2c2f96dcSApple OSS Distributions 			T_PASS("mem_entry() honored copy-on-write");
1748*2c2f96dcSApple OSS Distributions 		} else {
1749*2c2f96dcSApple OSS Distributions 			T_FAIL("mem_entry() did not trigger copy-on_write");
1750*2c2f96dcSApple OSS Distributions 		}
1751*2c2f96dcSApple OSS Distributions 	} else {
1752*2c2f96dcSApple OSS Distributions 		T_FAIL("mem_entry() did not honor copy-on-write");
1753*2c2f96dcSApple OSS Distributions 	}
1754*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(tmp_address, address, "address hasn't changed");
1755*2c2f96dcSApple OSS Distributions //	T_QUIET; T_ASSERT_EQ(tmp_size, size, "size hasn't changed");
1756*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(depth, 0, "no longer nested");
1757*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ(info.protection, VM_PROT_DEFAULT, "cur_prot still writable");
1758*2c2f96dcSApple OSS Distributions 	T_QUIET; T_ASSERT_EQ((info.max_protection & VM_PROT_WRITE), VM_PROT_WRITE, "max_prot still writable");
1759*2c2f96dcSApple OSS Distributions 	/* cleanup */
1760*2c2f96dcSApple OSS Distributions 	kr = mach_vm_deallocate(mach_task_self(), remap_address, remap_size);
1761*2c2f96dcSApple OSS Distributions 	T_QUIET; T_EXPECT_MACH_SUCCESS(kr, "vm_deallocate()");
1762*2c2f96dcSApple OSS Distributions 	mach_port_deallocate(mach_task_self(), mem_entry);
1763*2c2f96dcSApple OSS Distributions }
1764*2c2f96dcSApple OSS Distributions 
1765*2c2f96dcSApple OSS Distributions T_DECL(copyoverwrite_submap_protection, "test copywrite vm region submap \
1766*2c2f96dcSApple OSS Distributions     protection", T_META_ALL_VALID_ARCHS(true))
1767*2c2f96dcSApple OSS Distributions {
1768*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
1769*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       vmaddr;
1770*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize;
1771*2c2f96dcSApple OSS Distributions 	natural_t               depth;
1772*2c2f96dcSApple OSS Distributions 	vm_region_submap_short_info_data_64_t region_info;
1773*2c2f96dcSApple OSS Distributions 	mach_msg_type_number_t  region_info_count;
1774*2c2f96dcSApple OSS Distributions 
1775*2c2f96dcSApple OSS Distributions 	for (vmaddr = SHARED_REGION_BASE;
1776*2c2f96dcSApple OSS Distributions 	    vmaddr < SHARED_REGION_BASE + SHARED_REGION_SIZE;
1777*2c2f96dcSApple OSS Distributions 	    vmaddr += vmsize) {
1778*2c2f96dcSApple OSS Distributions 		depth = 99;
1779*2c2f96dcSApple OSS Distributions 		region_info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1780*2c2f96dcSApple OSS Distributions 		kr = mach_vm_region_recurse(mach_task_self(),
1781*2c2f96dcSApple OSS Distributions 		    &vmaddr,
1782*2c2f96dcSApple OSS Distributions 		    &vmsize,
1783*2c2f96dcSApple OSS Distributions 		    &depth,
1784*2c2f96dcSApple OSS Distributions 		    (vm_region_info_t) &region_info,
1785*2c2f96dcSApple OSS Distributions 		    &region_info_count);
1786*2c2f96dcSApple OSS Distributions 		if (kr == KERN_INVALID_ADDRESS) {
1787*2c2f96dcSApple OSS Distributions 			break;
1788*2c2f96dcSApple OSS Distributions 		}
1789*2c2f96dcSApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "vm_region_recurse(0x%llx)", vmaddr);
1790*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(region_info_count,
1791*2c2f96dcSApple OSS Distributions 		    VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
1792*2c2f96dcSApple OSS Distributions 		    "vm_region_recurse(0x%llx) count = %d expected %d",
1793*2c2f96dcSApple OSS Distributions 		    vmaddr, region_info_count,
1794*2c2f96dcSApple OSS Distributions 		    VM_REGION_SUBMAP_SHORT_INFO_COUNT_64);
1795*2c2f96dcSApple OSS Distributions 
1796*2c2f96dcSApple OSS Distributions 		T_LOG("--> region: vmaddr 0x%llx depth %d prot 0x%x/0x%x",
1797*2c2f96dcSApple OSS Distributions 		    vmaddr, depth, region_info.protection,
1798*2c2f96dcSApple OSS Distributions 		    region_info.max_protection);
1799*2c2f96dcSApple OSS Distributions 		if (depth == 0) {
1800*2c2f96dcSApple OSS Distributions 			/* not a submap mapping: next mapping */
1801*2c2f96dcSApple OSS Distributions 			continue;
1802*2c2f96dcSApple OSS Distributions 		}
1803*2c2f96dcSApple OSS Distributions 		if (vmaddr >= SHARED_REGION_BASE + SHARED_REGION_SIZE) {
1804*2c2f96dcSApple OSS Distributions 			break;
1805*2c2f96dcSApple OSS Distributions 		}
1806*2c2f96dcSApple OSS Distributions 		kr = mach_vm_copy(mach_task_self(),
1807*2c2f96dcSApple OSS Distributions 		    vmaddr,
1808*2c2f96dcSApple OSS Distributions 		    vmsize,
1809*2c2f96dcSApple OSS Distributions 		    vmaddr);
1810*2c2f96dcSApple OSS Distributions 		if (kr == KERN_PROTECTION_FAILURE ||
1811*2c2f96dcSApple OSS Distributions 		    kr == KERN_INVALID_ADDRESS) {
1812*2c2f96dcSApple OSS Distributions 			T_PASS("vm_copy(0x%llx,0x%llx) expected prot error 0x%x (%s)",
1813*2c2f96dcSApple OSS Distributions 			    vmaddr, vmsize, kr, mach_error_string(kr));
1814*2c2f96dcSApple OSS Distributions 			continue;
1815*2c2f96dcSApple OSS Distributions 		}
1816*2c2f96dcSApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "vm_copy(0x%llx,0x%llx) prot 0x%x",
1817*2c2f96dcSApple OSS Distributions 		    vmaddr, vmsize, region_info.protection);
1818*2c2f96dcSApple OSS Distributions 		depth = 0;
1819*2c2f96dcSApple OSS Distributions 		region_info_count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
1820*2c2f96dcSApple OSS Distributions 		kr = mach_vm_region_recurse(mach_task_self(),
1821*2c2f96dcSApple OSS Distributions 		    &vmaddr,
1822*2c2f96dcSApple OSS Distributions 		    &vmsize,
1823*2c2f96dcSApple OSS Distributions 		    &depth,
1824*2c2f96dcSApple OSS Distributions 		    (vm_region_info_t) &region_info,
1825*2c2f96dcSApple OSS Distributions 		    &region_info_count);
1826*2c2f96dcSApple OSS Distributions 		T_ASSERT_MACH_SUCCESS(kr, "m_region_recurse(0x%llx)", vmaddr);
1827*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(region_info_count,
1828*2c2f96dcSApple OSS Distributions 		    VM_REGION_SUBMAP_SHORT_INFO_COUNT_64,
1829*2c2f96dcSApple OSS Distributions 		    "vm_region_recurse() count = %d expected %d",
1830*2c2f96dcSApple OSS Distributions 		    region_info_count, VM_REGION_SUBMAP_SHORT_INFO_COUNT_64);
1831*2c2f96dcSApple OSS Distributions 
1832*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(depth, 0, "vm_region_recurse(0x%llx): depth = %d expected 0",
1833*2c2f96dcSApple OSS Distributions 		    vmaddr, depth);
1834*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ((region_info.protection & VM_PROT_EXECUTE),
1835*2c2f96dcSApple OSS Distributions 		    0, "vm_region_recurse(0x%llx): prot 0x%x",
1836*2c2f96dcSApple OSS Distributions 		    vmaddr, region_info.protection);
1837*2c2f96dcSApple OSS Distributions 	}
1838*2c2f96dcSApple OSS Distributions }
1839*2c2f96dcSApple OSS Distributions 
1840*2c2f96dcSApple OSS Distributions T_DECL(wire_text, "test wired text for rdar://problem/16783546 Wiring code in \
1841*2c2f96dcSApple OSS Distributions     the shared region triggers code-signing violations",
1842*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
1843*2c2f96dcSApple OSS Distributions {
1844*2c2f96dcSApple OSS Distributions 	uint32_t *addr, before, after;
1845*2c2f96dcSApple OSS Distributions 	int retval;
1846*2c2f96dcSApple OSS Distributions 	int saved_errno;
1847*2c2f96dcSApple OSS Distributions 	kern_return_t kr;
1848*2c2f96dcSApple OSS Distributions 	vm_address_t map_addr, remap_addr;
1849*2c2f96dcSApple OSS Distributions 	vm_prot_t curprot, maxprot;
1850*2c2f96dcSApple OSS Distributions 
1851*2c2f96dcSApple OSS Distributions 	addr = (uint32_t *)&printf;
1852*2c2f96dcSApple OSS Distributions #if __has_feature(ptrauth_calls)
1853*2c2f96dcSApple OSS Distributions 	map_addr = (vm_address_t)(uintptr_t)ptrauth_strip(addr, ptrauth_key_function_pointer);
1854*2c2f96dcSApple OSS Distributions #else /* __has_feature(ptrauth_calls) */
1855*2c2f96dcSApple OSS Distributions 	map_addr = (vm_address_t)(uintptr_t)addr;
1856*2c2f96dcSApple OSS Distributions #endif /* __has_feature(ptrauth_calls) */
1857*2c2f96dcSApple OSS Distributions 	remap_addr = 0;
1858*2c2f96dcSApple OSS Distributions 	kr = vm_remap(mach_task_self(), &remap_addr, 4096,
1859*2c2f96dcSApple OSS Distributions 	    0,           /* mask */
1860*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1861*2c2f96dcSApple OSS Distributions 	    mach_task_self(), map_addr,
1862*2c2f96dcSApple OSS Distributions 	    FALSE,           /* copy */
1863*2c2f96dcSApple OSS Distributions 	    &curprot, &maxprot,
1864*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1865*2c2f96dcSApple OSS Distributions 	T_ASSERT_EQ(kr, KERN_SUCCESS, "vm_remap error 0x%x (%s)",
1866*2c2f96dcSApple OSS Distributions 	    kr, mach_error_string(kr));
1867*2c2f96dcSApple OSS Distributions 	before = *addr;
1868*2c2f96dcSApple OSS Distributions 	retval = mlock(addr, 4096);
1869*2c2f96dcSApple OSS Distributions 	after = *addr;
1870*2c2f96dcSApple OSS Distributions 	if (retval != 0) {
1871*2c2f96dcSApple OSS Distributions 		saved_errno = errno;
1872*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(saved_errno, EACCES, "wire shared text error %d (%s), expected: %d",
1873*2c2f96dcSApple OSS Distributions 		    saved_errno, strerror(saved_errno), EACCES);
1874*2c2f96dcSApple OSS Distributions 	} else if (after != before) {
1875*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("shared text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1876*2c2f96dcSApple OSS Distributions 	} else {
1877*2c2f96dcSApple OSS Distributions 		T_PASS("wire shared text");
1878*2c2f96dcSApple OSS Distributions 	}
1879*2c2f96dcSApple OSS Distributions 
1880*2c2f96dcSApple OSS Distributions 	addr = (uint32_t *) &fprintf;
1881*2c2f96dcSApple OSS Distributions 	before = *addr;
1882*2c2f96dcSApple OSS Distributions 	retval = mlock(addr, 4096);
1883*2c2f96dcSApple OSS Distributions 	after = *addr;
1884*2c2f96dcSApple OSS Distributions 	if (retval != 0) {
1885*2c2f96dcSApple OSS Distributions 		saved_errno = errno;
1886*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(saved_errno, EACCES, "wire shared text error %d (%s), expected: %d",
1887*2c2f96dcSApple OSS Distributions 		    saved_errno, strerror(saved_errno), EACCES);
1888*2c2f96dcSApple OSS Distributions 	} else if (after != before) {
1889*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("shared text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1890*2c2f96dcSApple OSS Distributions 	} else {
1891*2c2f96dcSApple OSS Distributions 		T_PASS("wire shared text");
1892*2c2f96dcSApple OSS Distributions 	}
1893*2c2f96dcSApple OSS Distributions 
1894*2c2f96dcSApple OSS Distributions 	addr = (uint32_t *) &testmain_wire_text;
1895*2c2f96dcSApple OSS Distributions 	before = *addr;
1896*2c2f96dcSApple OSS Distributions 	retval = mlock(addr, 4096);
1897*2c2f96dcSApple OSS Distributions 	after = *addr;
1898*2c2f96dcSApple OSS Distributions 	if (retval != 0) {
1899*2c2f96dcSApple OSS Distributions 		saved_errno = errno;
1900*2c2f96dcSApple OSS Distributions 		T_ASSERT_EQ(saved_errno, EACCES, "wire text error return error %d (%s)",
1901*2c2f96dcSApple OSS Distributions 		    saved_errno, strerror(saved_errno));
1902*2c2f96dcSApple OSS Distributions 	} else if (after != before) {
1903*2c2f96dcSApple OSS Distributions 		T_ASSERT_FAIL("text changed by wiring at %p 0x%x -> 0x%x", addr, before, after);
1904*2c2f96dcSApple OSS Distributions 	} else {
1905*2c2f96dcSApple OSS Distributions 		T_PASS("wire text");
1906*2c2f96dcSApple OSS Distributions 	}
1907*2c2f96dcSApple OSS Distributions }
1908*2c2f96dcSApple OSS Distributions 
1909*2c2f96dcSApple OSS Distributions T_DECL(remap_comm_page, "test remapping of the commpage - rdar://93177124",
1910*2c2f96dcSApple OSS Distributions     T_META_ALL_VALID_ARCHS(true))
1911*2c2f96dcSApple OSS Distributions {
1912*2c2f96dcSApple OSS Distributions 	kern_return_t           kr;
1913*2c2f96dcSApple OSS Distributions 	mach_vm_address_t       commpage_addr, remap_addr;
1914*2c2f96dcSApple OSS Distributions 	mach_vm_size_t          vmsize;
1915*2c2f96dcSApple OSS Distributions 	vm_prot_t               curprot, maxprot;
1916*2c2f96dcSApple OSS Distributions 
1917*2c2f96dcSApple OSS Distributions #if __arm__
1918*2c2f96dcSApple OSS Distributions 	commpage_addr = 0xFFFF4000ULL;
1919*2c2f96dcSApple OSS Distributions #elif __arm64__
1920*2c2f96dcSApple OSS Distributions 	commpage_addr = 0x0000000FFFFFC000ULL;
1921*2c2f96dcSApple OSS Distributions #elif __x86_64__
1922*2c2f96dcSApple OSS Distributions 	commpage_addr = 0x00007FFFFFE00000ULL;
1923*2c2f96dcSApple OSS Distributions #else
1924*2c2f96dcSApple OSS Distributions 	T_FAIL("unknown commpage address for this architecture");
1925*2c2f96dcSApple OSS Distributions #endif
1926*2c2f96dcSApple OSS Distributions 
1927*2c2f96dcSApple OSS Distributions 	T_LOG("Remapping commpage from 0x%llx", commpage_addr);
1928*2c2f96dcSApple OSS Distributions 	vmsize = vm_kernel_page_size;
1929*2c2f96dcSApple OSS Distributions 	remap_addr = 0;
1930*2c2f96dcSApple OSS Distributions 	kr = mach_vm_remap(mach_task_self(),
1931*2c2f96dcSApple OSS Distributions 	    &remap_addr,
1932*2c2f96dcSApple OSS Distributions 	    vmsize,
1933*2c2f96dcSApple OSS Distributions 	    0, /* mask */
1934*2c2f96dcSApple OSS Distributions 	    VM_FLAGS_ANYWHERE,
1935*2c2f96dcSApple OSS Distributions 	    mach_task_self(),
1936*2c2f96dcSApple OSS Distributions 	    commpage_addr,
1937*2c2f96dcSApple OSS Distributions 	    TRUE, /* copy */
1938*2c2f96dcSApple OSS Distributions 	    &curprot,
1939*2c2f96dcSApple OSS Distributions 	    &maxprot,
1940*2c2f96dcSApple OSS Distributions 	    VM_INHERIT_DEFAULT);
1941*2c2f96dcSApple OSS Distributions 	if (kr == KERN_INVALID_ADDRESS) {
1942*2c2f96dcSApple OSS Distributions 		T_SKIP("No mapping found at 0x%llx\n", commpage_addr);
1943*2c2f96dcSApple OSS Distributions 		return;
1944*2c2f96dcSApple OSS Distributions 	}
1945*2c2f96dcSApple OSS Distributions 	T_ASSERT_MACH_SUCCESS(kr, "vm_remap() of commpage from 0x%llx", commpage_addr);
1946*2c2f96dcSApple OSS Distributions }
1947