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