|
|
1.1 root 1: /*
2: * Small test program to verify simulated mmap behaviour.
3: *
4: * When running qemu-linux-user with the -p flag, you may need to tell
5: * this test program about the pagesize because getpagesize() will not reflect
6: * the -p choice. Simply pass one argument beeing the pagesize.
7: *
8: * Copyright (c) 2007 AXIS Communications AB
9: * Written by Edgar E. Iglesias.
10: *
11: * This program is free software; you can redistribute it and/or modify
12: * it under the terms of the GNU General Public License as published by
13: * the Free Software Foundation; either version 2 of the License, or
14: * (at your option) any later version.
15: *
16: * This program is distributed in the hope that it will be useful,
17: * but WITHOUT ANY WARRANTY; without even the implied warranty of
18: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19: * GNU General Public License for more details.
20: *
21: * You should have received a copy of the GNU General Public License
22: * along with this program; if not, write to the Free Software
23: * Foundation, Inc., 51 Franklin Street - Fifth Floor, Boston,
24: * MA 02110-1301, USA.
25: */
26:
27: #include <stdio.h>
28: #include <stdlib.h>
29: #include <stdint.h>
30: #include <string.h>
31: #include <unistd.h>
32:
33: #include <sys/mman.h>
34:
35: #define D(x)
36:
37: #define fail_unless(x) \
38: do \
39: { \
40: if (!(x)) { \
41: fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
42: exit (EXIT_FAILURE); \
43: } \
44: } while (0);
45:
46: unsigned char *dummybuf;
47: static unsigned int pagesize;
48: static unsigned int pagemask;
49: int test_fd;
50: size_t test_fsize;
51:
52: void check_aligned_anonymous_unfixed_mmaps(void)
53: {
54: void *p1;
55: void *p2;
56: void *p3;
57: void *p4;
58: void *p5;
59: uintptr_t p;
60: int i;
61:
62: fprintf (stderr, "%s", __func__);
63: for (i = 0; i < 0x1fff; i++)
64: {
65: size_t len;
66:
67: len = pagesize + (pagesize * i & 7);
68: p1 = mmap(NULL, len, PROT_READ,
69: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
70: p2 = mmap(NULL, len, PROT_READ,
71: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
72: p3 = mmap(NULL, len, PROT_READ,
73: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
74: p4 = mmap(NULL, len, PROT_READ,
75: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
76: p5 = mmap(NULL, len, PROT_READ,
77: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
78:
79: /* Make sure we get pages aligned with the pagesize. The
80: target expects this. */
81: fail_unless (p1 != MAP_FAILED);
82: fail_unless (p2 != MAP_FAILED);
83: fail_unless (p3 != MAP_FAILED);
84: fail_unless (p4 != MAP_FAILED);
85: fail_unless (p5 != MAP_FAILED);
86: p = (uintptr_t) p1;
87: D(printf ("p=%x\n", p));
88: fail_unless ((p & pagemask) == 0);
89: p = (uintptr_t) p2;
90: fail_unless ((p & pagemask) == 0);
91: p = (uintptr_t) p3;
92: fail_unless ((p & pagemask) == 0);
93: p = (uintptr_t) p4;
94: fail_unless ((p & pagemask) == 0);
95: p = (uintptr_t) p5;
96: fail_unless ((p & pagemask) == 0);
97:
98: /* Make sure we can read from the entire area. */
99: memcpy (dummybuf, p1, pagesize);
100: memcpy (dummybuf, p2, pagesize);
101: memcpy (dummybuf, p3, pagesize);
102: memcpy (dummybuf, p4, pagesize);
103: memcpy (dummybuf, p5, pagesize);
104:
105: munmap (p1, len);
106: munmap (p2, len);
107: munmap (p3, len);
108: munmap (p4, len);
109: munmap (p5, len);
110: }
111: fprintf (stderr, " passed\n");
112: }
113:
114: void check_large_anonymous_unfixed_mmap(void)
115: {
116: void *p1;
117: uintptr_t p;
118: size_t len;
119:
120: fprintf (stderr, "%s", __func__);
121:
122: len = 0x02000000;
123: p1 = mmap(NULL, len, PROT_READ,
124: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
125:
126: /* Make sure we get pages aligned with the pagesize. The
127: target expects this. */
128: fail_unless (p1 != MAP_FAILED);
129: p = (uintptr_t) p1;
130: fail_unless ((p & pagemask) == 0);
131:
132: /* Make sure we can read from the entire area. */
133: memcpy (dummybuf, p1, pagesize);
134: munmap (p1, len);
135: fprintf (stderr, " passed\n");
136: }
137:
138: void check_aligned_anonymous_unfixed_colliding_mmaps(void)
139: {
140: char *p1;
141: char *p2;
142: char *p3;
143: uintptr_t p;
144: int i;
145:
146: fprintf (stderr, "%s", __func__);
147: for (i = 0; i < 0x2fff; i++)
148: {
149: int nlen;
150: p1 = mmap(NULL, pagesize, PROT_READ,
151: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
152: fail_unless (p1 != MAP_FAILED);
153: p = (uintptr_t) p1;
154: fail_unless ((p & pagemask) == 0);
155: memcpy (dummybuf, p1, pagesize);
156:
157: p2 = mmap(NULL, pagesize, PROT_READ,
158: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
159: fail_unless (p2 != MAP_FAILED);
160: p = (uintptr_t) p2;
161: fail_unless ((p & pagemask) == 0);
162: memcpy (dummybuf, p2, pagesize);
163:
164:
165: munmap (p1, pagesize);
166: nlen = pagesize * 8;
167: p3 = mmap(NULL, nlen, PROT_READ,
168: MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
169:
170: /* Check if the mmaped areas collide. */
171: if (p3 < p2
172: && (p3 + nlen) > p2)
173: fail_unless (0);
174:
175: memcpy (dummybuf, p3, pagesize);
176:
177: /* Make sure we get pages aligned with the pagesize. The
178: target expects this. */
179: fail_unless (p3 != MAP_FAILED);
180: p = (uintptr_t) p3;
181: fail_unless ((p & pagemask) == 0);
182: munmap (p2, pagesize);
183: munmap (p3, nlen);
184: }
185: fprintf (stderr, " passed\n");
186: }
187:
188: void check_aligned_anonymous_fixed_mmaps(void)
189: {
190: char *addr;
191: void *p1;
192: uintptr_t p;
193: int i;
194:
195: /* Find a suitable address to start with. */
196: addr = mmap(NULL, pagesize * 40, PROT_READ | PROT_WRITE,
197: MAP_PRIVATE | MAP_ANONYMOUS,
198: -1, 0);
199: fprintf (stderr, "%s addr=%p", __func__, addr);
200: fail_unless (addr != MAP_FAILED);
201:
202: for (i = 0; i < 40; i++)
203: {
204: /* Create submaps within our unfixed map. */
205: p1 = mmap(addr, pagesize, PROT_READ,
206: MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
207: -1, 0);
208: /* Make sure we get pages aligned with the pagesize.
209: The target expects this. */
210: p = (uintptr_t) p1;
211: fail_unless (p1 == addr);
212: fail_unless ((p & pagemask) == 0);
213: memcpy (dummybuf, p1, pagesize);
214: munmap (p1, pagesize);
215: addr += pagesize;
216: }
217: fprintf (stderr, " passed\n");
218: }
219:
220: void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
221: {
222: char *addr;
223: void *p1;
224: uintptr_t p;
225: int i;
226:
227: /* Find a suitable address to start with. Right were the x86 hosts
228: stack is. */
229: addr = ((void *)0x80000000);
230: fprintf (stderr, "%s addr=%p", __func__, addr);
231: fprintf (stderr, "FIXME: QEMU fails to track pages used by the host.");
232:
233: for (i = 0; i < 20; i++)
234: {
235: /* Create submaps within our unfixed map. */
236: p1 = mmap(addr, pagesize, PROT_READ | PROT_WRITE,
237: MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
238: -1, 0);
239: /* Make sure we get pages aligned with the pagesize.
240: The target expects this. */
241: p = (uintptr_t) p1;
242: fail_unless (p1 == addr);
243: fail_unless ((p & pagemask) == 0);
244: memcpy (p1, dummybuf, pagesize);
245: munmap (p1, pagesize);
246: addr += pagesize;
247: }
248: fprintf (stderr, " passed\n");
249: }
250:
251: void check_file_unfixed_mmaps(void)
252: {
253: unsigned int *p1, *p2, *p3;
254: uintptr_t p;
255: int i;
256:
257: fprintf (stderr, "%s", __func__);
258: for (i = 0; i < 0x10; i++)
259: {
260: size_t len;
261:
262: len = pagesize;
263: p1 = mmap(NULL, len, PROT_READ,
264: MAP_PRIVATE,
265: test_fd, 0);
266: p2 = mmap(NULL, len, PROT_READ,
267: MAP_PRIVATE,
268: test_fd, pagesize);
269: p3 = mmap(NULL, len, PROT_READ,
270: MAP_PRIVATE,
271: test_fd, pagesize * 2);
272:
273: fail_unless (p1 != MAP_FAILED);
274: fail_unless (p2 != MAP_FAILED);
275: fail_unless (p3 != MAP_FAILED);
276:
277: /* Make sure we get pages aligned with the pagesize. The
278: target expects this. */
279: p = (uintptr_t) p1;
280: fail_unless ((p & pagemask) == 0);
281: p = (uintptr_t) p2;
282: fail_unless ((p & pagemask) == 0);
283: p = (uintptr_t) p3;
284: fail_unless ((p & pagemask) == 0);
285:
286: /* Verify that the file maps was made correctly. */
287: D(printf ("p1=%d p2=%d p3=%d\n", *p1, *p2, *p3));
288: fail_unless (*p1 == 0);
289: fail_unless (*p2 == (pagesize / sizeof *p2));
290: fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
291:
292: memcpy (dummybuf, p1, pagesize);
293: memcpy (dummybuf, p2, pagesize);
294: memcpy (dummybuf, p3, pagesize);
295: munmap (p1, len);
296: munmap (p2, len);
297: munmap (p3, len);
298: }
299: fprintf (stderr, " passed\n");
300: }
301:
302: void check_file_unfixed_eof_mmaps(void)
303: {
304: char *cp;
305: unsigned int *p1;
306: uintptr_t p;
307: int i;
308:
309: fprintf (stderr, "%s", __func__);
310: for (i = 0; i < 0x10; i++)
311: {
312: p1 = mmap(NULL, pagesize, PROT_READ,
313: MAP_PRIVATE,
314: test_fd,
315: (test_fsize - sizeof *p1) & ~pagemask);
316:
317: fail_unless (p1 != MAP_FAILED);
318:
319: /* Make sure we get pages aligned with the pagesize. The
320: target expects this. */
321: p = (uintptr_t) p1;
322: fail_unless ((p & pagemask) == 0);
323: /* Verify that the file maps was made correctly. */
324: fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
325: == ((test_fsize - sizeof *p1) / sizeof *p1));
326:
327: /* Verify that the end of page is accessable and zeroed. */
328: cp = (void *) p1;
329: fail_unless (cp[pagesize - 4] == 0);
330: munmap (p1, pagesize);
331: }
332: fprintf (stderr, " passed\n");
333: }
334:
335: void check_file_fixed_eof_mmaps(void)
336: {
337: char *addr;
338: char *cp;
339: unsigned int *p1;
340: uintptr_t p;
341: int i;
342:
343: /* Find a suitable address to start with. */
344: addr = mmap(NULL, pagesize * 44, PROT_READ,
345: MAP_PRIVATE | MAP_ANONYMOUS,
346: -1, 0);
347:
348: fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
349: fail_unless (addr != MAP_FAILED);
350:
351: for (i = 0; i < 0x10; i++)
352: {
353: /* Create submaps within our unfixed map. */
354: p1 = mmap(addr, pagesize, PROT_READ,
355: MAP_PRIVATE | MAP_FIXED,
356: test_fd,
357: (test_fsize - sizeof *p1) & ~pagemask);
358:
359: fail_unless (p1 != MAP_FAILED);
360:
361: /* Make sure we get pages aligned with the pagesize. The
362: target expects this. */
363: p = (uintptr_t) p1;
364: fail_unless ((p & pagemask) == 0);
365:
366: /* Verify that the file maps was made correctly. */
367: fail_unless (p1[(test_fsize & pagemask) / sizeof *p1 - 1]
368: == ((test_fsize - sizeof *p1) / sizeof *p1));
369:
370: /* Verify that the end of page is accessable and zeroed. */
371: cp = (void *)p1;
372: fail_unless (cp[pagesize - 4] == 0);
373: munmap (p1, pagesize);
374: addr += pagesize;
375: }
376: fprintf (stderr, " passed\n");
377: }
378:
379: void check_file_fixed_mmaps(void)
380: {
381: unsigned char *addr;
382: unsigned int *p1, *p2, *p3, *p4;
383: int i;
384:
385: /* Find a suitable address to start with. */
386: addr = mmap(NULL, pagesize * 40 * 4, PROT_READ,
387: MAP_PRIVATE | MAP_ANONYMOUS,
388: -1, 0);
389: fprintf (stderr, "%s addr=%p", __func__, (void *)addr);
390: fail_unless (addr != MAP_FAILED);
391:
392: for (i = 0; i < 40; i++)
393: {
394: p1 = mmap(addr, pagesize, PROT_READ,
395: MAP_PRIVATE | MAP_FIXED,
396: test_fd, 0);
397: p2 = mmap(addr + pagesize, pagesize, PROT_READ,
398: MAP_PRIVATE | MAP_FIXED,
399: test_fd, pagesize);
400: p3 = mmap(addr + pagesize * 2, pagesize, PROT_READ,
401: MAP_PRIVATE | MAP_FIXED,
402: test_fd, pagesize * 2);
403: p4 = mmap(addr + pagesize * 3, pagesize, PROT_READ,
404: MAP_PRIVATE | MAP_FIXED,
405: test_fd, pagesize * 3);
406:
407: /* Make sure we get pages aligned with the pagesize.
408: The target expects this. */
409: fail_unless (p1 == (void *)addr);
410: fail_unless (p2 == (void *)addr + pagesize);
411: fail_unless (p3 == (void *)addr + pagesize * 2);
412: fail_unless (p4 == (void *)addr + pagesize * 3);
413:
414: /* Verify that the file maps was made correctly. */
415: fail_unless (*p1 == 0);
416: fail_unless (*p2 == (pagesize / sizeof *p2));
417: fail_unless (*p3 == ((pagesize * 2) / sizeof *p3));
418: fail_unless (*p4 == ((pagesize * 3) / sizeof *p4));
419:
420: memcpy (dummybuf, p1, pagesize);
421: memcpy (dummybuf, p2, pagesize);
422: memcpy (dummybuf, p3, pagesize);
423: memcpy (dummybuf, p4, pagesize);
424:
425: munmap (p1, pagesize);
426: munmap (p2, pagesize);
427: munmap (p3, pagesize);
428: munmap (p4, pagesize);
429: addr += pagesize * 4;
430: }
431: fprintf (stderr, " passed\n");
432: }
433:
434: int main(int argc, char **argv)
435: {
436: char tempname[] = "/tmp/.cmmapXXXXXX";
437: unsigned int i;
438:
439: /* Trust the first argument, otherwise probe the system for our
440: pagesize. */
441: if (argc > 1)
442: pagesize = strtoul(argv[1], NULL, 0);
443: else
444: pagesize = sysconf(_SC_PAGESIZE);
445:
446: /* Assume pagesize is a power of two. */
447: pagemask = pagesize - 1;
448: dummybuf = malloc (pagesize);
449: printf ("pagesize=%u pagemask=%x\n", pagesize, pagemask);
450:
451: test_fd = mkstemp(tempname);
452: unlink(tempname);
453:
454: /* Fill the file with int's counting from zero and up. */
455: for (i = 0; i < (pagesize * 4) / sizeof i; i++)
456: write (test_fd, &i, sizeof i);
457: /* Append a few extra writes to make the file end at non
458: page boundary. */
459: write (test_fd, &i, sizeof i); i++;
460: write (test_fd, &i, sizeof i); i++;
461: write (test_fd, &i, sizeof i); i++;
462:
463: test_fsize = lseek(test_fd, 0, SEEK_CUR);
464:
465: /* Run the tests. */
466: check_aligned_anonymous_unfixed_mmaps();
467: check_aligned_anonymous_unfixed_colliding_mmaps();
468: check_aligned_anonymous_fixed_mmaps();
469: check_file_unfixed_mmaps();
470: check_file_fixed_mmaps();
471: check_file_fixed_eof_mmaps();
472: check_file_unfixed_eof_mmaps();
473:
474: /* Fails at the moment. */
475: /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */
476:
477: return EXIT_SUCCESS;
478: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.