File:  [Qemu by Fabrice Bellard] / qemu / tests / test-mmap.c
Revision 1.1.1.3 (vendor branch): download - view: text, annotated - select for diffs
Tue Apr 24 18:57:15 2018 UTC (3 years, 3 months ago) by root
Branches: qemu, MAIN
CVS tags: qemu1001, qemu1000, qemu0151, HEAD
qemu 0.15.1

    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, see <http://www.gnu.org/licenses/>.
   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: 		fail_unless (p3 != MAP_FAILED);
  168: 
  169: 		/* Check if the mmaped areas collide.  */
  170: 		if (p3 < p2 
  171: 		    && (p3 + nlen) > p2)
  172: 			fail_unless (0);
  173: 
  174: 		memcpy (dummybuf, p3, pagesize);
  175: 
  176: 		/* Make sure we get pages aligned with the pagesize. The
  177: 		   target expects this.  */
  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 accessible 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 accessible 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: }

unix.superglobalmegacorp.com