1f08c3bdfSopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
2f08c3bdfSopenharmony_ci/*
3f08c3bdfSopenharmony_ci * Copyright (c) International Business Machines  Corp., 2004
4f08c3bdfSopenharmony_ci * Copyright (c) Linux Test Project, 2004-2017
5f08c3bdfSopenharmony_ci *
6f08c3bdfSopenharmony_ci * Test Name: hugemmap04
7f08c3bdfSopenharmony_ci *
8f08c3bdfSopenharmony_ci * Test Description:
9f08c3bdfSopenharmony_ci *  Verify that, a hugetlb mmap() succeeds when used to map the largest
10f08c3bdfSopenharmony_ci *  size possible.
11f08c3bdfSopenharmony_ci *
12f08c3bdfSopenharmony_ci * Expected Result:
13f08c3bdfSopenharmony_ci *  mmap() should succeed returning the address of the hugetlb mapped region.
14f08c3bdfSopenharmony_ci *  The number of free huge pages should decrease.
15f08c3bdfSopenharmony_ci *
16f08c3bdfSopenharmony_ci * Test:
17f08c3bdfSopenharmony_ci *  Loop if the proper options are given.
18f08c3bdfSopenharmony_ci *  Execute system call
19f08c3bdfSopenharmony_ci *  Check return code, if system call failed (return=-1)
20f08c3bdfSopenharmony_ci *  Log the errno and Issue a FAIL message.
21f08c3bdfSopenharmony_ci *
22f08c3bdfSopenharmony_ci * HISTORY
23f08c3bdfSopenharmony_ci *  04/2004 Written by Robbie Williamson
24f08c3bdfSopenharmony_ci */
25f08c3bdfSopenharmony_ci
26f08c3bdfSopenharmony_ci#include <sys/mount.h>
27f08c3bdfSopenharmony_ci#include <stdio.h>
28f08c3bdfSopenharmony_ci#include <limits.h>
29f08c3bdfSopenharmony_ci#include <sys/param.h>
30f08c3bdfSopenharmony_ci#include "lapi/abisize.h"
31f08c3bdfSopenharmony_ci#include "hugetlb.h"
32f08c3bdfSopenharmony_ci
33f08c3bdfSopenharmony_cistatic char TEMPFILE[MAXPATHLEN];
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_cistatic long *addr;
36f08c3bdfSopenharmony_cistatic long long mapsize;
37f08c3bdfSopenharmony_cistatic int fildes;
38f08c3bdfSopenharmony_cistatic long freepages;
39f08c3bdfSopenharmony_cistatic long beforetest;
40f08c3bdfSopenharmony_cistatic long aftertest;
41f08c3bdfSopenharmony_cistatic long hugepagesmapped;
42f08c3bdfSopenharmony_ci
43f08c3bdfSopenharmony_cistatic void test_hugemmap(void)
44f08c3bdfSopenharmony_ci{
45f08c3bdfSopenharmony_ci	int huge_pagesize = 0;
46f08c3bdfSopenharmony_ci
47f08c3bdfSopenharmony_ci	/* Creat a temporary file used for huge mapping */
48f08c3bdfSopenharmony_ci	fildes = SAFE_OPEN(TEMPFILE, O_RDWR | O_CREAT, 0666);
49f08c3bdfSopenharmony_ci
50f08c3bdfSopenharmony_ci	freepages = SAFE_READ_MEMINFO("HugePages_Free:");
51f08c3bdfSopenharmony_ci	beforetest = freepages;
52f08c3bdfSopenharmony_ci
53f08c3bdfSopenharmony_ci	huge_pagesize = SAFE_READ_MEMINFO("Hugepagesize:");
54f08c3bdfSopenharmony_ci	tst_res(TINFO, "Size of huge pages is %d KB", huge_pagesize);
55f08c3bdfSopenharmony_ci
56f08c3bdfSopenharmony_ci#ifdef TST_ABI32
57f08c3bdfSopenharmony_ci	tst_res(TINFO, "Total amount of free huge pages is %ld",
58f08c3bdfSopenharmony_ci			freepages);
59f08c3bdfSopenharmony_ci	tst_res(TINFO, "Max number allowed for 1 mmap file in"
60f08c3bdfSopenharmony_ci			" 32-bits is 128");
61f08c3bdfSopenharmony_ci	if (freepages > 128)
62f08c3bdfSopenharmony_ci		freepages = 128;
63f08c3bdfSopenharmony_ci#endif
64f08c3bdfSopenharmony_ci	mapsize = (long long)freepages * huge_pagesize * 1024;
65f08c3bdfSopenharmony_ci	addr = mmap(NULL, mapsize, PROT_READ | PROT_WRITE,
66f08c3bdfSopenharmony_ci			MAP_SHARED, fildes, 0);
67f08c3bdfSopenharmony_ci	if (addr == MAP_FAILED) {
68f08c3bdfSopenharmony_ci		tst_res(TFAIL | TERRNO, "mmap() Failed on %s",
69f08c3bdfSopenharmony_ci				TEMPFILE);
70f08c3bdfSopenharmony_ci	} else {
71f08c3bdfSopenharmony_ci		tst_res(TPASS,
72f08c3bdfSopenharmony_ci				"Succeeded mapping file using %ld pages",
73f08c3bdfSopenharmony_ci				freepages);
74f08c3bdfSopenharmony_ci
75f08c3bdfSopenharmony_ci		/* force to allocate page and change HugePages_Free */
76f08c3bdfSopenharmony_ci		*(int *)addr = 0;
77f08c3bdfSopenharmony_ci		/* Make sure the number of free huge pages AFTER testing decreased */
78f08c3bdfSopenharmony_ci		aftertest = SAFE_READ_MEMINFO("HugePages_Free:");
79f08c3bdfSopenharmony_ci		hugepagesmapped = beforetest - aftertest;
80f08c3bdfSopenharmony_ci		if (hugepagesmapped < 1)
81f08c3bdfSopenharmony_ci			tst_res(TWARN, "Number of HUGEPAGES_FREE stayed the"
82f08c3bdfSopenharmony_ci					" same. Okay if multiple copies running due"
83f08c3bdfSopenharmony_ci					" to test collision.");
84f08c3bdfSopenharmony_ci	}
85f08c3bdfSopenharmony_ci
86f08c3bdfSopenharmony_ci	munmap(addr, mapsize);
87f08c3bdfSopenharmony_ci	close(fildes);
88f08c3bdfSopenharmony_ci}
89f08c3bdfSopenharmony_ci
90f08c3bdfSopenharmony_civoid setup(void)
91f08c3bdfSopenharmony_ci{
92f08c3bdfSopenharmony_ci	if (tst_hugepages == 0)
93f08c3bdfSopenharmony_ci		tst_brk(TCONF, "Not enough hugepages for testing!");
94f08c3bdfSopenharmony_ci
95f08c3bdfSopenharmony_ci	if (!Hopt)
96f08c3bdfSopenharmony_ci		Hopt = tst_get_tmpdir();
97f08c3bdfSopenharmony_ci	SAFE_MOUNT("none", Hopt, "hugetlbfs", 0, NULL);
98f08c3bdfSopenharmony_ci
99f08c3bdfSopenharmony_ci	snprintf(TEMPFILE, sizeof(TEMPFILE), "%s/mmapfile%d", Hopt, getpid());
100f08c3bdfSopenharmony_ci}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_civoid cleanup(void)
103f08c3bdfSopenharmony_ci{
104f08c3bdfSopenharmony_ci	unlink(TEMPFILE);
105f08c3bdfSopenharmony_ci	umount(Hopt);
106f08c3bdfSopenharmony_ci}
107f08c3bdfSopenharmony_ci
108f08c3bdfSopenharmony_cistatic struct tst_test test = {
109f08c3bdfSopenharmony_ci	.needs_root = 1,
110f08c3bdfSopenharmony_ci	.needs_tmpdir = 1,
111f08c3bdfSopenharmony_ci	.options = (struct tst_option[]) {
112f08c3bdfSopenharmony_ci		{"H:", &Hopt,   "Location of hugetlbfs, i.e.  -H /var/hugetlbfs"},
113f08c3bdfSopenharmony_ci		{"s:", &nr_opt, "Set the number of the been allocated hugepages"},
114f08c3bdfSopenharmony_ci		{}
115f08c3bdfSopenharmony_ci	},
116f08c3bdfSopenharmony_ci	.setup = setup,
117f08c3bdfSopenharmony_ci	.cleanup = cleanup,
118f08c3bdfSopenharmony_ci	.test_all = test_hugemmap,
119f08c3bdfSopenharmony_ci	.hugepages = {128, TST_REQUEST},
120f08c3bdfSopenharmony_ci};
121