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