1 // SPDX-License-Identifier: LGPL-2.1-or-later
2 /*
3 * Copyright (C) 2009 IBM Corporation.
4 * Author: David Gibson
5 */
6
7 /*\
8 * [Description]
9 *
10 * Test Description: The kernel has bug for mremap() on some architecture.
11 * mremap() can cause crashes on architectures with holes in the address
12 * space (like ia64) and on powerpc with it's distinct page size "slices".
13 *
14 * This test get the huge mapping address and mremap() normal mapping
15 * near to this huge mapping.
16 */
17
18 #define _GNU_SOURCE
19 #include "hugetlb.h"
20
21 #define MNTPOINT "hugetlbfs/"
22
23 static int fd = -1;
24 static long hpage_size, page_size;
25
do_remap(void * target)26 static int do_remap(void *target)
27 {
28 void *a, *b;
29 int ret;
30
31 a = SAFE_MMAP(NULL, page_size, PROT_READ|PROT_WRITE,
32 MAP_SHARED|MAP_ANONYMOUS, -1, 0);
33
34 ret = do_readback(a, page_size, "base normal");
35 if (ret)
36 goto cleanup;
37
38 b = mremap(a, page_size, page_size, MREMAP_MAYMOVE | MREMAP_FIXED,
39 target);
40
41 if (b != MAP_FAILED) {
42 do_readback(b, page_size, "remapped");
43 a = b;
44 } else {
45 tst_res(TINFO|TERRNO, "mremap(MAYMOVE|FIXED) disallowed");
46 }
47
48 cleanup:
49 SAFE_MUNMAP(a, page_size);
50 return ret;
51 }
52
run_test(void)53 static void run_test(void)
54 {
55 void *p;
56 int ret;
57
58 fd = tst_creat_unlinked(MNTPOINT, 0);
59 p = SAFE_MMAP(NULL, 3*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
60
61 SAFE_MUNMAP(p, hpage_size);
62
63 SAFE_MUNMAP(p + 2*hpage_size, hpage_size);
64
65 p = p + hpage_size;
66
67 tst_res(TINFO, "Hugepage mapping at %p", p);
68
69 ret = do_readback(p, hpage_size, "base hugepage");
70 if (ret)
71 goto cleanup;
72
73 ret = do_remap(p - page_size);
74 if (ret)
75 goto cleanup;
76
77 ret = do_remap(p + hpage_size);
78 if (ret == 0)
79 tst_res(TPASS, "Successfully tested mremap normal near hpage mapping");
80
81 cleanup:
82 SAFE_MUNMAP(p, hpage_size);
83 SAFE_CLOSE(fd);
84 }
85
setup(void)86 static void setup(void)
87 {
88 hpage_size = tst_get_hugepage_size();
89 page_size = getpagesize();
90 }
91
cleanup(void)92 static void cleanup(void)
93 {
94 if (fd >= 0)
95 SAFE_CLOSE(fd);
96 }
97
98 static struct tst_test test = {
99 .needs_root = 1,
100 .mntpoint = MNTPOINT,
101 .needs_hugetlbfs = 1,
102 .needs_tmpdir = 1,
103 .setup = setup,
104 .cleanup = cleanup,
105 .test_all = run_test,
106 .hugepages = {3, TST_NEEDS},
107 };
108