Commit e1ffb0f18f01dfedbff344bfeaf85ef9bd2084c4

Authored by edgar_igl
1 parent bebb39d4

Add a tests for user-mode mmap


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