1*0f4c859eSApple OSS Distributions /*
2*0f4c859eSApple OSS Distributions * This tests the Mac OS X Superpage API introduced in 10.7
3*0f4c859eSApple OSS Distributions *
4*0f4c859eSApple OSS Distributions * Note that most of these calls go through the mach_vm_allocate() interface,
5*0f4c859eSApple OSS Distributions * but the actually supported and documented interface is the mmap() one
6*0f4c859eSApple OSS Distributions * (see mmap(2)).
7*0f4c859eSApple OSS Distributions */
8*0f4c859eSApple OSS Distributions #include <stdio.h>
9*0f4c859eSApple OSS Distributions #include <stdlib.h>
10*0f4c859eSApple OSS Distributions #include <signal.h>
11*0f4c859eSApple OSS Distributions #include <setjmp.h>
12*0f4c859eSApple OSS Distributions #include <mach/mach.h>
13*0f4c859eSApple OSS Distributions #include <mach/mach_vm.h>
14*0f4c859eSApple OSS Distributions #include <time.h>
15*0f4c859eSApple OSS Distributions #include <unistd.h>
16*0f4c859eSApple OSS Distributions #include <fcntl.h>
17*0f4c859eSApple OSS Distributions #include <sys/mman.h>
18*0f4c859eSApple OSS Distributions
19*0f4c859eSApple OSS Distributions #define SUPERPAGE_SIZE (2*1024*1024)
20*0f4c859eSApple OSS Distributions #define SUPERPAGE_MASK (-SUPERPAGE_SIZE)
21*0f4c859eSApple OSS Distributions
22*0f4c859eSApple OSS Distributions #ifdef __LP64__
23*0f4c859eSApple OSS Distributions #define FIXED_ADDRESS1 (0x100000000ULL+500*1024*1024) /* at 4 GB + 500 MB virtual */
24*0f4c859eSApple OSS Distributions #define FIXED_ADDRESS2 (0x100000000ULL+502*1024*1024 + 4*1024) /* at 4 GB + 502 MB + 4 KB virtual */
25*0f4c859eSApple OSS Distributions #else
26*0f4c859eSApple OSS Distributions #define FIXED_ADDRESS1 (500*1024*1024) /* at 500 MB virtual */
27*0f4c859eSApple OSS Distributions #define FIXED_ADDRESS2 (502*1024*1024 + 4*1024) /* at 502 MB + 4 KB virtual */
28*0f4c859eSApple OSS Distributions #endif
29*0f4c859eSApple OSS Distributions
30*0f4c859eSApple OSS Distributions char error[100];
31*0f4c859eSApple OSS Distributions
32*0f4c859eSApple OSS Distributions jmp_buf resume;
33*0f4c859eSApple OSS Distributions void
test_signal_handler(int signo)34*0f4c859eSApple OSS Distributions test_signal_handler(int signo)
35*0f4c859eSApple OSS Distributions {
36*0f4c859eSApple OSS Distributions longjmp(resume, signo);
37*0f4c859eSApple OSS Distributions }
38*0f4c859eSApple OSS Distributions
39*0f4c859eSApple OSS Distributions char *signame[32] = {
40*0f4c859eSApple OSS Distributions [SIGBUS] "SIGBUS",
41*0f4c859eSApple OSS Distributions [SIGSEGV] "SIGSEGV"
42*0f4c859eSApple OSS Distributions };
43*0f4c859eSApple OSS Distributions
44*0f4c859eSApple OSS Distributions typedef struct {
45*0f4c859eSApple OSS Distributions char *description;
46*0f4c859eSApple OSS Distributions boolean_t (*fn)();
47*0f4c859eSApple OSS Distributions } test_t;
48*0f4c859eSApple OSS Distributions
49*0f4c859eSApple OSS Distributions boolean_t
check_kr(int kr,char * fn)50*0f4c859eSApple OSS Distributions check_kr(int kr, char *fn)
51*0f4c859eSApple OSS Distributions {
52*0f4c859eSApple OSS Distributions if (kr) {
53*0f4c859eSApple OSS Distributions sprintf(error, "%s() returned %d", fn, kr);
54*0f4c859eSApple OSS Distributions return FALSE;
55*0f4c859eSApple OSS Distributions }
56*0f4c859eSApple OSS Distributions return TRUE;
57*0f4c859eSApple OSS Distributions }
58*0f4c859eSApple OSS Distributions
59*0f4c859eSApple OSS Distributions boolean_t
check_addr0(mach_vm_address_t addr,char * fn)60*0f4c859eSApple OSS Distributions check_addr0(mach_vm_address_t addr, char *fn)
61*0f4c859eSApple OSS Distributions {
62*0f4c859eSApple OSS Distributions if (!addr) {
63*0f4c859eSApple OSS Distributions sprintf(error, "%s() returned address 0", fn);
64*0f4c859eSApple OSS Distributions return FALSE;
65*0f4c859eSApple OSS Distributions }
66*0f4c859eSApple OSS Distributions return TRUE;
67*0f4c859eSApple OSS Distributions }
68*0f4c859eSApple OSS Distributions
69*0f4c859eSApple OSS Distributions boolean_t
check_addr(mach_vm_address_t addr1,mach_vm_address_t addr2,char * fn)70*0f4c859eSApple OSS Distributions check_addr(mach_vm_address_t addr1, mach_vm_address_t addr2, char *fn)
71*0f4c859eSApple OSS Distributions {
72*0f4c859eSApple OSS Distributions if (addr1 != addr2) {
73*0f4c859eSApple OSS Distributions sprintf(error, "%s() returned address %llx instead of %llx", fn, addr1, addr2);
74*0f4c859eSApple OSS Distributions return FALSE;
75*0f4c859eSApple OSS Distributions }
76*0f4c859eSApple OSS Distributions return TRUE;
77*0f4c859eSApple OSS Distributions }
78*0f4c859eSApple OSS Distributions
79*0f4c859eSApple OSS Distributions boolean_t
check_align(mach_vm_address_t addr)80*0f4c859eSApple OSS Distributions check_align(mach_vm_address_t addr)
81*0f4c859eSApple OSS Distributions {
82*0f4c859eSApple OSS Distributions if (addr & !SUPERPAGE_MASK) {
83*0f4c859eSApple OSS Distributions sprintf(error, "address not aligned properly: 0x%llx", addr);
84*0f4c859eSApple OSS Distributions return FALSE;
85*0f4c859eSApple OSS Distributions }
86*0f4c859eSApple OSS Distributions return TRUE;
87*0f4c859eSApple OSS Distributions }
88*0f4c859eSApple OSS Distributions
89*0f4c859eSApple OSS Distributions boolean_t
check_r(mach_vm_address_t addr,mach_vm_size_t size,int * res)90*0f4c859eSApple OSS Distributions check_r(mach_vm_address_t addr, mach_vm_size_t size, int *res)
91*0f4c859eSApple OSS Distributions {
92*0f4c859eSApple OSS Distributions volatile char *data = (char*)(uintptr_t)addr;
93*0f4c859eSApple OSS Distributions int i, sig, test;
94*0f4c859eSApple OSS Distributions
95*0f4c859eSApple OSS Distributions if ((sig = setjmp(resume)) != 0) {
96*0f4c859eSApple OSS Distributions sprintf(error, "%s when reading", signame[sig]);
97*0f4c859eSApple OSS Distributions return FALSE;
98*0f4c859eSApple OSS Distributions }
99*0f4c859eSApple OSS Distributions test = 0;
100*0f4c859eSApple OSS Distributions for (i = 0; i < size; i++) {
101*0f4c859eSApple OSS Distributions test += (data)[i];
102*0f4c859eSApple OSS Distributions }
103*0f4c859eSApple OSS Distributions
104*0f4c859eSApple OSS Distributions if (res) {
105*0f4c859eSApple OSS Distributions *res = test;
106*0f4c859eSApple OSS Distributions }
107*0f4c859eSApple OSS Distributions
108*0f4c859eSApple OSS Distributions return TRUE;
109*0f4c859eSApple OSS Distributions }
110*0f4c859eSApple OSS Distributions
111*0f4c859eSApple OSS Distributions /* check that no subpage of the superpage is readable */
112*0f4c859eSApple OSS Distributions boolean_t
check_nr(mach_vm_address_t addr,mach_vm_size_t size,int * res)113*0f4c859eSApple OSS Distributions check_nr(mach_vm_address_t addr, mach_vm_size_t size, int *res)
114*0f4c859eSApple OSS Distributions {
115*0f4c859eSApple OSS Distributions int i;
116*0f4c859eSApple OSS Distributions boolean_t ret;
117*0f4c859eSApple OSS Distributions for (i = 0; i < size / PAGE_SIZE; i++) {
118*0f4c859eSApple OSS Distributions if ((ret = check_r(addr + i * PAGE_SIZE, PAGE_SIZE, res))) {
119*0f4c859eSApple OSS Distributions sprintf(error, "page still readable");
120*0f4c859eSApple OSS Distributions return FALSE;
121*0f4c859eSApple OSS Distributions }
122*0f4c859eSApple OSS Distributions }
123*0f4c859eSApple OSS Distributions return TRUE;
124*0f4c859eSApple OSS Distributions }
125*0f4c859eSApple OSS Distributions
126*0f4c859eSApple OSS Distributions boolean_t
check_w(mach_vm_address_t addr,mach_vm_size_t size)127*0f4c859eSApple OSS Distributions check_w(mach_vm_address_t addr, mach_vm_size_t size)
128*0f4c859eSApple OSS Distributions {
129*0f4c859eSApple OSS Distributions char *data = (char*)(uintptr_t)addr;
130*0f4c859eSApple OSS Distributions int i, sig;
131*0f4c859eSApple OSS Distributions
132*0f4c859eSApple OSS Distributions if ((sig = setjmp(resume)) != 0) {
133*0f4c859eSApple OSS Distributions sprintf(error, "%s when writing", signame[sig]);
134*0f4c859eSApple OSS Distributions return FALSE;
135*0f4c859eSApple OSS Distributions }
136*0f4c859eSApple OSS Distributions
137*0f4c859eSApple OSS Distributions for (i = 0; i < size; i++) {
138*0f4c859eSApple OSS Distributions (data)[i] = i & 0xFF;
139*0f4c859eSApple OSS Distributions }
140*0f4c859eSApple OSS Distributions
141*0f4c859eSApple OSS Distributions return TRUE;
142*0f4c859eSApple OSS Distributions }
143*0f4c859eSApple OSS Distributions
144*0f4c859eSApple OSS Distributions boolean_t
check_nw(mach_vm_address_t addr,mach_vm_size_t size)145*0f4c859eSApple OSS Distributions check_nw(mach_vm_address_t addr, mach_vm_size_t size)
146*0f4c859eSApple OSS Distributions {
147*0f4c859eSApple OSS Distributions int i;
148*0f4c859eSApple OSS Distributions boolean_t ret;
149*0f4c859eSApple OSS Distributions
150*0f4c859eSApple OSS Distributions for (i = 0; i < size / PAGE_SIZE; i++) {
151*0f4c859eSApple OSS Distributions if ((ret = check_w(addr + i * PAGE_SIZE, PAGE_SIZE))) {
152*0f4c859eSApple OSS Distributions sprintf(error, "page still writable");
153*0f4c859eSApple OSS Distributions return FALSE;
154*0f4c859eSApple OSS Distributions }
155*0f4c859eSApple OSS Distributions }
156*0f4c859eSApple OSS Distributions return TRUE;
157*0f4c859eSApple OSS Distributions }
158*0f4c859eSApple OSS Distributions
159*0f4c859eSApple OSS Distributions boolean_t
check_rw(mach_vm_address_t addr,mach_vm_size_t size)160*0f4c859eSApple OSS Distributions check_rw(mach_vm_address_t addr, mach_vm_size_t size)
161*0f4c859eSApple OSS Distributions {
162*0f4c859eSApple OSS Distributions int ret;
163*0f4c859eSApple OSS Distributions int res;
164*0f4c859eSApple OSS Distributions if (!(ret = check_w(addr, size))) {
165*0f4c859eSApple OSS Distributions return ret;
166*0f4c859eSApple OSS Distributions }
167*0f4c859eSApple OSS Distributions if (!(ret = check_r(addr, size, &res))) {
168*0f4c859eSApple OSS Distributions return ret;
169*0f4c859eSApple OSS Distributions }
170*0f4c859eSApple OSS Distributions if ((size == SUPERPAGE_SIZE) && (res != 0xfff00000)) {
171*0f4c859eSApple OSS Distributions sprintf(error, "checksum error");
172*0f4c859eSApple OSS Distributions return FALSE;
173*0f4c859eSApple OSS Distributions }
174*0f4c859eSApple OSS Distributions
175*0f4c859eSApple OSS Distributions return TRUE;
176*0f4c859eSApple OSS Distributions }
177*0f4c859eSApple OSS Distributions
178*0f4c859eSApple OSS Distributions mach_vm_address_t global_addr = 0;
179*0f4c859eSApple OSS Distributions mach_vm_size_t global_size = 0;
180*0f4c859eSApple OSS Distributions
181*0f4c859eSApple OSS Distributions /*
182*0f4c859eSApple OSS Distributions * If we allocate a 2 MB superpage read-write without specifying an address,
183*0f4c859eSApple OSS Distributions * - the call should succeed
184*0f4c859eSApple OSS Distributions * - not return 0
185*0f4c859eSApple OSS Distributions * - return a 2 MB aligned address
186*0f4c859eSApple OSS Distributions * - the memory should be readable and writable
187*0f4c859eSApple OSS Distributions */
188*0f4c859eSApple OSS Distributions boolean_t
test_allocate()189*0f4c859eSApple OSS Distributions test_allocate()
190*0f4c859eSApple OSS Distributions {
191*0f4c859eSApple OSS Distributions int kr, ret;
192*0f4c859eSApple OSS Distributions
193*0f4c859eSApple OSS Distributions global_addr = 0;
194*0f4c859eSApple OSS Distributions global_size = SUPERPAGE_SIZE;
195*0f4c859eSApple OSS Distributions
196*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &global_addr, global_size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
197*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
198*0f4c859eSApple OSS Distributions return ret;
199*0f4c859eSApple OSS Distributions }
200*0f4c859eSApple OSS Distributions if (!(ret = check_addr0(global_addr, "mach_vm_allocate"))) {
201*0f4c859eSApple OSS Distributions return ret;
202*0f4c859eSApple OSS Distributions }
203*0f4c859eSApple OSS Distributions if (!(ret = check_align(global_addr))) {
204*0f4c859eSApple OSS Distributions return ret;
205*0f4c859eSApple OSS Distributions }
206*0f4c859eSApple OSS Distributions if (!(ret = check_rw(global_addr, global_size))) {
207*0f4c859eSApple OSS Distributions return ret;
208*0f4c859eSApple OSS Distributions }
209*0f4c859eSApple OSS Distributions
210*0f4c859eSApple OSS Distributions return TRUE;
211*0f4c859eSApple OSS Distributions }
212*0f4c859eSApple OSS Distributions
213*0f4c859eSApple OSS Distributions /*
214*0f4c859eSApple OSS Distributions * If we deallocate a superpage,
215*0f4c859eSApple OSS Distributions * - the call should succeed
216*0f4c859eSApple OSS Distributions * - make the memory inaccessible
217*0f4c859eSApple OSS Distributions */
218*0f4c859eSApple OSS Distributions boolean_t
test_deallocate()219*0f4c859eSApple OSS Distributions test_deallocate()
220*0f4c859eSApple OSS Distributions {
221*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
222*0f4c859eSApple OSS Distributions int kr, ret;
223*0f4c859eSApple OSS Distributions
224*0f4c859eSApple OSS Distributions if (!global_addr) {
225*0f4c859eSApple OSS Distributions sprintf(error, "skipped deallocation");
226*0f4c859eSApple OSS Distributions return FALSE;
227*0f4c859eSApple OSS Distributions }
228*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), global_addr, global_size);
229*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
230*0f4c859eSApple OSS Distributions return ret;
231*0f4c859eSApple OSS Distributions }
232*0f4c859eSApple OSS Distributions if (!(ret = check_nr(global_addr, size, NULL))) {
233*0f4c859eSApple OSS Distributions return ret;
234*0f4c859eSApple OSS Distributions }
235*0f4c859eSApple OSS Distributions return TRUE;
236*0f4c859eSApple OSS Distributions }
237*0f4c859eSApple OSS Distributions
238*0f4c859eSApple OSS Distributions /*
239*0f4c859eSApple OSS Distributions * If we allocate a superpage of any size read-write without specifying an address
240*0f4c859eSApple OSS Distributions * - the call should succeed
241*0f4c859eSApple OSS Distributions * - not return 0
242*0f4c859eSApple OSS Distributions * - the memory should be readable and writable
243*0f4c859eSApple OSS Distributions * If we deallocate it,
244*0f4c859eSApple OSS Distributions * - the call should succeed
245*0f4c859eSApple OSS Distributions * - make the memory inaccessible
246*0f4c859eSApple OSS Distributions */
247*0f4c859eSApple OSS Distributions boolean_t
test_allocate_size_any()248*0f4c859eSApple OSS Distributions test_allocate_size_any()
249*0f4c859eSApple OSS Distributions {
250*0f4c859eSApple OSS Distributions int kr;
251*0f4c859eSApple OSS Distributions int ret;
252*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
253*0f4c859eSApple OSS Distributions mach_vm_size_t size = 2 * PAGE_SIZE; /* will be rounded up to some superpage size */
254*0f4c859eSApple OSS Distributions
255*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_ANY);
256*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
257*0f4c859eSApple OSS Distributions return ret;
258*0f4c859eSApple OSS Distributions }
259*0f4c859eSApple OSS Distributions if (!(ret = check_addr0(addr, "mach_vm_allocate"))) {
260*0f4c859eSApple OSS Distributions return ret;
261*0f4c859eSApple OSS Distributions }
262*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
263*0f4c859eSApple OSS Distributions return ret;
264*0f4c859eSApple OSS Distributions }
265*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
266*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
267*0f4c859eSApple OSS Distributions return ret;
268*0f4c859eSApple OSS Distributions }
269*0f4c859eSApple OSS Distributions if (!(ret = check_nr(addr, size, NULL))) {
270*0f4c859eSApple OSS Distributions return ret;
271*0f4c859eSApple OSS Distributions }
272*0f4c859eSApple OSS Distributions return TRUE;
273*0f4c859eSApple OSS Distributions }
274*0f4c859eSApple OSS Distributions
275*0f4c859eSApple OSS Distributions /*
276*0f4c859eSApple OSS Distributions * If we allocate a 2 MB superpage read-write at a 2 MB aligned address,
277*0f4c859eSApple OSS Distributions * - the call should succeed
278*0f4c859eSApple OSS Distributions * - return the address we wished for
279*0f4c859eSApple OSS Distributions * - the memory should be readable and writable
280*0f4c859eSApple OSS Distributions * If we deallocate it,
281*0f4c859eSApple OSS Distributions * - the call should succeed
282*0f4c859eSApple OSS Distributions * - make the memory inaccessible
283*0f4c859eSApple OSS Distributions */
284*0f4c859eSApple OSS Distributions boolean_t
test_allocatefixed()285*0f4c859eSApple OSS Distributions test_allocatefixed()
286*0f4c859eSApple OSS Distributions {
287*0f4c859eSApple OSS Distributions int kr;
288*0f4c859eSApple OSS Distributions int ret;
289*0f4c859eSApple OSS Distributions mach_vm_address_t addr = FIXED_ADDRESS1;
290*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
291*0f4c859eSApple OSS Distributions
292*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_SUPERPAGE_SIZE_2MB);
293*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
294*0f4c859eSApple OSS Distributions return ret;
295*0f4c859eSApple OSS Distributions }
296*0f4c859eSApple OSS Distributions if (!(ret = check_addr(addr, FIXED_ADDRESS1, "mach_vm_allocate"))) {
297*0f4c859eSApple OSS Distributions return ret;
298*0f4c859eSApple OSS Distributions }
299*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
300*0f4c859eSApple OSS Distributions return ret;
301*0f4c859eSApple OSS Distributions }
302*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
303*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
304*0f4c859eSApple OSS Distributions return ret;
305*0f4c859eSApple OSS Distributions }
306*0f4c859eSApple OSS Distributions if (!(ret = check_nr(addr, size, NULL))) {
307*0f4c859eSApple OSS Distributions return ret;
308*0f4c859eSApple OSS Distributions }
309*0f4c859eSApple OSS Distributions return TRUE;
310*0f4c859eSApple OSS Distributions }
311*0f4c859eSApple OSS Distributions
312*0f4c859eSApple OSS Distributions /*
313*0f4c859eSApple OSS Distributions * If we allocate a 2 MB superpage read-write at an unaligned address,
314*0f4c859eSApple OSS Distributions * - the call should fail
315*0f4c859eSApple OSS Distributions */
316*0f4c859eSApple OSS Distributions boolean_t
test_allocateunalignedfixed()317*0f4c859eSApple OSS Distributions test_allocateunalignedfixed()
318*0f4c859eSApple OSS Distributions {
319*0f4c859eSApple OSS Distributions int kr;
320*0f4c859eSApple OSS Distributions int ret;
321*0f4c859eSApple OSS Distributions mach_vm_address_t addr = FIXED_ADDRESS2;
322*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
323*0f4c859eSApple OSS Distributions
324*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_SUPERPAGE_SIZE_2MB);
325*0f4c859eSApple OSS Distributions /* is supposed to fail */
326*0f4c859eSApple OSS Distributions if ((ret = check_kr(kr, "mach_vm_allocate"))) {
327*0f4c859eSApple OSS Distributions sprintf(error, "mach_vm_allocate() should have failed");
328*0f4c859eSApple OSS Distributions return FALSE;
329*0f4c859eSApple OSS Distributions }
330*0f4c859eSApple OSS Distributions return TRUE;
331*0f4c859eSApple OSS Distributions }
332*0f4c859eSApple OSS Distributions
333*0f4c859eSApple OSS Distributions /*
334*0f4c859eSApple OSS Distributions * If we allocate an amount of memory not divisible by 2 MB as a 2 MB superpage
335*0f4c859eSApple OSS Distributions * - the call should fail
336*0f4c859eSApple OSS Distributions */
337*0f4c859eSApple OSS Distributions boolean_t
test_allocateoddsize()338*0f4c859eSApple OSS Distributions test_allocateoddsize()
339*0f4c859eSApple OSS Distributions {
340*0f4c859eSApple OSS Distributions int kr;
341*0f4c859eSApple OSS Distributions int ret;
342*0f4c859eSApple OSS Distributions mach_vm_address_t addr = FIXED_ADDRESS1;
343*0f4c859eSApple OSS Distributions mach_vm_size_t size = PAGE_SIZE; /* != 2 MB */
344*0f4c859eSApple OSS Distributions
345*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_SUPERPAGE_SIZE_2MB);
346*0f4c859eSApple OSS Distributions /* is supposed to fail */
347*0f4c859eSApple OSS Distributions if ((ret = check_kr(kr, "mach_vm_allocate"))) {
348*0f4c859eSApple OSS Distributions sprintf(error, "mach_vm_allocate() should have failed");
349*0f4c859eSApple OSS Distributions return FALSE;
350*0f4c859eSApple OSS Distributions }
351*0f4c859eSApple OSS Distributions return TRUE;
352*0f4c859eSApple OSS Distributions }
353*0f4c859eSApple OSS Distributions
354*0f4c859eSApple OSS Distributions /*
355*0f4c859eSApple OSS Distributions * If we deallocate a sub-page of a superpage,
356*0f4c859eSApple OSS Distributions * - the call should succeed
357*0f4c859eSApple OSS Distributions * - make the complete memory inaccessible
358*0f4c859eSApple OSS Distributions */
359*0f4c859eSApple OSS Distributions boolean_t
test_deallocatesubpage()360*0f4c859eSApple OSS Distributions test_deallocatesubpage()
361*0f4c859eSApple OSS Distributions {
362*0f4c859eSApple OSS Distributions int kr;
363*0f4c859eSApple OSS Distributions int ret;
364*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
365*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
366*0f4c859eSApple OSS Distributions
367*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
368*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
369*0f4c859eSApple OSS Distributions return ret;
370*0f4c859eSApple OSS Distributions }
371*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr + PAGE_SIZE, size);
372*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
373*0f4c859eSApple OSS Distributions return ret;
374*0f4c859eSApple OSS Distributions }
375*0f4c859eSApple OSS Distributions if (!(ret = check_nr(addr, size, NULL))) {
376*0f4c859eSApple OSS Distributions return ret;
377*0f4c859eSApple OSS Distributions }
378*0f4c859eSApple OSS Distributions return TRUE;
379*0f4c859eSApple OSS Distributions }
380*0f4c859eSApple OSS Distributions
381*0f4c859eSApple OSS Distributions /*
382*0f4c859eSApple OSS Distributions * If we try to allocate memory occupied by superpages as normal pages
383*0f4c859eSApple OSS Distributions * - the call should fail
384*0f4c859eSApple OSS Distributions */
385*0f4c859eSApple OSS Distributions boolean_t
test_reallocate()386*0f4c859eSApple OSS Distributions test_reallocate()
387*0f4c859eSApple OSS Distributions {
388*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0, addr2;
389*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
390*0f4c859eSApple OSS Distributions int kr, ret;
391*0f4c859eSApple OSS Distributions int i;
392*0f4c859eSApple OSS Distributions
393*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
394*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
395*0f4c859eSApple OSS Distributions return ret;
396*0f4c859eSApple OSS Distributions }
397*0f4c859eSApple OSS Distributions
398*0f4c859eSApple OSS Distributions /* attempt to allocate every sub-page of superpage */
399*0f4c859eSApple OSS Distributions for (i = 0; i < SUPERPAGE_SIZE / PAGE_SIZE; i++) {
400*0f4c859eSApple OSS Distributions addr2 = addr + i * PAGE_SIZE;
401*0f4c859eSApple OSS Distributions size = PAGE_SIZE;
402*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr2, size, 0);
403*0f4c859eSApple OSS Distributions if ((ret = check_kr(kr, "mach_vm_allocate"))) {
404*0f4c859eSApple OSS Distributions sprintf(error, "could allocate already allocated space, page %d", i);
405*0f4c859eSApple OSS Distributions mach_vm_deallocate(mach_task_self(), addr, size);
406*0f4c859eSApple OSS Distributions return FALSE;
407*0f4c859eSApple OSS Distributions }
408*0f4c859eSApple OSS Distributions }
409*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
410*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
411*0f4c859eSApple OSS Distributions return ret;
412*0f4c859eSApple OSS Distributions }
413*0f4c859eSApple OSS Distributions return TRUE;
414*0f4c859eSApple OSS Distributions }
415*0f4c859eSApple OSS Distributions
416*0f4c859eSApple OSS Distributions /*
417*0f4c859eSApple OSS Distributions * If we try to wire superpages
418*0f4c859eSApple OSS Distributions * - the call should succeed
419*0f4c859eSApple OSS Distributions * - the memory should remain readable and writable
420*0f4c859eSApple OSS Distributions */
421*0f4c859eSApple OSS Distributions boolean_t
test_wire()422*0f4c859eSApple OSS Distributions test_wire()
423*0f4c859eSApple OSS Distributions {
424*0f4c859eSApple OSS Distributions int kr;
425*0f4c859eSApple OSS Distributions int ret;
426*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
427*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
428*0f4c859eSApple OSS Distributions
429*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
430*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
431*0f4c859eSApple OSS Distributions return ret;
432*0f4c859eSApple OSS Distributions }
433*0f4c859eSApple OSS Distributions
434*0f4c859eSApple OSS Distributions kr = mach_vm_wire(mach_host_self(), mach_task_self(), addr, size, VM_PROT_WRITE | VM_PROT_READ);
435*0f4c859eSApple OSS Distributions
436*0f4c859eSApple OSS Distributions if (!geteuid()) { /* may fail as user */
437*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_wire"))) {
438*0f4c859eSApple OSS Distributions return ret;
439*0f4c859eSApple OSS Distributions }
440*0f4c859eSApple OSS Distributions }
441*0f4c859eSApple OSS Distributions
442*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
443*0f4c859eSApple OSS Distributions return ret;
444*0f4c859eSApple OSS Distributions }
445*0f4c859eSApple OSS Distributions
446*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
447*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
448*0f4c859eSApple OSS Distributions return ret;
449*0f4c859eSApple OSS Distributions }
450*0f4c859eSApple OSS Distributions
451*0f4c859eSApple OSS Distributions return TRUE;
452*0f4c859eSApple OSS Distributions }
453*0f4c859eSApple OSS Distributions
454*0f4c859eSApple OSS Distributions /*
455*0f4c859eSApple OSS Distributions * If we try to wire superpages
456*0f4c859eSApple OSS Distributions * - the call should fail
457*0f4c859eSApple OSS Distributions * - the memory should remain readable and writable
458*0f4c859eSApple OSS Distributions * Currently, superpages are always wired.
459*0f4c859eSApple OSS Distributions */
460*0f4c859eSApple OSS Distributions boolean_t
test_unwire()461*0f4c859eSApple OSS Distributions test_unwire()
462*0f4c859eSApple OSS Distributions {
463*0f4c859eSApple OSS Distributions int kr;
464*0f4c859eSApple OSS Distributions int ret;
465*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
466*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
467*0f4c859eSApple OSS Distributions
468*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
469*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
470*0f4c859eSApple OSS Distributions return ret;
471*0f4c859eSApple OSS Distributions }
472*0f4c859eSApple OSS Distributions
473*0f4c859eSApple OSS Distributions kr = mach_vm_wire(mach_host_self(), mach_task_self(), addr, size, VM_PROT_NONE);
474*0f4c859eSApple OSS Distributions if ((ret = check_kr(kr, "mach_vm_wire"))) {
475*0f4c859eSApple OSS Distributions sprintf(error, "could unwire");
476*0f4c859eSApple OSS Distributions return FALSE;
477*0f4c859eSApple OSS Distributions }
478*0f4c859eSApple OSS Distributions
479*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
480*0f4c859eSApple OSS Distributions return ret;
481*0f4c859eSApple OSS Distributions }
482*0f4c859eSApple OSS Distributions
483*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
484*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
485*0f4c859eSApple OSS Distributions return ret;
486*0f4c859eSApple OSS Distributions }
487*0f4c859eSApple OSS Distributions
488*0f4c859eSApple OSS Distributions return TRUE;
489*0f4c859eSApple OSS Distributions }
490*0f4c859eSApple OSS Distributions
491*0f4c859eSApple OSS Distributions /*
492*0f4c859eSApple OSS Distributions * If we try to write-protect superpages
493*0f4c859eSApple OSS Distributions * - the call should succeed
494*0f4c859eSApple OSS Distributions * - the memory should remain readable
495*0f4c859eSApple OSS Distributions * - the memory should not be writable
496*0f4c859eSApple OSS Distributions */
497*0f4c859eSApple OSS Distributions boolean_t
test_readonly()498*0f4c859eSApple OSS Distributions test_readonly()
499*0f4c859eSApple OSS Distributions {
500*0f4c859eSApple OSS Distributions int kr;
501*0f4c859eSApple OSS Distributions int ret;
502*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
503*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
504*0f4c859eSApple OSS Distributions
505*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
506*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
507*0f4c859eSApple OSS Distributions return ret;
508*0f4c859eSApple OSS Distributions }
509*0f4c859eSApple OSS Distributions
510*0f4c859eSApple OSS Distributions mach_vm_protect(mach_task_self(), addr, size, 0, VM_PROT_READ);
511*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_protect"))) {
512*0f4c859eSApple OSS Distributions return ret;
513*0f4c859eSApple OSS Distributions }
514*0f4c859eSApple OSS Distributions
515*0f4c859eSApple OSS Distributions if (!(ret = check_r(addr, size, NULL))) {
516*0f4c859eSApple OSS Distributions return ret;
517*0f4c859eSApple OSS Distributions }
518*0f4c859eSApple OSS Distributions if (!(ret = check_nw(addr, size))) {
519*0f4c859eSApple OSS Distributions return ret;
520*0f4c859eSApple OSS Distributions }
521*0f4c859eSApple OSS Distributions
522*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
523*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
524*0f4c859eSApple OSS Distributions return ret;
525*0f4c859eSApple OSS Distributions }
526*0f4c859eSApple OSS Distributions
527*0f4c859eSApple OSS Distributions return TRUE;
528*0f4c859eSApple OSS Distributions }
529*0f4c859eSApple OSS Distributions
530*0f4c859eSApple OSS Distributions /*
531*0f4c859eSApple OSS Distributions * If we try to write-protect a sub-page of a superpage
532*0f4c859eSApple OSS Distributions * - the call should succeed
533*0f4c859eSApple OSS Distributions * - the complete memory should remain readable
534*0f4c859eSApple OSS Distributions * - the complete memory should not be writable
535*0f4c859eSApple OSS Distributions */
536*0f4c859eSApple OSS Distributions boolean_t
test_readonlysubpage()537*0f4c859eSApple OSS Distributions test_readonlysubpage()
538*0f4c859eSApple OSS Distributions {
539*0f4c859eSApple OSS Distributions int kr;
540*0f4c859eSApple OSS Distributions int ret;
541*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
542*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
543*0f4c859eSApple OSS Distributions
544*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
545*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
546*0f4c859eSApple OSS Distributions return ret;
547*0f4c859eSApple OSS Distributions }
548*0f4c859eSApple OSS Distributions
549*0f4c859eSApple OSS Distributions mach_vm_protect(mach_task_self(), addr + PAGE_SIZE, PAGE_SIZE, 0, VM_PROT_READ);
550*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_protect"))) {
551*0f4c859eSApple OSS Distributions return ret;
552*0f4c859eSApple OSS Distributions }
553*0f4c859eSApple OSS Distributions
554*0f4c859eSApple OSS Distributions if (!(ret = check_r(addr, size, NULL))) {
555*0f4c859eSApple OSS Distributions return ret;
556*0f4c859eSApple OSS Distributions }
557*0f4c859eSApple OSS Distributions if (!(ret = check_nw(addr, size))) {
558*0f4c859eSApple OSS Distributions return ret;
559*0f4c859eSApple OSS Distributions }
560*0f4c859eSApple OSS Distributions
561*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
562*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
563*0f4c859eSApple OSS Distributions return ret;
564*0f4c859eSApple OSS Distributions }
565*0f4c859eSApple OSS Distributions
566*0f4c859eSApple OSS Distributions return TRUE;
567*0f4c859eSApple OSS Distributions }
568*0f4c859eSApple OSS Distributions
569*0f4c859eSApple OSS Distributions /*
570*0f4c859eSApple OSS Distributions * If we fork with active superpages
571*0f4c859eSApple OSS Distributions * - the parent should still be able to access the superpages
572*0f4c859eSApple OSS Distributions * - the child should not be able to access the superpages
573*0f4c859eSApple OSS Distributions */
574*0f4c859eSApple OSS Distributions boolean_t
test_fork()575*0f4c859eSApple OSS Distributions test_fork()
576*0f4c859eSApple OSS Distributions {
577*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
578*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
579*0f4c859eSApple OSS Distributions int kr, ret;
580*0f4c859eSApple OSS Distributions pid_t pid;
581*0f4c859eSApple OSS Distributions
582*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
583*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
584*0f4c859eSApple OSS Distributions return ret;
585*0f4c859eSApple OSS Distributions }
586*0f4c859eSApple OSS Distributions
587*0f4c859eSApple OSS Distributions fflush(stdout);
588*0f4c859eSApple OSS Distributions if ((pid = fork())) { /* parent */
589*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
590*0f4c859eSApple OSS Distributions return ret;
591*0f4c859eSApple OSS Distributions }
592*0f4c859eSApple OSS Distributions waitpid(pid, &ret, 0);
593*0f4c859eSApple OSS Distributions if (!ret) {
594*0f4c859eSApple OSS Distributions sprintf(error, "child could access superpage");
595*0f4c859eSApple OSS Distributions return ret;
596*0f4c859eSApple OSS Distributions }
597*0f4c859eSApple OSS Distributions } else { /* child */
598*0f4c859eSApple OSS Distributions if (!(ret = check_nr(addr, size, NULL))) {
599*0f4c859eSApple OSS Distributions exit(ret);
600*0f4c859eSApple OSS Distributions }
601*0f4c859eSApple OSS Distributions exit(TRUE);
602*0f4c859eSApple OSS Distributions }
603*0f4c859eSApple OSS Distributions
604*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
605*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
606*0f4c859eSApple OSS Distributions return ret;
607*0f4c859eSApple OSS Distributions }
608*0f4c859eSApple OSS Distributions return TRUE;
609*0f4c859eSApple OSS Distributions }
610*0f4c859eSApple OSS Distributions
611*0f4c859eSApple OSS Distributions /*
612*0f4c859eSApple OSS Distributions * Doing file I/O with superpages
613*0f4c859eSApple OSS Distributions * - should succeed
614*0f4c859eSApple OSS Distributions * - should behave the same as with base pages (i.e. no bad data)
615*0f4c859eSApple OSS Distributions */
616*0f4c859eSApple OSS Distributions #define FILENAME "/System/Library/Kernels/kernel"
617*0f4c859eSApple OSS Distributions boolean_t
test_fileio()618*0f4c859eSApple OSS Distributions test_fileio()
619*0f4c859eSApple OSS Distributions {
620*0f4c859eSApple OSS Distributions mach_vm_address_t addr1 = 0;
621*0f4c859eSApple OSS Distributions mach_vm_address_t addr2 = 0;
622*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
623*0f4c859eSApple OSS Distributions int kr, ret;
624*0f4c859eSApple OSS Distributions int fd;
625*0f4c859eSApple OSS Distributions unsigned int bytes;
626*0f4c859eSApple OSS Distributions
627*0f4c859eSApple OSS Distributions /* allocate one superpage */
628*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr1, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
629*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate (1)"))) {
630*0f4c859eSApple OSS Distributions return ret;
631*0f4c859eSApple OSS Distributions }
632*0f4c859eSApple OSS Distributions
633*0f4c859eSApple OSS Distributions /* allocate base pages (superpage-sized) */
634*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr2, size, VM_FLAGS_ANYWHERE);
635*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate (2)"))) {
636*0f4c859eSApple OSS Distributions return ret;
637*0f4c859eSApple OSS Distributions }
638*0f4c859eSApple OSS Distributions
639*0f4c859eSApple OSS Distributions if ((fd = open(FILENAME, O_RDONLY)) < 0) {
640*0f4c859eSApple OSS Distributions sprintf(error, "couldn't open %s", FILENAME);
641*0f4c859eSApple OSS Distributions return FALSE;
642*0f4c859eSApple OSS Distributions }
643*0f4c859eSApple OSS Distributions fcntl(fd, F_NOCACHE, 1);
644*0f4c859eSApple OSS Distributions /* read kernel into superpage */
645*0f4c859eSApple OSS Distributions if ((bytes = read(fd, (void*)(uintptr_t)addr1, SUPERPAGE_SIZE)) < SUPERPAGE_SIZE) {
646*0f4c859eSApple OSS Distributions sprintf(error, "short read (1)");
647*0f4c859eSApple OSS Distributions return FALSE;
648*0f4c859eSApple OSS Distributions }
649*0f4c859eSApple OSS Distributions lseek(fd, 0, SEEK_SET);
650*0f4c859eSApple OSS Distributions /* read kernel into base pages */
651*0f4c859eSApple OSS Distributions if ((bytes = read(fd, (void*)(uintptr_t)addr2, SUPERPAGE_SIZE)) < SUPERPAGE_SIZE) {
652*0f4c859eSApple OSS Distributions sprintf(error, "short read (2)");
653*0f4c859eSApple OSS Distributions return FALSE;
654*0f4c859eSApple OSS Distributions }
655*0f4c859eSApple OSS Distributions close(fd);
656*0f4c859eSApple OSS Distributions
657*0f4c859eSApple OSS Distributions /* compare */
658*0f4c859eSApple OSS Distributions if (memcmp((void*)(uintptr_t)addr1, (void*)(uintptr_t)addr2, bytes)) {
659*0f4c859eSApple OSS Distributions sprintf(error, "read data corrupt");
660*0f4c859eSApple OSS Distributions return FALSE;
661*0f4c859eSApple OSS Distributions }
662*0f4c859eSApple OSS Distributions
663*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr1, size);
664*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate (1)"))) {
665*0f4c859eSApple OSS Distributions return ret;
666*0f4c859eSApple OSS Distributions }
667*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr2, size);
668*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate (2)"))) {
669*0f4c859eSApple OSS Distributions return ret;
670*0f4c859eSApple OSS Distributions }
671*0f4c859eSApple OSS Distributions return TRUE;
672*0f4c859eSApple OSS Distributions }
673*0f4c859eSApple OSS Distributions
674*0f4c859eSApple OSS Distributions /*
675*0f4c859eSApple OSS Distributions * The mmap() interface should work just as well!
676*0f4c859eSApple OSS Distributions */
677*0f4c859eSApple OSS Distributions boolean_t
test_mmap()678*0f4c859eSApple OSS Distributions test_mmap()
679*0f4c859eSApple OSS Distributions {
680*0f4c859eSApple OSS Distributions int kr, ret;
681*0f4c859eSApple OSS Distributions uintptr_t addr = 0;
682*0f4c859eSApple OSS Distributions int size = SUPERPAGE_SIZE;
683*0f4c859eSApple OSS Distributions
684*0f4c859eSApple OSS Distributions addr = (uintptr_t)mmap((void*)addr, size, PROT_READ, MAP_ANON | MAP_PRIVATE, VM_FLAGS_SUPERPAGE_SIZE_2MB, 0);
685*0f4c859eSApple OSS Distributions if (addr == (uintptr_t)MAP_FAILED) {
686*0f4c859eSApple OSS Distributions sprintf(error, "mmap()");
687*0f4c859eSApple OSS Distributions return FALSE;
688*0f4c859eSApple OSS Distributions }
689*0f4c859eSApple OSS Distributions if (!(ret = check_addr0(addr, "mach_vm_allocate"))) {
690*0f4c859eSApple OSS Distributions return ret;
691*0f4c859eSApple OSS Distributions }
692*0f4c859eSApple OSS Distributions if (!(ret = check_align(addr))) {
693*0f4c859eSApple OSS Distributions return ret;
694*0f4c859eSApple OSS Distributions }
695*0f4c859eSApple OSS Distributions if (!(ret = check_r(addr, SUPERPAGE_SIZE, NULL))) {
696*0f4c859eSApple OSS Distributions return ret;
697*0f4c859eSApple OSS Distributions }
698*0f4c859eSApple OSS Distributions if (!(ret = check_nw(addr, SUPERPAGE_SIZE))) {
699*0f4c859eSApple OSS Distributions return ret;
700*0f4c859eSApple OSS Distributions }
701*0f4c859eSApple OSS Distributions kr = munmap((void*)addr, size);
702*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "munmap"))) {
703*0f4c859eSApple OSS Distributions return ret;
704*0f4c859eSApple OSS Distributions }
705*0f4c859eSApple OSS Distributions if (!(ret = check_nr(addr, size, NULL))) {
706*0f4c859eSApple OSS Distributions return ret;
707*0f4c859eSApple OSS Distributions }
708*0f4c859eSApple OSS Distributions
709*0f4c859eSApple OSS Distributions return TRUE;
710*0f4c859eSApple OSS Distributions }
711*0f4c859eSApple OSS Distributions
712*0f4c859eSApple OSS Distributions /*
713*0f4c859eSApple OSS Distributions * Tests one allocation/deallocaton cycle; used in a loop this tests for leaks
714*0f4c859eSApple OSS Distributions */
715*0f4c859eSApple OSS Distributions boolean_t
test_alloc_dealloc()716*0f4c859eSApple OSS Distributions test_alloc_dealloc()
717*0f4c859eSApple OSS Distributions {
718*0f4c859eSApple OSS Distributions mach_vm_address_t addr = 0;
719*0f4c859eSApple OSS Distributions mach_vm_size_t size = SUPERPAGE_SIZE;
720*0f4c859eSApple OSS Distributions int kr, ret;
721*0f4c859eSApple OSS Distributions
722*0f4c859eSApple OSS Distributions kr = mach_vm_allocate(mach_task_self(), &addr, size, VM_FLAGS_ANYWHERE | VM_FLAGS_SUPERPAGE_SIZE_2MB);
723*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_allocate"))) {
724*0f4c859eSApple OSS Distributions return ret;
725*0f4c859eSApple OSS Distributions }
726*0f4c859eSApple OSS Distributions if (!(ret = check_addr0(addr, "mach_vm_allocate"))) {
727*0f4c859eSApple OSS Distributions return ret;
728*0f4c859eSApple OSS Distributions }
729*0f4c859eSApple OSS Distributions if (!(ret = check_align(addr))) {
730*0f4c859eSApple OSS Distributions return ret;
731*0f4c859eSApple OSS Distributions }
732*0f4c859eSApple OSS Distributions if (!(ret = check_rw(addr, size))) {
733*0f4c859eSApple OSS Distributions return ret;
734*0f4c859eSApple OSS Distributions }
735*0f4c859eSApple OSS Distributions kr = mach_vm_deallocate(mach_task_self(), addr, size);
736*0f4c859eSApple OSS Distributions if (!(ret = check_kr(kr, "mach_vm_deallocate"))) {
737*0f4c859eSApple OSS Distributions return ret;
738*0f4c859eSApple OSS Distributions }
739*0f4c859eSApple OSS Distributions return TRUE;
740*0f4c859eSApple OSS Distributions }
741*0f4c859eSApple OSS Distributions
742*0f4c859eSApple OSS Distributions test_t test[] = {
743*0f4c859eSApple OSS Distributions { "allocate one page anywhere", test_allocate },
744*0f4c859eSApple OSS Distributions { "deallocate a page", test_deallocate },
745*0f4c859eSApple OSS Distributions { "allocate a SIZE_ANY page anywhere", test_allocate_size_any },
746*0f4c859eSApple OSS Distributions { "allocate one page at a fixed address", test_allocatefixed },
747*0f4c859eSApple OSS Distributions { "allocate one page at an unaligned fixed address", test_allocateunalignedfixed },
748*0f4c859eSApple OSS Distributions { "deallocate sub-page", test_deallocatesubpage },
749*0f4c859eSApple OSS Distributions { "allocate already allocated subpage", test_reallocate },
750*0f4c859eSApple OSS Distributions { "wire a page", test_wire },
751*0f4c859eSApple OSS Distributions { "unwire a page", test_unwire },
752*0f4c859eSApple OSS Distributions { "make page readonly", test_readonly },
753*0f4c859eSApple OSS Distributions { "make sub-page readonly", test_readonlysubpage },
754*0f4c859eSApple OSS Distributions { "file I/O", test_fileio },
755*0f4c859eSApple OSS Distributions { "mmap()", test_mmap },
756*0f4c859eSApple OSS Distributions { "fork", test_fork },
757*0f4c859eSApple OSS Distributions };
758*0f4c859eSApple OSS Distributions #define TESTS ((int)(sizeof(test)/sizeof(*test)))
759*0f4c859eSApple OSS Distributions
760*0f4c859eSApple OSS Distributions boolean_t
testit(int i)761*0f4c859eSApple OSS Distributions testit(int i)
762*0f4c859eSApple OSS Distributions {
763*0f4c859eSApple OSS Distributions boolean_t ret;
764*0f4c859eSApple OSS Distributions
765*0f4c859eSApple OSS Distributions error[0] = 0;
766*0f4c859eSApple OSS Distributions printf("Test #%d \"%s\"...", i + 1, test[i].description);
767*0f4c859eSApple OSS Distributions ret = test[i].fn();
768*0f4c859eSApple OSS Distributions if (ret) {
769*0f4c859eSApple OSS Distributions printf("OK\n");
770*0f4c859eSApple OSS Distributions } else {
771*0f4c859eSApple OSS Distributions printf("FAILED!");
772*0f4c859eSApple OSS Distributions if (error[0]) {
773*0f4c859eSApple OSS Distributions printf(" (%s)\n", error);
774*0f4c859eSApple OSS Distributions } else {
775*0f4c859eSApple OSS Distributions printf("\n");
776*0f4c859eSApple OSS Distributions }
777*0f4c859eSApple OSS Distributions }
778*0f4c859eSApple OSS Distributions }
779*0f4c859eSApple OSS Distributions
780*0f4c859eSApple OSS Distributions int
main(int argc,char ** argv)781*0f4c859eSApple OSS Distributions main(int argc, char **argv)
782*0f4c859eSApple OSS Distributions {
783*0f4c859eSApple OSS Distributions int i;
784*0f4c859eSApple OSS Distributions uint64_t time1, time2;
785*0f4c859eSApple OSS Distributions
786*0f4c859eSApple OSS Distributions int mode = 0;
787*0f4c859eSApple OSS Distributions if (argc > 1) {
788*0f4c859eSApple OSS Distributions if (!strcmp(argv[1], "-h")) {
789*0f4c859eSApple OSS Distributions printf("Usage: %s <mode>\n", argv[0]);
790*0f4c859eSApple OSS Distributions printf("\tmode = 0: test all cases\n");
791*0f4c859eSApple OSS Distributions printf("\tmode = -1: allocate/deallocate until failure\n");
792*0f4c859eSApple OSS Distributions printf("\tmode > 0: run test <tmode>\n");
793*0f4c859eSApple OSS Distributions exit(0);
794*0f4c859eSApple OSS Distributions }
795*0f4c859eSApple OSS Distributions mode = atoi(argv[1]);
796*0f4c859eSApple OSS Distributions }
797*0f4c859eSApple OSS Distributions
798*0f4c859eSApple OSS Distributions /* install SIGBUS handler */
799*0f4c859eSApple OSS Distributions struct sigaction my_sigaction;
800*0f4c859eSApple OSS Distributions my_sigaction.sa_handler = test_signal_handler;
801*0f4c859eSApple OSS Distributions my_sigaction.sa_flags = SA_RESTART;
802*0f4c859eSApple OSS Distributions my_sigaction.sa_mask = 0;
803*0f4c859eSApple OSS Distributions sigaction( SIGBUS, &my_sigaction, NULL );
804*0f4c859eSApple OSS Distributions sigaction( SIGSEGV, &my_sigaction, NULL );
805*0f4c859eSApple OSS Distributions
806*0f4c859eSApple OSS Distributions if (mode > 0) { /* one specific test */
807*0f4c859eSApple OSS Distributions testit(mode - 1);
808*0f4c859eSApple OSS Distributions }
809*0f4c859eSApple OSS Distributions
810*0f4c859eSApple OSS Distributions if (mode == 0) { /* test all cases */
811*0f4c859eSApple OSS Distributions printf("Running %d tests:\n", TESTS);
812*0f4c859eSApple OSS Distributions for (i = 0; i < TESTS; i++) {
813*0f4c859eSApple OSS Distributions testit(i);
814*0f4c859eSApple OSS Distributions }
815*0f4c859eSApple OSS Distributions }
816*0f4c859eSApple OSS Distributions if (mode == -1) { /* alloc/dealloc */
817*0f4c859eSApple OSS Distributions boolean_t ret;
818*0f4c859eSApple OSS Distributions do {
819*0f4c859eSApple OSS Distributions ret = test_alloc_dealloc(TRUE);
820*0f4c859eSApple OSS Distributions printf(".");
821*0f4c859eSApple OSS Distributions fflush(stdout);
822*0f4c859eSApple OSS Distributions } while (ret);
823*0f4c859eSApple OSS Distributions if (error[0]) {
824*0f4c859eSApple OSS Distributions printf(" (%s)\n", error);
825*0f4c859eSApple OSS Distributions }
826*0f4c859eSApple OSS Distributions }
827*0f4c859eSApple OSS Distributions return 0;
828*0f4c859eSApple OSS Distributions }
829