1 #include <stdio.h>
2 #include <sys/mman.h>
3 
4 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
5 
6 #define PAGE_SIZE	4096
7 #define LOW_ADDR	((void *) (1UL << 30))
8 #define HIGH_ADDR	((void *) (1UL << 50))
9 
10 struct testcase {
11 	void *addr;
12 	unsigned long size;
13 	unsigned long flags;
14 	const char *msg;
15 	unsigned int low_addr_required:1;
16 	unsigned int keep_mapped:1;
17 };
18 
19 static struct testcase testcases[] = {
20 	{
21 		.addr = NULL,
22 		.size = 2 * PAGE_SIZE,
23 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
24 		.msg = "mmap(NULL)",
25 		.low_addr_required = 1,
26 	},
27 	{
28 		.addr = LOW_ADDR,
29 		.size = 2 * PAGE_SIZE,
30 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
31 		.msg = "mmap(LOW_ADDR)",
32 		.low_addr_required = 1,
33 	},
34 	{
35 		.addr = HIGH_ADDR,
36 		.size = 2 * PAGE_SIZE,
37 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
38 		.msg = "mmap(HIGH_ADDR)",
39 		.keep_mapped = 1,
40 	},
41 	{
42 		.addr = HIGH_ADDR,
43 		.size = 2 * PAGE_SIZE,
44 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
45 		.msg = "mmap(HIGH_ADDR) again",
46 		.keep_mapped = 1,
47 	},
48 	{
49 		.addr = HIGH_ADDR,
50 		.size = 2 * PAGE_SIZE,
51 		.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
52 		.msg = "mmap(HIGH_ADDR, MAP_FIXED)",
53 	},
54 	{
55 		.addr = (void*) -1,
56 		.size = 2 * PAGE_SIZE,
57 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
58 		.msg = "mmap(-1)",
59 		.keep_mapped = 1,
60 	},
61 	{
62 		.addr = (void*) -1,
63 		.size = 2 * PAGE_SIZE,
64 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
65 		.msg = "mmap(-1) again",
66 	},
67 	{
68 		.addr = (void *)((1UL << 47) - PAGE_SIZE),
69 		.size = 2 * PAGE_SIZE,
70 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
71 		.msg = "mmap((1UL << 47), 2 * PAGE_SIZE)",
72 		.low_addr_required = 1,
73 		.keep_mapped = 1,
74 	},
75 	{
76 		.addr = (void *)((1UL << 47) - PAGE_SIZE / 2),
77 		.size = 2 * PAGE_SIZE,
78 		.flags = MAP_PRIVATE | MAP_ANONYMOUS,
79 		.msg = "mmap((1UL << 47), 2 * PAGE_SIZE / 2)",
80 		.low_addr_required = 1,
81 		.keep_mapped = 1,
82 	},
83 	{
84 		.addr = (void *)((1UL << 47) - PAGE_SIZE),
85 		.size = 2 * PAGE_SIZE,
86 		.flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
87 		.msg = "mmap((1UL << 47) - PAGE_SIZE, 2 * PAGE_SIZE, MAP_FIXED)",
88 	},
89 	{
90 		.addr = NULL,
91 		.size = 2UL << 20,
92 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
93 		.msg = "mmap(NULL, MAP_HUGETLB)",
94 		.low_addr_required = 1,
95 	},
96 	{
97 		.addr = LOW_ADDR,
98 		.size = 2UL << 20,
99 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
100 		.msg = "mmap(LOW_ADDR, MAP_HUGETLB)",
101 		.low_addr_required = 1,
102 	},
103 	{
104 		.addr = HIGH_ADDR,
105 		.size = 2UL << 20,
106 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
107 		.msg = "mmap(HIGH_ADDR, MAP_HUGETLB)",
108 		.keep_mapped = 1,
109 	},
110 	{
111 		.addr = HIGH_ADDR,
112 		.size = 2UL << 20,
113 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
114 		.msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again",
115 		.keep_mapped = 1,
116 	},
117 	{
118 		.addr = HIGH_ADDR,
119 		.size = 2UL << 20,
120 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
121 		.msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)",
122 	},
123 	{
124 		.addr = (void*) -1,
125 		.size = 2UL << 20,
126 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
127 		.msg = "mmap(-1, MAP_HUGETLB)",
128 		.keep_mapped = 1,
129 	},
130 	{
131 		.addr = (void*) -1,
132 		.size = 2UL << 20,
133 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
134 		.msg = "mmap(-1, MAP_HUGETLB) again",
135 	},
136 	{
137 		.addr = (void *)((1UL << 47) - PAGE_SIZE),
138 		.size = 4UL << 20,
139 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
140 		.msg = "mmap((1UL << 47), 4UL << 20, MAP_HUGETLB)",
141 		.low_addr_required = 1,
142 		.keep_mapped = 1,
143 	},
144 	{
145 		.addr = (void *)((1UL << 47) - (2UL << 20)),
146 		.size = 4UL << 20,
147 		.flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
148 		.msg = "mmap((1UL << 47) - (2UL << 20), 4UL << 20, MAP_FIXED | MAP_HUGETLB)",
149 	},
150 };
151 
main(int argc,char ** argv)152 int main(int argc, char **argv)
153 {
154 	int i;
155 	void *p;
156 
157 	for (i = 0; i < ARRAY_SIZE(testcases); i++) {
158 		struct testcase *t = testcases + i;
159 
160 		p = mmap(t->addr, t->size, PROT_NONE, t->flags, -1, 0);
161 
162 		printf("%s: %p - ", t->msg, p);
163 
164 		if (p == MAP_FAILED) {
165 			printf("FAILED\n");
166 			continue;
167 		}
168 
169 		if (t->low_addr_required && p >= (void *)(1UL << 47))
170 			printf("FAILED\n");
171 		else
172 			printf("OK\n");
173 		if (!t->keep_mapped)
174 			munmap(p, t->size);
175 	}
176 	return 0;
177 }
178