1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun
3*4882a593Smuzhiyun /*
4*4882a593Smuzhiyun * Tests for mremap w/ MREMAP_DONTUNMAP.
5*4882a593Smuzhiyun *
6*4882a593Smuzhiyun * Copyright 2020, Brian Geffon <bgeffon@google.com>
7*4882a593Smuzhiyun */
8*4882a593Smuzhiyun #define _GNU_SOURCE
9*4882a593Smuzhiyun #include <sys/mman.h>
10*4882a593Smuzhiyun #include <errno.h>
11*4882a593Smuzhiyun #include <stdio.h>
12*4882a593Smuzhiyun #include <stdlib.h>
13*4882a593Smuzhiyun #include <string.h>
14*4882a593Smuzhiyun #include <unistd.h>
15*4882a593Smuzhiyun
16*4882a593Smuzhiyun #include "../kselftest.h"
17*4882a593Smuzhiyun
18*4882a593Smuzhiyun #ifndef MREMAP_DONTUNMAP
19*4882a593Smuzhiyun #define MREMAP_DONTUNMAP 4
20*4882a593Smuzhiyun #endif
21*4882a593Smuzhiyun
22*4882a593Smuzhiyun unsigned long page_size;
23*4882a593Smuzhiyun char *page_buffer;
24*4882a593Smuzhiyun
dump_maps(void)25*4882a593Smuzhiyun static void dump_maps(void)
26*4882a593Smuzhiyun {
27*4882a593Smuzhiyun char cmd[32];
28*4882a593Smuzhiyun
29*4882a593Smuzhiyun snprintf(cmd, sizeof(cmd), "cat /proc/%d/maps", getpid());
30*4882a593Smuzhiyun system(cmd);
31*4882a593Smuzhiyun }
32*4882a593Smuzhiyun
33*4882a593Smuzhiyun #define BUG_ON(condition, description) \
34*4882a593Smuzhiyun do { \
35*4882a593Smuzhiyun if (condition) { \
36*4882a593Smuzhiyun fprintf(stderr, "[FAIL]\t%s():%d\t%s:%s\n", __func__, \
37*4882a593Smuzhiyun __LINE__, (description), strerror(errno)); \
38*4882a593Smuzhiyun dump_maps(); \
39*4882a593Smuzhiyun exit(1); \
40*4882a593Smuzhiyun } \
41*4882a593Smuzhiyun } while (0)
42*4882a593Smuzhiyun
43*4882a593Smuzhiyun // Try a simple operation for to "test" for kernel support this prevents
44*4882a593Smuzhiyun // reporting tests as failed when it's run on an older kernel.
kernel_support_for_mremap_dontunmap()45*4882a593Smuzhiyun static int kernel_support_for_mremap_dontunmap()
46*4882a593Smuzhiyun {
47*4882a593Smuzhiyun int ret = 0;
48*4882a593Smuzhiyun unsigned long num_pages = 1;
49*4882a593Smuzhiyun void *source_mapping = mmap(NULL, num_pages * page_size, PROT_NONE,
50*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
51*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
52*4882a593Smuzhiyun
53*4882a593Smuzhiyun // This simple remap should only fail if MREMAP_DONTUNMAP isn't
54*4882a593Smuzhiyun // supported.
55*4882a593Smuzhiyun void *dest_mapping =
56*4882a593Smuzhiyun mremap(source_mapping, num_pages * page_size, num_pages * page_size,
57*4882a593Smuzhiyun MREMAP_DONTUNMAP | MREMAP_MAYMOVE, 0);
58*4882a593Smuzhiyun if (dest_mapping == MAP_FAILED) {
59*4882a593Smuzhiyun ret = errno;
60*4882a593Smuzhiyun } else {
61*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, num_pages * page_size) == -1,
62*4882a593Smuzhiyun "unable to unmap destination mapping");
63*4882a593Smuzhiyun }
64*4882a593Smuzhiyun
65*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
66*4882a593Smuzhiyun "unable to unmap source mapping");
67*4882a593Smuzhiyun return ret;
68*4882a593Smuzhiyun }
69*4882a593Smuzhiyun
70*4882a593Smuzhiyun // This helper will just validate that an entire mapping contains the expected
71*4882a593Smuzhiyun // byte.
check_region_contains_byte(void * addr,unsigned long size,char byte)72*4882a593Smuzhiyun static int check_region_contains_byte(void *addr, unsigned long size, char byte)
73*4882a593Smuzhiyun {
74*4882a593Smuzhiyun BUG_ON(size & (page_size - 1),
75*4882a593Smuzhiyun "check_region_contains_byte expects page multiples");
76*4882a593Smuzhiyun BUG_ON((unsigned long)addr & (page_size - 1),
77*4882a593Smuzhiyun "check_region_contains_byte expects page alignment");
78*4882a593Smuzhiyun
79*4882a593Smuzhiyun memset(page_buffer, byte, page_size);
80*4882a593Smuzhiyun
81*4882a593Smuzhiyun unsigned long num_pages = size / page_size;
82*4882a593Smuzhiyun unsigned long i;
83*4882a593Smuzhiyun
84*4882a593Smuzhiyun // Compare each page checking that it contains our expected byte.
85*4882a593Smuzhiyun for (i = 0; i < num_pages; ++i) {
86*4882a593Smuzhiyun int ret =
87*4882a593Smuzhiyun memcmp(addr + (i * page_size), page_buffer, page_size);
88*4882a593Smuzhiyun if (ret) {
89*4882a593Smuzhiyun return ret;
90*4882a593Smuzhiyun }
91*4882a593Smuzhiyun }
92*4882a593Smuzhiyun
93*4882a593Smuzhiyun return 0;
94*4882a593Smuzhiyun }
95*4882a593Smuzhiyun
96*4882a593Smuzhiyun // this test validates that MREMAP_DONTUNMAP moves the pagetables while leaving
97*4882a593Smuzhiyun // the source mapping mapped.
mremap_dontunmap_simple()98*4882a593Smuzhiyun static void mremap_dontunmap_simple()
99*4882a593Smuzhiyun {
100*4882a593Smuzhiyun unsigned long num_pages = 5;
101*4882a593Smuzhiyun
102*4882a593Smuzhiyun void *source_mapping =
103*4882a593Smuzhiyun mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE,
104*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
105*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
106*4882a593Smuzhiyun
107*4882a593Smuzhiyun memset(source_mapping, 'a', num_pages * page_size);
108*4882a593Smuzhiyun
109*4882a593Smuzhiyun // Try to just move the whole mapping anywhere (not fixed).
110*4882a593Smuzhiyun void *dest_mapping =
111*4882a593Smuzhiyun mremap(source_mapping, num_pages * page_size, num_pages * page_size,
112*4882a593Smuzhiyun MREMAP_DONTUNMAP | MREMAP_MAYMOVE, NULL);
113*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mremap");
114*4882a593Smuzhiyun
115*4882a593Smuzhiyun // Validate that the pages have been moved, we know they were moved if
116*4882a593Smuzhiyun // the dest_mapping contains a's.
117*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
118*4882a593Smuzhiyun (dest_mapping, num_pages * page_size, 'a') != 0,
119*4882a593Smuzhiyun "pages did not migrate");
120*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
121*4882a593Smuzhiyun (source_mapping, num_pages * page_size, 0) != 0,
122*4882a593Smuzhiyun "source should have no ptes");
123*4882a593Smuzhiyun
124*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, num_pages * page_size) == -1,
125*4882a593Smuzhiyun "unable to unmap destination mapping");
126*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
127*4882a593Smuzhiyun "unable to unmap source mapping");
128*4882a593Smuzhiyun }
129*4882a593Smuzhiyun
130*4882a593Smuzhiyun // This test validates that MREMAP_DONTUNMAP on a shared mapping works as expected.
mremap_dontunmap_simple_shmem()131*4882a593Smuzhiyun static void mremap_dontunmap_simple_shmem()
132*4882a593Smuzhiyun {
133*4882a593Smuzhiyun unsigned long num_pages = 5;
134*4882a593Smuzhiyun
135*4882a593Smuzhiyun int mem_fd = memfd_create("memfd", MFD_CLOEXEC);
136*4882a593Smuzhiyun BUG_ON(mem_fd < 0, "memfd_create");
137*4882a593Smuzhiyun
138*4882a593Smuzhiyun BUG_ON(ftruncate(mem_fd, num_pages * page_size) < 0,
139*4882a593Smuzhiyun "ftruncate");
140*4882a593Smuzhiyun
141*4882a593Smuzhiyun void *source_mapping =
142*4882a593Smuzhiyun mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE,
143*4882a593Smuzhiyun MAP_FILE | MAP_SHARED, mem_fd, 0);
144*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
145*4882a593Smuzhiyun
146*4882a593Smuzhiyun BUG_ON(close(mem_fd) < 0, "close");
147*4882a593Smuzhiyun
148*4882a593Smuzhiyun memset(source_mapping, 'a', num_pages * page_size);
149*4882a593Smuzhiyun
150*4882a593Smuzhiyun // Try to just move the whole mapping anywhere (not fixed).
151*4882a593Smuzhiyun void *dest_mapping =
152*4882a593Smuzhiyun mremap(source_mapping, num_pages * page_size, num_pages * page_size,
153*4882a593Smuzhiyun MREMAP_DONTUNMAP | MREMAP_MAYMOVE, NULL);
154*4882a593Smuzhiyun if (dest_mapping == MAP_FAILED && errno == EINVAL) {
155*4882a593Smuzhiyun // Old kernel which doesn't support MREMAP_DONTUNMAP on shmem.
156*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
157*4882a593Smuzhiyun "unable to unmap source mapping");
158*4882a593Smuzhiyun return;
159*4882a593Smuzhiyun }
160*4882a593Smuzhiyun
161*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mremap");
162*4882a593Smuzhiyun
163*4882a593Smuzhiyun // Validate that the pages have been moved, we know they were moved if
164*4882a593Smuzhiyun // the dest_mapping contains a's.
165*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
166*4882a593Smuzhiyun (dest_mapping, num_pages * page_size, 'a') != 0,
167*4882a593Smuzhiyun "pages did not migrate");
168*4882a593Smuzhiyun
169*4882a593Smuzhiyun // Because the region is backed by shmem, we will actually see the same
170*4882a593Smuzhiyun // memory at the source location still.
171*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
172*4882a593Smuzhiyun (source_mapping, num_pages * page_size, 'a') != 0,
173*4882a593Smuzhiyun "source should have no ptes");
174*4882a593Smuzhiyun
175*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, num_pages * page_size) == -1,
176*4882a593Smuzhiyun "unable to unmap destination mapping");
177*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
178*4882a593Smuzhiyun "unable to unmap source mapping");
179*4882a593Smuzhiyun }
180*4882a593Smuzhiyun
181*4882a593Smuzhiyun // This test validates MREMAP_DONTUNMAP will move page tables to a specific
182*4882a593Smuzhiyun // destination using MREMAP_FIXED, also while validating that the source
183*4882a593Smuzhiyun // remains intact.
mremap_dontunmap_simple_fixed()184*4882a593Smuzhiyun static void mremap_dontunmap_simple_fixed()
185*4882a593Smuzhiyun {
186*4882a593Smuzhiyun unsigned long num_pages = 5;
187*4882a593Smuzhiyun
188*4882a593Smuzhiyun // Since we want to guarantee that we can remap to a point, we will
189*4882a593Smuzhiyun // create a mapping up front.
190*4882a593Smuzhiyun void *dest_mapping =
191*4882a593Smuzhiyun mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE,
192*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
193*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mmap");
194*4882a593Smuzhiyun memset(dest_mapping, 'X', num_pages * page_size);
195*4882a593Smuzhiyun
196*4882a593Smuzhiyun void *source_mapping =
197*4882a593Smuzhiyun mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE,
198*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
199*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
200*4882a593Smuzhiyun memset(source_mapping, 'a', num_pages * page_size);
201*4882a593Smuzhiyun
202*4882a593Smuzhiyun void *remapped_mapping =
203*4882a593Smuzhiyun mremap(source_mapping, num_pages * page_size, num_pages * page_size,
204*4882a593Smuzhiyun MREMAP_FIXED | MREMAP_DONTUNMAP | MREMAP_MAYMOVE,
205*4882a593Smuzhiyun dest_mapping);
206*4882a593Smuzhiyun BUG_ON(remapped_mapping == MAP_FAILED, "mremap");
207*4882a593Smuzhiyun BUG_ON(remapped_mapping != dest_mapping,
208*4882a593Smuzhiyun "mremap should have placed the remapped mapping at dest_mapping");
209*4882a593Smuzhiyun
210*4882a593Smuzhiyun // The dest mapping will have been unmap by mremap so we expect the Xs
211*4882a593Smuzhiyun // to be gone and replaced with a's.
212*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
213*4882a593Smuzhiyun (dest_mapping, num_pages * page_size, 'a') != 0,
214*4882a593Smuzhiyun "pages did not migrate");
215*4882a593Smuzhiyun
216*4882a593Smuzhiyun // And the source mapping will have had its ptes dropped.
217*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
218*4882a593Smuzhiyun (source_mapping, num_pages * page_size, 0) != 0,
219*4882a593Smuzhiyun "source should have no ptes");
220*4882a593Smuzhiyun
221*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, num_pages * page_size) == -1,
222*4882a593Smuzhiyun "unable to unmap destination mapping");
223*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
224*4882a593Smuzhiyun "unable to unmap source mapping");
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun
227*4882a593Smuzhiyun // This test validates that we can MREMAP_DONTUNMAP for a portion of an
228*4882a593Smuzhiyun // existing mapping.
mremap_dontunmap_partial_mapping()229*4882a593Smuzhiyun static void mremap_dontunmap_partial_mapping()
230*4882a593Smuzhiyun {
231*4882a593Smuzhiyun /*
232*4882a593Smuzhiyun * source mapping:
233*4882a593Smuzhiyun * --------------
234*4882a593Smuzhiyun * | aaaaaaaaaa |
235*4882a593Smuzhiyun * --------------
236*4882a593Smuzhiyun * to become:
237*4882a593Smuzhiyun * --------------
238*4882a593Smuzhiyun * | aaaaa00000 |
239*4882a593Smuzhiyun * --------------
240*4882a593Smuzhiyun * With the destination mapping containing 5 pages of As.
241*4882a593Smuzhiyun * ---------
242*4882a593Smuzhiyun * | aaaaa |
243*4882a593Smuzhiyun * ---------
244*4882a593Smuzhiyun */
245*4882a593Smuzhiyun unsigned long num_pages = 10;
246*4882a593Smuzhiyun void *source_mapping =
247*4882a593Smuzhiyun mmap(NULL, num_pages * page_size, PROT_READ | PROT_WRITE,
248*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
249*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
250*4882a593Smuzhiyun memset(source_mapping, 'a', num_pages * page_size);
251*4882a593Smuzhiyun
252*4882a593Smuzhiyun // We will grab the last 5 pages of the source and move them.
253*4882a593Smuzhiyun void *dest_mapping =
254*4882a593Smuzhiyun mremap(source_mapping + (5 * page_size), 5 * page_size,
255*4882a593Smuzhiyun 5 * page_size,
256*4882a593Smuzhiyun MREMAP_DONTUNMAP | MREMAP_MAYMOVE, NULL);
257*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mremap");
258*4882a593Smuzhiyun
259*4882a593Smuzhiyun // We expect the first 5 pages of the source to contain a's and the
260*4882a593Smuzhiyun // final 5 pages to contain zeros.
261*4882a593Smuzhiyun BUG_ON(check_region_contains_byte(source_mapping, 5 * page_size, 'a') !=
262*4882a593Smuzhiyun 0, "first 5 pages of source should have original pages");
263*4882a593Smuzhiyun BUG_ON(check_region_contains_byte
264*4882a593Smuzhiyun (source_mapping + (5 * page_size), 5 * page_size, 0) != 0,
265*4882a593Smuzhiyun "final 5 pages of source should have no ptes");
266*4882a593Smuzhiyun
267*4882a593Smuzhiyun // Finally we expect the destination to have 5 pages worth of a's.
268*4882a593Smuzhiyun BUG_ON(check_region_contains_byte(dest_mapping, 5 * page_size, 'a') !=
269*4882a593Smuzhiyun 0, "dest mapping should contain ptes from the source");
270*4882a593Smuzhiyun
271*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, 5 * page_size) == -1,
272*4882a593Smuzhiyun "unable to unmap destination mapping");
273*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, num_pages * page_size) == -1,
274*4882a593Smuzhiyun "unable to unmap source mapping");
275*4882a593Smuzhiyun }
276*4882a593Smuzhiyun
277*4882a593Smuzhiyun // This test validates that we can remap over only a portion of a mapping.
mremap_dontunmap_partial_mapping_overwrite(void)278*4882a593Smuzhiyun static void mremap_dontunmap_partial_mapping_overwrite(void)
279*4882a593Smuzhiyun {
280*4882a593Smuzhiyun /*
281*4882a593Smuzhiyun * source mapping:
282*4882a593Smuzhiyun * ---------
283*4882a593Smuzhiyun * |aaaaa|
284*4882a593Smuzhiyun * ---------
285*4882a593Smuzhiyun * dest mapping initially:
286*4882a593Smuzhiyun * -----------
287*4882a593Smuzhiyun * |XXXXXXXXXX|
288*4882a593Smuzhiyun * ------------
289*4882a593Smuzhiyun * Source to become:
290*4882a593Smuzhiyun * ---------
291*4882a593Smuzhiyun * |00000|
292*4882a593Smuzhiyun * ---------
293*4882a593Smuzhiyun * With the destination mapping containing 5 pages of As.
294*4882a593Smuzhiyun * ------------
295*4882a593Smuzhiyun * |aaaaaXXXXX|
296*4882a593Smuzhiyun * ------------
297*4882a593Smuzhiyun */
298*4882a593Smuzhiyun void *source_mapping =
299*4882a593Smuzhiyun mmap(NULL, 5 * page_size, PROT_READ | PROT_WRITE,
300*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
301*4882a593Smuzhiyun BUG_ON(source_mapping == MAP_FAILED, "mmap");
302*4882a593Smuzhiyun memset(source_mapping, 'a', 5 * page_size);
303*4882a593Smuzhiyun
304*4882a593Smuzhiyun void *dest_mapping =
305*4882a593Smuzhiyun mmap(NULL, 10 * page_size, PROT_READ | PROT_WRITE,
306*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
307*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mmap");
308*4882a593Smuzhiyun memset(dest_mapping, 'X', 10 * page_size);
309*4882a593Smuzhiyun
310*4882a593Smuzhiyun // We will grab the last 5 pages of the source and move them.
311*4882a593Smuzhiyun void *remapped_mapping =
312*4882a593Smuzhiyun mremap(source_mapping, 5 * page_size,
313*4882a593Smuzhiyun 5 * page_size,
314*4882a593Smuzhiyun MREMAP_DONTUNMAP | MREMAP_MAYMOVE | MREMAP_FIXED, dest_mapping);
315*4882a593Smuzhiyun BUG_ON(dest_mapping == MAP_FAILED, "mremap");
316*4882a593Smuzhiyun BUG_ON(dest_mapping != remapped_mapping, "expected to remap to dest_mapping");
317*4882a593Smuzhiyun
318*4882a593Smuzhiyun BUG_ON(check_region_contains_byte(source_mapping, 5 * page_size, 0) !=
319*4882a593Smuzhiyun 0, "first 5 pages of source should have no ptes");
320*4882a593Smuzhiyun
321*4882a593Smuzhiyun // Finally we expect the destination to have 5 pages worth of a's.
322*4882a593Smuzhiyun BUG_ON(check_region_contains_byte(dest_mapping, 5 * page_size, 'a') != 0,
323*4882a593Smuzhiyun "dest mapping should contain ptes from the source");
324*4882a593Smuzhiyun
325*4882a593Smuzhiyun // Finally the last 5 pages shouldn't have been touched.
326*4882a593Smuzhiyun BUG_ON(check_region_contains_byte(dest_mapping + (5 * page_size),
327*4882a593Smuzhiyun 5 * page_size, 'X') != 0,
328*4882a593Smuzhiyun "dest mapping should have retained the last 5 pages");
329*4882a593Smuzhiyun
330*4882a593Smuzhiyun BUG_ON(munmap(dest_mapping, 10 * page_size) == -1,
331*4882a593Smuzhiyun "unable to unmap destination mapping");
332*4882a593Smuzhiyun BUG_ON(munmap(source_mapping, 5 * page_size) == -1,
333*4882a593Smuzhiyun "unable to unmap source mapping");
334*4882a593Smuzhiyun }
335*4882a593Smuzhiyun
main(void)336*4882a593Smuzhiyun int main(void)
337*4882a593Smuzhiyun {
338*4882a593Smuzhiyun page_size = sysconf(_SC_PAGE_SIZE);
339*4882a593Smuzhiyun
340*4882a593Smuzhiyun // test for kernel support for MREMAP_DONTUNMAP skipping the test if
341*4882a593Smuzhiyun // not.
342*4882a593Smuzhiyun if (kernel_support_for_mremap_dontunmap() != 0) {
343*4882a593Smuzhiyun printf("No kernel support for MREMAP_DONTUNMAP\n");
344*4882a593Smuzhiyun return KSFT_SKIP;
345*4882a593Smuzhiyun }
346*4882a593Smuzhiyun
347*4882a593Smuzhiyun // Keep a page sized buffer around for when we need it.
348*4882a593Smuzhiyun page_buffer =
349*4882a593Smuzhiyun mmap(NULL, page_size, PROT_READ | PROT_WRITE,
350*4882a593Smuzhiyun MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
351*4882a593Smuzhiyun BUG_ON(page_buffer == MAP_FAILED, "unable to mmap a page.");
352*4882a593Smuzhiyun
353*4882a593Smuzhiyun mremap_dontunmap_simple();
354*4882a593Smuzhiyun mremap_dontunmap_simple_shmem();
355*4882a593Smuzhiyun mremap_dontunmap_simple_fixed();
356*4882a593Smuzhiyun mremap_dontunmap_partial_mapping();
357*4882a593Smuzhiyun mremap_dontunmap_partial_mapping_overwrite();
358*4882a593Smuzhiyun
359*4882a593Smuzhiyun BUG_ON(munmap(page_buffer, page_size) == -1,
360*4882a593Smuzhiyun "unable to unmap page buffer");
361*4882a593Smuzhiyun
362*4882a593Smuzhiyun printf("OK\n");
363*4882a593Smuzhiyun return 0;
364*4882a593Smuzhiyun }
365