1f08c3bdfSopenharmony_ci#include <stdio.h>
2f08c3bdfSopenharmony_ci#include <stdlib.h>
3f08c3bdfSopenharmony_ci#include <unistd.h>
4f08c3bdfSopenharmony_ci#include <dirent.h>
5f08c3bdfSopenharmony_ci#include <sys/mman.h>
6f08c3bdfSopenharmony_ci#include <sys/ipc.h>
7f08c3bdfSopenharmony_ci#include <sys/shm.h>
8f08c3bdfSopenharmony_ci
9f08c3bdfSopenharmony_ciint HPS;
10f08c3bdfSopenharmony_cichar hugetlbfsdir[256];
11f08c3bdfSopenharmony_ci#ifndef UTILS
12f08c3bdfSopenharmony_ci#include "utils.h"
13f08c3bdfSopenharmony_ci#endif
14f08c3bdfSopenharmony_ci#define errmsg(x) fprintf(stderr, x), exit(1)
15f08c3bdfSopenharmony_ci
16f08c3bdfSopenharmony_ci/*
17f08c3bdfSopenharmony_ci * Function    : write_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
18f08c3bdfSopenharmony_ci * Parameters  :
19f08c3bdfSopenharmony_ci *     addr            head address of hugepage range
20f08c3bdfSopenharmony_ci *     nr_hugepage     hugepage number from head address
21f08c3bdfSopenharmony_ci *     avoid_addr      the address which avoid to be operated
22f08c3bdfSopenharmony_ci */
23f08c3bdfSopenharmony_civoid write_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
24f08c3bdfSopenharmony_ci{
25f08c3bdfSopenharmony_ci	int i, j;
26f08c3bdfSopenharmony_ci	for (i = 0; i < nr_hugepage; i++) {
27f08c3bdfSopenharmony_ci		if ((addr + i * HPS) == avoid_addr)
28f08c3bdfSopenharmony_ci			continue;
29f08c3bdfSopenharmony_ci		for (j = 0; j < HPS; j++) {
30f08c3bdfSopenharmony_ci			*(addr + i * HPS + j) = (char)('a' + ((i + j) % 26));
31f08c3bdfSopenharmony_ci		}
32f08c3bdfSopenharmony_ci	}
33f08c3bdfSopenharmony_ci}
34f08c3bdfSopenharmony_ci
35f08c3bdfSopenharmony_ci/*
36f08c3bdfSopenharmony_ci * Function    : read_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
37f08c3bdfSopenharmony_ci * Parameters  :
38f08c3bdfSopenharmony_ci *     addr            head address of hugepage range
39f08c3bdfSopenharmony_ci *     nr_hugepage     hugepage number from head address
40f08c3bdfSopenharmony_ci *     avoid_addr      the address which avoid to be operated
41f08c3bdfSopenharmony_ci *
42f08c3bdfSopenharmony_ci * return      :
43f08c3bdfSopenharmony_ci *     0               OK
44f08c3bdfSopenharmony_ci *     -1              if buffer content differs from the expected ones
45f08c3bdfSopenharmony_ci */
46f08c3bdfSopenharmony_ciint read_hugepage(char *addr, int nr_hugepage, char *avoid_addr)
47f08c3bdfSopenharmony_ci{
48f08c3bdfSopenharmony_ci	int i, j;
49f08c3bdfSopenharmony_ci	int ret = 0;
50f08c3bdfSopenharmony_ci
51f08c3bdfSopenharmony_ci	for (i = 0; i < nr_hugepage; i++) {
52f08c3bdfSopenharmony_ci		if ((addr + i * HPS) == avoid_addr)
53f08c3bdfSopenharmony_ci			continue;
54f08c3bdfSopenharmony_ci		for (j = 0; j < HPS; j++) {
55f08c3bdfSopenharmony_ci			if (*(addr + i * HPS + j) != (char)('a' + ((i + j) % 26))) {
56f08c3bdfSopenharmony_ci				printf("Mismatch at %d\n", i + j);
57f08c3bdfSopenharmony_ci				ret = -1;
58f08c3bdfSopenharmony_ci				break;
59f08c3bdfSopenharmony_ci			}
60f08c3bdfSopenharmony_ci		}
61f08c3bdfSopenharmony_ci	}
62f08c3bdfSopenharmony_ci	return ret;
63f08c3bdfSopenharmony_ci}
64f08c3bdfSopenharmony_ci
65f08c3bdfSopenharmony_ciint hugetlbfs_root(char *dir)
66f08c3bdfSopenharmony_ci{
67f08c3bdfSopenharmony_ci	int found = 0;
68f08c3bdfSopenharmony_ci	FILE *f = fopen("/proc/mounts", "r");
69f08c3bdfSopenharmony_ci	if (!f) err("open /proc/mounts");
70f08c3bdfSopenharmony_ci	char *line = NULL;
71f08c3bdfSopenharmony_ci	size_t linelen = 0;
72f08c3bdfSopenharmony_ci	char dummy[100];
73f08c3bdfSopenharmony_ci	while (getline(&line, &linelen, f) > 0) {
74f08c3bdfSopenharmony_ci		if (sscanf(line, "none %s hugetlbfs %[^ ]",
75f08c3bdfSopenharmony_ci			   dir, dummy) >= 2) {
76f08c3bdfSopenharmony_ci			found = 1;
77f08c3bdfSopenharmony_ci			break;
78f08c3bdfSopenharmony_ci		}
79f08c3bdfSopenharmony_ci	}
80f08c3bdfSopenharmony_ci	free(line);
81f08c3bdfSopenharmony_ci	fclose(f);
82f08c3bdfSopenharmony_ci	if (!found)
83f08c3bdfSopenharmony_ci		printf("cannot find hugetlbfs directory in /proc/mounts\n");
84f08c3bdfSopenharmony_ci	return found;
85f08c3bdfSopenharmony_ci}
86f08c3bdfSopenharmony_ci
87f08c3bdfSopenharmony_ci/* Assume there is only one types of hugepage size for now. */
88f08c3bdfSopenharmony_ciint gethugepagesize(void)
89f08c3bdfSopenharmony_ci{
90f08c3bdfSopenharmony_ci	int hpagesize = 0;
91f08c3bdfSopenharmony_ci	struct dirent *dent;
92f08c3bdfSopenharmony_ci	DIR *dir;
93f08c3bdfSopenharmony_ci	dir = opendir("/sys/kernel/mm/hugepages");
94f08c3bdfSopenharmony_ci	if (!dir) err("open /sys/kernel/mm/hugepages");
95f08c3bdfSopenharmony_ci	while ((dent = readdir(dir)) != NULL)
96f08c3bdfSopenharmony_ci		if (sscanf(dent->d_name, "hugepages-%dkB", &hpagesize) >= 1)
97f08c3bdfSopenharmony_ci			break;
98f08c3bdfSopenharmony_ci	closedir(dir);
99f08c3bdfSopenharmony_ci	return hpagesize * 1024;
100f08c3bdfSopenharmony_ci}
101f08c3bdfSopenharmony_ci
102f08c3bdfSopenharmony_civoid *alloc_shm_hugepage(int *key, int size)
103f08c3bdfSopenharmony_ci{
104f08c3bdfSopenharmony_ci	void *addr;
105f08c3bdfSopenharmony_ci	int shmid;
106f08c3bdfSopenharmony_ci	if ((shmid = shmget(*key, size,
107f08c3bdfSopenharmony_ci			    SHM_HUGETLB | IPC_CREAT | SHM_R | SHM_W)) < 0) {
108f08c3bdfSopenharmony_ci		perror("shmget");
109f08c3bdfSopenharmony_ci		return NULL;
110f08c3bdfSopenharmony_ci	}
111f08c3bdfSopenharmony_ci	addr = shmat(shmid, (void *)0x0UL, 0);
112f08c3bdfSopenharmony_ci	if (addr == (char *)-1) {
113f08c3bdfSopenharmony_ci		perror("Shared memory attach failure");
114f08c3bdfSopenharmony_ci		shmctl(shmid, IPC_RMID, NULL);
115f08c3bdfSopenharmony_ci		return NULL;
116f08c3bdfSopenharmony_ci	}
117f08c3bdfSopenharmony_ci	*key = shmid;
118f08c3bdfSopenharmony_ci	return addr;
119f08c3bdfSopenharmony_ci}
120f08c3bdfSopenharmony_ci
121f08c3bdfSopenharmony_civoid *alloc_anonymous_hugepage(int size, int private)
122f08c3bdfSopenharmony_ci{
123f08c3bdfSopenharmony_ci	void *addr;
124f08c3bdfSopenharmony_ci	int mapflag = MAP_ANONYMOUS | 0x40000; /* MAP_HUGETLB */
125f08c3bdfSopenharmony_ci	if (private)
126f08c3bdfSopenharmony_ci		mapflag |= MAP_PRIVATE;
127f08c3bdfSopenharmony_ci	else
128f08c3bdfSopenharmony_ci		mapflag |= MAP_SHARED;
129f08c3bdfSopenharmony_ci	if ((addr = mmap(0, size,
130f08c3bdfSopenharmony_ci			 PROT_READ|PROT_WRITE, mapflag, -1, 0)) == MAP_FAILED) {
131f08c3bdfSopenharmony_ci		perror("mmap");
132f08c3bdfSopenharmony_ci		return NULL;
133f08c3bdfSopenharmony_ci	}
134f08c3bdfSopenharmony_ci	return addr;
135f08c3bdfSopenharmony_ci}
136f08c3bdfSopenharmony_ci
137f08c3bdfSopenharmony_civoid *alloc_filebacked_hugepage(char *filepath, int size, int private, int *fd)
138f08c3bdfSopenharmony_ci{
139f08c3bdfSopenharmony_ci	int mapflag = MAP_SHARED;
140f08c3bdfSopenharmony_ci	void *addr;
141f08c3bdfSopenharmony_ci	if (private)
142f08c3bdfSopenharmony_ci		mapflag = MAP_PRIVATE;
143f08c3bdfSopenharmony_ci	if ((*fd = open(filepath, O_CREAT | O_RDWR, 0777)) < 0) {
144f08c3bdfSopenharmony_ci		perror("open");
145f08c3bdfSopenharmony_ci		return NULL;
146f08c3bdfSopenharmony_ci	}
147f08c3bdfSopenharmony_ci	if ((addr = mmap(0, size,
148f08c3bdfSopenharmony_ci			 PROT_READ|PROT_WRITE, mapflag, *fd, 0)) == MAP_FAILED) {
149f08c3bdfSopenharmony_ci		perror("mmap");
150f08c3bdfSopenharmony_ci		unlink(filepath);
151f08c3bdfSopenharmony_ci		return NULL;
152f08c3bdfSopenharmony_ci	}
153f08c3bdfSopenharmony_ci	return addr;
154f08c3bdfSopenharmony_ci}
155f08c3bdfSopenharmony_ci
156f08c3bdfSopenharmony_ciint free_shm_hugepage(int key, void *addr)
157f08c3bdfSopenharmony_ci{
158f08c3bdfSopenharmony_ci	if (shmdt((const void *)addr) != 0) {
159f08c3bdfSopenharmony_ci		perror("Detach failure");
160f08c3bdfSopenharmony_ci		shmctl(key, IPC_RMID, NULL);
161f08c3bdfSopenharmony_ci		return -1;
162f08c3bdfSopenharmony_ci	}
163f08c3bdfSopenharmony_ci	shmctl(key, IPC_RMID, NULL);
164f08c3bdfSopenharmony_ci	return 0;
165f08c3bdfSopenharmony_ci}
166f08c3bdfSopenharmony_ci
167f08c3bdfSopenharmony_ciint free_anonymous_hugepage(void *addr, int size)
168f08c3bdfSopenharmony_ci{
169f08c3bdfSopenharmony_ci	int ret = 0;
170f08c3bdfSopenharmony_ci	if (munmap(addr, size)) {
171f08c3bdfSopenharmony_ci		perror("munmap");
172f08c3bdfSopenharmony_ci		ret = -1;
173f08c3bdfSopenharmony_ci	}
174f08c3bdfSopenharmony_ci	return ret;
175f08c3bdfSopenharmony_ci}
176f08c3bdfSopenharmony_ci
177f08c3bdfSopenharmony_ciint free_filebacked_hugepage(void *addr, int size, int fd, char *filepath)
178f08c3bdfSopenharmony_ci{
179f08c3bdfSopenharmony_ci	int ret = 0;
180f08c3bdfSopenharmony_ci	if (munmap(addr, size)) {
181f08c3bdfSopenharmony_ci		perror("munmap");
182f08c3bdfSopenharmony_ci		ret = -1;
183f08c3bdfSopenharmony_ci	}
184f08c3bdfSopenharmony_ci	if (close(fd)) {
185f08c3bdfSopenharmony_ci		perror("close");
186f08c3bdfSopenharmony_ci		ret = -1;
187f08c3bdfSopenharmony_ci	}
188f08c3bdfSopenharmony_ci	if (filepath) {
189f08c3bdfSopenharmony_ci		if (unlink(filepath)) {
190f08c3bdfSopenharmony_ci			perror("unlink");
191f08c3bdfSopenharmony_ci			ret = -1;
192f08c3bdfSopenharmony_ci		}
193f08c3bdfSopenharmony_ci	} else {
194f08c3bdfSopenharmony_ci		fprintf(stderr, "Filepath not specified.\n");
195f08c3bdfSopenharmony_ci		ret = -1;
196f08c3bdfSopenharmony_ci	}
197f08c3bdfSopenharmony_ci	return ret;
198f08c3bdfSopenharmony_ci}
199