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