2 * Small test program to verify simulated mmap behaviour.
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 being the pagesize.
8 * Copyright (c) 2007 AXIS Communications AB
9 * Written by Edgar E. Iglesias.
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.
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.
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/>.
35 #define fail_unless(x) \
39 fprintf (stderr, "FAILED at %s:%d\n", __FILE__, __LINE__); \
40 exit (EXIT_FAILURE); \
44 unsigned char *dummybuf
;
45 static unsigned int pagesize
;
46 static unsigned int pagemask
;
50 void check_aligned_anonymous_unfixed_mmaps(void)
60 fprintf (stderr
, "%s", __func__
);
61 for (i
= 0; i
< 0x1fff; i
++)
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);
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
);
85 D(printf ("p=%x\n", p
));
86 fail_unless ((p
& pagemask
) == 0);
88 fail_unless ((p
& pagemask
) == 0);
90 fail_unless ((p
& pagemask
) == 0);
92 fail_unless ((p
& pagemask
) == 0);
94 fail_unless ((p
& pagemask
) == 0);
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
);
109 fprintf (stderr
, " passed\n");
112 void check_large_anonymous_unfixed_mmap(void)
118 fprintf (stderr
, "%s", __func__
);
121 p1
= mmap(NULL
, len
, PROT_READ
,
122 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
124 /* Make sure we get pages aligned with the pagesize. The
125 target expects this. */
126 fail_unless (p1
!= MAP_FAILED
);
128 fail_unless ((p
& pagemask
) == 0);
130 /* Make sure we can read from the entire area. */
131 memcpy (dummybuf
, p1
, pagesize
);
133 fprintf (stderr
, " passed\n");
136 void check_aligned_anonymous_unfixed_colliding_mmaps(void)
144 fprintf (stderr
, "%s", __func__
);
145 for (i
= 0; i
< 0x2fff; i
++)
148 p1
= mmap(NULL
, pagesize
, PROT_READ
,
149 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
150 fail_unless (p1
!= MAP_FAILED
);
152 fail_unless ((p
& pagemask
) == 0);
153 memcpy (dummybuf
, p1
, pagesize
);
155 p2
= mmap(NULL
, pagesize
, PROT_READ
,
156 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
157 fail_unless (p2
!= MAP_FAILED
);
159 fail_unless ((p
& pagemask
) == 0);
160 memcpy (dummybuf
, p2
, pagesize
);
163 munmap (p1
, pagesize
);
165 p3
= mmap(NULL
, nlen
, PROT_READ
,
166 MAP_PRIVATE
| MAP_ANONYMOUS
, -1, 0);
167 fail_unless (p3
!= MAP_FAILED
);
169 /* Check if the mmaped areas collide. */
174 memcpy (dummybuf
, p3
, pagesize
);
176 /* Make sure we get pages aligned with the pagesize. The
177 target expects this. */
179 fail_unless ((p
& pagemask
) == 0);
180 munmap (p2
, pagesize
);
183 fprintf (stderr
, " passed\n");
186 void check_aligned_anonymous_fixed_mmaps(void)
193 /* Find a suitable address to start with. */
194 addr
= mmap(NULL
, pagesize
* 40, PROT_READ
| PROT_WRITE
,
195 MAP_PRIVATE
| MAP_ANONYMOUS
,
197 fprintf (stderr
, "%s addr=%p", __func__
, addr
);
198 fail_unless (addr
!= MAP_FAILED
);
200 for (i
= 0; i
< 40; i
++)
202 /* Create submaps within our unfixed map. */
203 p1
= mmap(addr
, pagesize
, PROT_READ
,
204 MAP_PRIVATE
| MAP_ANONYMOUS
| MAP_FIXED
,
206 /* Make sure we get pages aligned with the pagesize.
207 The target expects this. */
209 fail_unless (p1
== addr
);
210 fail_unless ((p
& pagemask
) == 0);
211 memcpy (dummybuf
, p1
, pagesize
);
212 munmap (p1
, pagesize
);
215 fprintf (stderr
, " passed\n");
218 void check_aligned_anonymous_fixed_mmaps_collide_with_host(void)
225 /* Find a suitable address to start with. Right were the x86 hosts
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.");
231 for (i
= 0; i
< 20; i
++)
233 /* Create submaps within our unfixed map. */
234 p1
= mmap(addr
, pagesize
, PROT_READ
| PROT_WRITE
,
235 MAP_PRIVATE
| MAP_ANONYMOUS
| MAP_FIXED
,
237 /* Make sure we get pages aligned with the pagesize.
238 The target expects this. */
240 fail_unless (p1
== addr
);
241 fail_unless ((p
& pagemask
) == 0);
242 memcpy (p1
, dummybuf
, pagesize
);
243 munmap (p1
, pagesize
);
246 fprintf (stderr
, " passed\n");
249 void check_file_unfixed_mmaps(void)
251 unsigned int *p1
, *p2
, *p3
;
255 fprintf (stderr
, "%s", __func__
);
256 for (i
= 0; i
< 0x10; i
++)
261 p1
= mmap(NULL
, len
, PROT_READ
,
264 p2
= mmap(NULL
, len
, PROT_READ
,
267 p3
= mmap(NULL
, len
, PROT_READ
,
269 test_fd
, pagesize
* 2);
271 fail_unless (p1
!= MAP_FAILED
);
272 fail_unless (p2
!= MAP_FAILED
);
273 fail_unless (p3
!= MAP_FAILED
);
275 /* Make sure we get pages aligned with the pagesize. The
276 target expects this. */
278 fail_unless ((p
& pagemask
) == 0);
280 fail_unless ((p
& pagemask
) == 0);
282 fail_unless ((p
& pagemask
) == 0);
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
));
290 memcpy (dummybuf
, p1
, pagesize
);
291 memcpy (dummybuf
, p2
, pagesize
);
292 memcpy (dummybuf
, p3
, pagesize
);
297 fprintf (stderr
, " passed\n");
300 void check_file_unfixed_eof_mmaps(void)
307 fprintf (stderr
, "%s", __func__
);
308 for (i
= 0; i
< 0x10; i
++)
310 p1
= mmap(NULL
, pagesize
, PROT_READ
,
313 (test_fsize
- sizeof *p1
) & ~pagemask
);
315 fail_unless (p1
!= MAP_FAILED
);
317 /* Make sure we get pages aligned with the pagesize. The
318 target expects this. */
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
));
325 /* Verify that the end of page is accessible and zeroed. */
327 fail_unless (cp
[pagesize
- 4] == 0);
328 munmap (p1
, pagesize
);
330 fprintf (stderr
, " passed\n");
333 void check_file_fixed_eof_mmaps(void)
341 /* Find a suitable address to start with. */
342 addr
= mmap(NULL
, pagesize
* 44, PROT_READ
,
343 MAP_PRIVATE
| MAP_ANONYMOUS
,
346 fprintf (stderr
, "%s addr=%p", __func__
, (void *)addr
);
347 fail_unless (addr
!= MAP_FAILED
);
349 for (i
= 0; i
< 0x10; i
++)
351 /* Create submaps within our unfixed map. */
352 p1
= mmap(addr
, pagesize
, PROT_READ
,
353 MAP_PRIVATE
| MAP_FIXED
,
355 (test_fsize
- sizeof *p1
) & ~pagemask
);
357 fail_unless (p1
!= MAP_FAILED
);
359 /* Make sure we get pages aligned with the pagesize. The
360 target expects this. */
362 fail_unless ((p
& pagemask
) == 0);
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
));
368 /* Verify that the end of page is accessible and zeroed. */
370 fail_unless (cp
[pagesize
- 4] == 0);
371 munmap (p1
, pagesize
);
374 fprintf (stderr
, " passed\n");
377 void check_file_fixed_mmaps(void)
380 unsigned int *p1
, *p2
, *p3
, *p4
;
383 /* Find a suitable address to start with. */
384 addr
= mmap(NULL
, pagesize
* 40 * 4, PROT_READ
,
385 MAP_PRIVATE
| MAP_ANONYMOUS
,
387 fprintf (stderr
, "%s addr=%p", __func__
, (void *)addr
);
388 fail_unless (addr
!= MAP_FAILED
);
390 for (i
= 0; i
< 40; i
++)
392 p1
= mmap(addr
, pagesize
, PROT_READ
,
393 MAP_PRIVATE
| MAP_FIXED
,
395 p2
= mmap(addr
+ pagesize
, pagesize
, PROT_READ
,
396 MAP_PRIVATE
| MAP_FIXED
,
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);
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);
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
));
418 memcpy (dummybuf
, p1
, pagesize
);
419 memcpy (dummybuf
, p2
, pagesize
);
420 memcpy (dummybuf
, p3
, pagesize
);
421 memcpy (dummybuf
, p4
, pagesize
);
423 munmap (p1
, pagesize
);
424 munmap (p2
, pagesize
);
425 munmap (p3
, pagesize
);
426 munmap (p4
, pagesize
);
427 addr
+= pagesize
* 4;
429 fprintf (stderr
, " passed\n");
432 void checked_write(int fd
, const void *buf
, size_t count
)
434 ssize_t rc
= write(fd
, buf
, count
);
435 fail_unless(rc
== count
);
438 int main(int argc
, char **argv
)
440 char tempname
[] = "/tmp/.cmmapXXXXXX";
443 /* Trust the first argument, otherwise probe the system for our
446 pagesize
= strtoul(argv
[1], NULL
, 0);
448 pagesize
= sysconf(_SC_PAGESIZE
);
450 /* Assume pagesize is a power of two. */
451 pagemask
= pagesize
- 1;
452 dummybuf
= malloc (pagesize
);
453 printf ("pagesize=%u pagemask=%x\n", pagesize
, pagemask
);
455 test_fd
= mkstemp(tempname
);
458 /* Fill the file with int's counting from zero and up. */
459 for (i
= 0; i
< (pagesize
* 4) / sizeof i
; i
++) {
460 checked_write(test_fd
, &i
, sizeof i
);
463 /* Append a few extra writes to make the file end at non
465 checked_write(test_fd
, &i
, sizeof i
); i
++;
466 checked_write(test_fd
, &i
, sizeof i
); i
++;
467 checked_write(test_fd
, &i
, sizeof i
); i
++;
469 test_fsize
= lseek(test_fd
, 0, SEEK_CUR
);
472 check_aligned_anonymous_unfixed_mmaps();
473 check_aligned_anonymous_unfixed_colliding_mmaps();
474 check_aligned_anonymous_fixed_mmaps();
475 check_file_unfixed_mmaps();
476 check_file_fixed_mmaps();
477 check_file_fixed_eof_mmaps();
478 check_file_unfixed_eof_mmaps();
480 /* Fails at the moment. */
481 /* check_aligned_anonymous_fixed_mmaps_collide_with_host(); */