summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>2018-01-31 19:16:59 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2018-01-31 20:18:37 -0500
commit235266b8e11c9db12497bdfc6d5e9100f3434c24 (patch)
treef3356b606dc05782ca19eeacbd70d8deab040a4c
parente496612c5130567fc9d5f1969ca4b86665aa3cbb (diff)
selftests/vm: move 128TB mmap boundary test to generic directory
Architectures like PPC64 support mmap hint address based large address space selection. This test can be run on those architectures too. Move the test from the x86 selftests to selftest/vm so that other architectures can use it too. We also add a few new test scenarios in this patch. We do test a few boundary conditions before we do a high address mmap. PPC64 uses the address limit to validate the address in the fault path. We had bugs in this area w.r.t SLB fault handling before we updated the addess limit. We also touch the allocated space to make sure we don't have any bugs in the fault handling path. [akpm@linux-foundation.org: restore tools/testing/selftests/vm/Makefile alpha ordering] Link: http://lkml.kernel.org/r/20171123165226.32582-1-aneesh.kumar@linux.vnet.ibm.com Signed-off-by: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com> Cc: "Kirill A . Shutemov" <kirill.shutemov@linux.intel.com> Cc: Ingo Molnar <mingo@redhat.com> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Shuah Khan <shuah@kernel.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--tools/testing/selftests/vm/Makefile5
-rwxr-xr-xtools/testing/selftests/vm/run_vmtests11
-rw-r--r--tools/testing/selftests/vm/va_128TBswitch.c297
-rw-r--r--tools/testing/selftests/x86/5lvl.c177
4 files changed, 311 insertions, 179 deletions
diff --git a/tools/testing/selftests/vm/Makefile b/tools/testing/selftests/vm/Makefile
index 7f45806bd863..fdefa2295ddc 100644
--- a/tools/testing/selftests/vm/Makefile
+++ b/tools/testing/selftests/vm/Makefile
@@ -8,17 +8,18 @@ endif
8CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS) 8CFLAGS = -Wall -I ../../../../usr/include $(EXTRA_CFLAGS)
9LDLIBS = -lrt 9LDLIBS = -lrt
10TEST_GEN_FILES = compaction_test 10TEST_GEN_FILES = compaction_test
11TEST_GEN_FILES += gup_benchmark
11TEST_GEN_FILES += hugepage-mmap 12TEST_GEN_FILES += hugepage-mmap
12TEST_GEN_FILES += hugepage-shm 13TEST_GEN_FILES += hugepage-shm
13TEST_GEN_FILES += map_hugetlb 14TEST_GEN_FILES += map_hugetlb
15TEST_GEN_FILES += mlock-random-test
14TEST_GEN_FILES += mlock2-tests 16TEST_GEN_FILES += mlock2-tests
15TEST_GEN_FILES += on-fault-limit 17TEST_GEN_FILES += on-fault-limit
16TEST_GEN_FILES += thuge-gen 18TEST_GEN_FILES += thuge-gen
17TEST_GEN_FILES += transhuge-stress 19TEST_GEN_FILES += transhuge-stress
18TEST_GEN_FILES += userfaultfd 20TEST_GEN_FILES += userfaultfd
19TEST_GEN_FILES += mlock-random-test 21TEST_GEN_FILES += va_128TBswitch
20TEST_GEN_FILES += virtual_address_range 22TEST_GEN_FILES += virtual_address_range
21TEST_GEN_FILES += gup_benchmark
22 23
23TEST_PROGS := run_vmtests 24TEST_PROGS := run_vmtests
24 25
diff --git a/tools/testing/selftests/vm/run_vmtests b/tools/testing/selftests/vm/run_vmtests
index cc826326de87..d2561895a021 100755
--- a/tools/testing/selftests/vm/run_vmtests
+++ b/tools/testing/selftests/vm/run_vmtests
@@ -177,4 +177,15 @@ else
177 echo "[PASS]" 177 echo "[PASS]"
178fi 178fi
179 179
180echo "-----------------------------"
181echo "running virtual address 128TB switch test"
182echo "-----------------------------"
183./va_128TBswitch
184if [ $? -ne 0 ]; then
185 echo "[FAIL]"
186 exitcode=1
187else
188 echo "[PASS]"
189fi
190
180exit $exitcode 191exit $exitcode
diff --git a/tools/testing/selftests/vm/va_128TBswitch.c b/tools/testing/selftests/vm/va_128TBswitch.c
new file mode 100644
index 000000000000..e7fe734c374f
--- /dev/null
+++ b/tools/testing/selftests/vm/va_128TBswitch.c
@@ -0,0 +1,297 @@
1/*
2 *
3 * Authors: Kirill A. Shutemov <kirill.shutemov@linux.intel.com>
4 * Authors: Aneesh Kumar K.V <aneesh.kumar@linux.vnet.ibm.com>
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License, version 2, as
8 * published by the Free Software Foundation.
9
10 * This program is distributed in the hope that it would be useful, but
11 * WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 */
15
16#include <stdio.h>
17#include <sys/mman.h>
18#include <string.h>
19
20#define ARRAY_SIZE(arr) (sizeof(arr) / sizeof((arr)[0]))
21
22#ifdef __powerpc64__
23#define PAGE_SIZE (64 << 10)
24/*
25 * This will work with 16M and 2M hugepage size
26 */
27#define HUGETLB_SIZE (16 << 20)
28#else
29#define PAGE_SIZE (4 << 10)
30#define HUGETLB_SIZE (2 << 20)
31#endif
32
33/*
34 * >= 128TB is the hint addr value we used to select
35 * large address space.
36 */
37#define ADDR_SWITCH_HINT (1UL << 47)
38#define LOW_ADDR ((void *) (1UL << 30))
39#define HIGH_ADDR ((void *) (1UL << 48))
40
41struct testcase {
42 void *addr;
43 unsigned long size;
44 unsigned long flags;
45 const char *msg;
46 unsigned int low_addr_required:1;
47 unsigned int keep_mapped:1;
48};
49
50static struct testcase testcases[] = {
51 {
52 /*
53 * If stack is moved, we could possibly allocate
54 * this at the requested address.
55 */
56 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
57 .size = PAGE_SIZE,
58 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
59 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
60 .low_addr_required = 1,
61 },
62 {
63 /*
64 * We should never allocate at the requested address or above it
65 * The len cross the 128TB boundary. Without MAP_FIXED
66 * we will always search in the lower address space.
67 */
68 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
69 .size = 2 * PAGE_SIZE,
70 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
71 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, (2 * PAGE_SIZE))",
72 .low_addr_required = 1,
73 },
74 {
75 /*
76 * Exact mapping at 128TB, the area is free we should get that
77 * even without MAP_FIXED.
78 */
79 .addr = ((void *)(ADDR_SWITCH_HINT)),
80 .size = PAGE_SIZE,
81 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
82 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
83 .keep_mapped = 1,
84 },
85 {
86 .addr = (void *)(ADDR_SWITCH_HINT),
87 .size = 2 * PAGE_SIZE,
88 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
89 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
90 },
91 {
92 .addr = NULL,
93 .size = 2 * PAGE_SIZE,
94 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
95 .msg = "mmap(NULL)",
96 .low_addr_required = 1,
97 },
98 {
99 .addr = LOW_ADDR,
100 .size = 2 * PAGE_SIZE,
101 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
102 .msg = "mmap(LOW_ADDR)",
103 .low_addr_required = 1,
104 },
105 {
106 .addr = HIGH_ADDR,
107 .size = 2 * PAGE_SIZE,
108 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
109 .msg = "mmap(HIGH_ADDR)",
110 .keep_mapped = 1,
111 },
112 {
113 .addr = HIGH_ADDR,
114 .size = 2 * PAGE_SIZE,
115 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
116 .msg = "mmap(HIGH_ADDR) again",
117 .keep_mapped = 1,
118 },
119 {
120 .addr = HIGH_ADDR,
121 .size = 2 * PAGE_SIZE,
122 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
123 .msg = "mmap(HIGH_ADDR, MAP_FIXED)",
124 },
125 {
126 .addr = (void *) -1,
127 .size = 2 * PAGE_SIZE,
128 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
129 .msg = "mmap(-1)",
130 .keep_mapped = 1,
131 },
132 {
133 .addr = (void *) -1,
134 .size = 2 * PAGE_SIZE,
135 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
136 .msg = "mmap(-1) again",
137 },
138 {
139 .addr = ((void *)(ADDR_SWITCH_HINT - PAGE_SIZE)),
140 .size = PAGE_SIZE,
141 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
142 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, PAGE_SIZE)",
143 .low_addr_required = 1,
144 },
145 {
146 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
147 .size = 2 * PAGE_SIZE,
148 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
149 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2 * PAGE_SIZE)",
150 .low_addr_required = 1,
151 .keep_mapped = 1,
152 },
153 {
154 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE / 2),
155 .size = 2 * PAGE_SIZE,
156 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
157 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE/2 , 2 * PAGE_SIZE)",
158 .low_addr_required = 1,
159 .keep_mapped = 1,
160 },
161 {
162 .addr = ((void *)(ADDR_SWITCH_HINT)),
163 .size = PAGE_SIZE,
164 .flags = MAP_PRIVATE | MAP_ANONYMOUS,
165 .msg = "mmap(ADDR_SWITCH_HINT, PAGE_SIZE)",
166 },
167 {
168 .addr = (void *)(ADDR_SWITCH_HINT),
169 .size = 2 * PAGE_SIZE,
170 .flags = MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
171 .msg = "mmap(ADDR_SWITCH_HINT, 2 * PAGE_SIZE, MAP_FIXED)",
172 },
173};
174
175static struct testcase hugetlb_testcases[] = {
176 {
177 .addr = NULL,
178 .size = HUGETLB_SIZE,
179 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
180 .msg = "mmap(NULL, MAP_HUGETLB)",
181 .low_addr_required = 1,
182 },
183 {
184 .addr = LOW_ADDR,
185 .size = HUGETLB_SIZE,
186 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
187 .msg = "mmap(LOW_ADDR, MAP_HUGETLB)",
188 .low_addr_required = 1,
189 },
190 {
191 .addr = HIGH_ADDR,
192 .size = HUGETLB_SIZE,
193 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
194 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB)",
195 .keep_mapped = 1,
196 },
197 {
198 .addr = HIGH_ADDR,
199 .size = HUGETLB_SIZE,
200 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
201 .msg = "mmap(HIGH_ADDR, MAP_HUGETLB) again",
202 .keep_mapped = 1,
203 },
204 {
205 .addr = HIGH_ADDR,
206 .size = HUGETLB_SIZE,
207 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
208 .msg = "mmap(HIGH_ADDR, MAP_FIXED | MAP_HUGETLB)",
209 },
210 {
211 .addr = (void *) -1,
212 .size = HUGETLB_SIZE,
213 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
214 .msg = "mmap(-1, MAP_HUGETLB)",
215 .keep_mapped = 1,
216 },
217 {
218 .addr = (void *) -1,
219 .size = HUGETLB_SIZE,
220 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
221 .msg = "mmap(-1, MAP_HUGETLB) again",
222 },
223 {
224 .addr = (void *)(ADDR_SWITCH_HINT - PAGE_SIZE),
225 .size = 2 * HUGETLB_SIZE,
226 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS,
227 .msg = "mmap(ADDR_SWITCH_HINT - PAGE_SIZE, 2*HUGETLB_SIZE, MAP_HUGETLB)",
228 .low_addr_required = 1,
229 .keep_mapped = 1,
230 },
231 {
232 .addr = (void *)(ADDR_SWITCH_HINT),
233 .size = 2 * HUGETLB_SIZE,
234 .flags = MAP_HUGETLB | MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED,
235 .msg = "mmap(ADDR_SWITCH_HINT , 2*HUGETLB_SIZE, MAP_FIXED | MAP_HUGETLB)",
236 },
237};
238
239static int run_test(struct testcase *test, int count)
240{
241 void *p;
242 int i, ret = 0;
243
244 for (i = 0; i < count; i++) {
245 struct testcase *t = test + i;
246
247 p = mmap(t->addr, t->size, PROT_READ | PROT_WRITE, t->flags, -1, 0);
248
249 printf("%s: %p - ", t->msg, p);
250
251 if (p == MAP_FAILED) {
252 printf("FAILED\n");
253 ret = 1;
254 continue;
255 }
256
257 if (t->low_addr_required && p >= (void *)(ADDR_SWITCH_HINT)) {
258 printf("FAILED\n");
259 ret = 1;
260 } else {
261 /*
262 * Do a dereference of the address returned so that we catch
263 * bugs in page fault handling
264 */
265 memset(p, 0, t->size);
266 printf("OK\n");
267 }
268 if (!t->keep_mapped)
269 munmap(p, t->size);
270 }
271
272 return ret;
273}
274
275static int supported_arch(void)
276{
277#if defined(__powerpc64__)
278 return 1;
279#elif defined(__x86_64__)
280 return 1;
281#else
282 return 0;
283#endif
284}
285
286int main(int argc, char **argv)
287{
288 int ret;
289
290 if (!supported_arch())
291 return 0;
292
293 ret = run_test(testcases, ARRAY_SIZE(testcases));
294 if (argc == 2 && !strcmp(argv[1], "--run-hugetlb"))
295 ret = run_test(hugetlb_testcases, ARRAY_SIZE(hugetlb_testcases));
296 return ret;
297}
diff --git a/tools/testing/selftests/x86/5lvl.c b/tools/testing/selftests/x86/5lvl.c
deleted file mode 100644
index 2eafdcd4c2b3..000000000000
--- a/tools/testing/selftests/x86/5lvl.c
+++ /dev/null
@@ -1,177 +0,0 @@
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
10struct 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
19static 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
152int 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}