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
23static int fd = -1;
24static long hpage_size, page_size;
25
26static 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
48cleanup:
49	SAFE_MUNMAP(a, page_size);
50	return ret;
51}
52
53static 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
81cleanup:
82	SAFE_MUNMAP(p, hpage_size);
83	SAFE_CLOSE(fd);
84}
85
86static void setup(void)
87{
88	hpage_size = tst_get_hugepage_size();
89	page_size = getpagesize();
90}
91
92static void cleanup(void)
93{
94	if (fd >= 0)
95		SAFE_CLOSE(fd);
96}
97
98static 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