|
|
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.