1 /* $OpenBSD: mmap_hint.c,v 1.5 2017/07/13 11:24:58 bluhm Exp $ */ 2 /* 3 * Copyright (c) 2011 Ariane van der Steldt <ariane@stack.nl> 4 * 5 * Permission to use, copy, modify, and distribute this software for any 6 * purpose with or without fee is hereby granted, provided that the above 7 * copyright notice and this permission notice appear in all copies. 8 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 */ 17 18 #include <sys/param.h> 19 #include <sys/types.h> 20 #include <sys/mman.h> 21 #include <sys/tree.h> 22 #include <machine/pmap.h> 23 #include <machine/vmparam.h> 24 #include <err.h> 25 #include <sysexits.h> 26 #include <stdio.h> 27 28 #define MAX_HINT_DIST (2UL * 1024 * 1024 * 1024) 29 30 int errors = 0; 31 32 void * 33 mmap_hint(void *hint) 34 { 35 void *p; 36 size_t delta; 37 38 p = mmap(hint, 1, PROT_READ|PROT_WRITE, MAP_ANON|MAP_PRIVATE, -1, 0); 39 if (p == MAP_FAILED) { 40 warn("mmap(addr=%p, len=1) failed", hint); 41 errors++; 42 return MAP_FAILED; 43 } else if (p == NULL) { 44 warnx("mmap(addr=%p, len=1) mapped at address 0", hint); 45 errors++; 46 return MAP_FAILED; 47 } else 48 fprintf(stderr, " -> %p\n", p); 49 50 if (hint > p) 51 delta = hint - p; 52 else 53 delta = p - hint; 54 55 if (hint != NULL && delta > MAX_HINT_DIST) { 56 warnx("hinted allocation more than %#zx bytes away from hint: " 57 "hint %p, result %p", delta, hint, p); 58 errors++; 59 return MAP_FAILED; 60 } 61 return p; 62 } 63 64 int 65 main() 66 { 67 void *p, *hint; 68 69 /* Check that unhinted allocation works properly. */ 70 hint = NULL; 71 fprintf(stderr, "1: Checking hint %p mmap\n", hint); 72 p = mmap_hint(hint); 73 74 /* Check hinted allocation at top of map. */ 75 hint = (void *)((VM_MAXUSER_ADDRESS & ~PAGE_MASK) - PAGE_SIZE); 76 fprintf(stderr, "2: Checking hint page below " 77 "VM_MAXUSER_ADDRESS %p mmap\n", hint); 78 p = mmap_hint(hint); 79 80 /* Check hinted allocation at bottom of map. */ 81 hint = (void *)VM_MIN_ADDRESS; 82 fprintf(stderr, "3: Checking hint VM_MIN_ADDRESS %p mmap\n", hint); 83 p = mmap_hint(hint); 84 85 /* 86 * Check that hinted allocation doesn't overwrite existing allocation. 87 */ 88 if (p == MAP_FAILED) { 89 fprintf(stderr, "4: Skipping test: required previous test " 90 "to succeed"); 91 goto skip4; 92 } 93 hint = p; 94 fprintf(stderr, "4: Checking hint %p mmap, which is in use\n", hint); 95 p = mmap_hint(hint); 96 if (p == hint) { 97 warnx("hinted allocation %p overwrites previous allocation %p", 98 hint, p); 99 errors++; 100 } 101 102 skip4: 103 return errors; 104 } 105