Merge tag 'for-linus-20190617' of git://git.sourceforge.jp/gitroot/uclinux-h8/linux
[linux-2.6-microblaze.git] / tools / testing / selftests / vm / va_128TBswitch.c
1 // SPDX-License-Identifier: GPL-2.0-only
2 /*
3  *
4  * Authors: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
5  * Authors: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
6  */
7
8 #include <stdio.h>
9 #include <sys/mman.h>
10 #include <string.h>
11
12 #define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
13
14 #ifdef __powerpc64__
15 #define PAGE_SIZE       (64 << 10)
16 /*
17  * This will work with 16M and 2M hugepage size
18  */
19 #define HUGETLB_SIZE    (16 << 20)
20 #else
21 #define PAGE_SIZE       (4 << 10)
22 #define HUGETLB_SIZE    (2 << 20)
23 #endif
24
25 /*
26  * >= 128TB is the hint addr value we used to select
27  * large address space.
28  */
29 #define ADDR_SWITCH_HINT (1UL << 47)
30 #define LOW_ADDR        ((void *) (1UL << 30))
31 #define HIGH_ADDR       ((void *) (1UL << 48))
32
33 struct testcase {
34         void *addr;
35         unsigned long size;
36         unsigned long flags;
37         const char *msg;
38         unsigned int low_addr_required:1;
39         unsigned int keep_mapped:1;
40 };
41
42 static struct testcase testcases[] = {
43         {
44                 /*
45                  * If stack is moved, we could possibly allocate
46                  * this at the requested address.
47                  */
48                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
49                 .size = PAGE_SIZE,
50                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
51                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
52                 .low_addr_required = 1,
53         },
54         {
55                 /*
56                  * We should never allocate at the requested address or above it
57                  * The len cross the 128TB boundary. Without MAP_FIXED
58                  * we will always search in the lower address space.
59                  */
60                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
61                 .size = 2 * PAGE_SIZE,
62                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
63                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, (2 * PAGE_SIZE))",
64                 .low_addr_required = 1,
65         },
66         {
67                 /*
68                  * Exact mapping at 128TB, the area is free we should get that
69                  * even without MAP_FIXED.
70                  */
71                 .addr = ((void *)(ADDR_SWITCH_HINT)),
72                 .size = PAGE_SIZE,
73                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
74                 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
75                 .keep_mapped = 1,
76         },
77         {
78                 .addr = (void *)(ADDR_SWITCH_HINT),
79                 .size = 2 * PAGE_SIZE,
80                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
81                 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
82         },
83         {
84                 .addr = NULL,
85                 .size = 2 * PAGE_SIZE,
86                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
87                 .msg = "mmap(NULL)",
88                 .low_addr_required = 1,
89         },
90         {
91                 .addr = LOW_ADDR,
92                 .size = 2 * PAGE_SIZE,
93                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
94                 .msg = "mmap(LOW_ADDR)",
95                 .low_addr_required = 1,
96         },
97         {
98                 .addr = HIGH_ADDR,
99                 .size = 2 * PAGE_SIZE,
100                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
101                 .msg = "mmap(HIGH_ADDR)",
102                 .keep_mapped = 1,
103         },
104         {
105                 .addr = HIGH_ADDR,
106                 .size = 2 * PAGE_SIZE,
107                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
108                 .msg = "mmap(HIGH_ADDR) again",
109                 .keep_mapped = 1,
110         },
111         {
112                 .addr = HIGH_ADDR,
113                 .size = 2 * PAGE_SIZE,
114                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
115                 .msg = "mmap(HIGH_ADDR, MAP_FIXED)",
116         },
117         {
118                 .addr = (void *) -1,
119                 .size = 2 * PAGE_SIZE,
120                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
121                 .msg = "mmap(-1)",
122                 .keep_mapped = 1,
123         },
124         {
125                 .addr = (void *) -1,
126                 .size = 2 * PAGE_SIZE,
127                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
128                 .msg = "mmap(-1) again",
129         },
130         {
131                 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
132                 .size = PAGE_SIZE,
133                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
134                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
135                 .low_addr_required = 1,
136         },
137         {
138                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
139                 .size = 2 * PAGE_SIZE,
140                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
141                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2 * PAGE_SIZE)",
142                 .low_addr_required = 1,
143                 .keep_mapped = 1,
144         },
145         {
146                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE / 2),
147                 .size = 2 * PAGE_SIZE,
148                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
149                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE/2 , 2 * PAGE_SIZE)",
150                 .low_addr_required = 1,
151                 .keep_mapped = 1,
152         },
153         {
154                 .addr = ((void *)(ADDR_SWITCH_HINT)),
155                 .size = PAGE_SIZE,
156                 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
157                 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
158         },
159         {
160                 .addr = (void *)(ADDR_SWITCH_HINT),
161                 .size = 2 * PAGE_SIZE,
162                 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
163                 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
164         },
165 };
166
167 static struct testcase hugetlb_testcases[] = {
168         {
169                 .addr = NULL,
170                 .size = HUGETLB_SIZE,
171                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
172                 .msg = "mmap(NULL, MAP_HUGETLB)",
173                 .low_addr_required = 1,
174         },
175         {
176                 .addr = LOW_ADDR,
177                 .size = HUGETLB_SIZE,
178                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
179                 .msg = "mmap(LOW_ADDR, MAP_HUGETLB)",
180                 .low_addr_required = 1,
181         },
182         {
183                 .addr = HIGH_ADDR,
184                 .size = HUGETLB_SIZE,
185                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
186                 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB)",
187                 .keep_mapped = 1,
188         },
189         {
190                 .addr = HIGH_ADDR,
191                 .size = HUGETLB_SIZE,
192                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
193                 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again",
194                 .keep_mapped = 1,
195         },
196         {
197                 .addr = HIGH_ADDR,
198                 .size = HUGETLB_SIZE,
199                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
200                 .msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)",
201         },
202         {
203                 .addr = (void *) -1,
204                 .size = HUGETLB_SIZE,
205                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
206                 .msg = "mmap(-1, MAP_HUGETLB)",
207                 .keep_mapped = 1,
208         },
209         {
210                 .addr = (void *) -1,
211                 .size = HUGETLB_SIZE,
212                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
213                 .msg = "mmap(-1, MAP_HUGETLB) again",
214         },
215         {
216                 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
217                 .size = 2 * HUGETLB_SIZE,
218                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
219                 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2*HUGETLB_SIZE, MAP_HUGETLB)",
220                 .low_addr_required = 1,
221                 .keep_mapped = 1,
222         },
223         {
224                 .addr = (void *)(ADDR_SWITCH_HINT),
225                 .size = 2 * HUGETLB_SIZE,
226                 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
227                 .msg = "mmap(ADDR_SWITCH_HINT , 2*HUGETLB_SIZE, MAP_FIXED | MAP_HUGETLB)",
228         },
229 };
230
231 static int run_test(struct testcase *test, int count)
232 {
233         void *p;
234         int i, ret = 0;
235
236         for (i = 0; i < count; i++) {
237                 struct testcase *t = test + i;
238
239                 p = mmap(t->addr, t->size, PROT_READ | PROT_WRITE, t->flags, -1, 0);
240
241                 printf("%s: %p - ", t->msg, p);
242
243                 if (p == MAP_FAILED) {
244                         printf("FAILED\n");
245                         ret = 1;
246                         continue;
247                 }
248
249                 if (t->low_addr_required && p >= (void *)(ADDR_SWITCH_HINT)) {
250                         printf("FAILED\n");
251                         ret = 1;
252                 } else {
253                         /*
254                          * Do a dereference of the address returned so that we catch
255                          * bugs in page fault handling
256                          */
257                         memset(p, 0, t->size);
258                         printf("OK\n");
259                 }
260                 if (!t->keep_mapped)
261                         munmap(p, t->size);
262         }
263
264         return ret;
265 }
266
267 static int supported_arch(void)
268 {
269 #if defined(__powerpc64__)
270         return 1;
271 #elif defined(__x86_64__)
272         return 1;
273 #else
274         return 0;
275 #endif
276 }
277
278 int main(int argc, char **argv)
279 {
280         int ret;
281
282         if (!supported_arch())
283                 return 0;
284
285         ret = run_test(testcases, ARRAY_SIZE(testcases));
286         if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
287                 ret = run_test(hugetlb_testcases, ARRAY_SIZE(hugetlb_testcases));
288         return ret;
289 }