162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * hugepage-mmap: 462306a36Sopenharmony_ci * 562306a36Sopenharmony_ci * Example of using huge page memory in a user application using the mmap 662306a36Sopenharmony_ci * system call. Before running this application, make sure that the 762306a36Sopenharmony_ci * administrator has mounted the hugetlbfs filesystem (on some directory 862306a36Sopenharmony_ci * like /mnt) using the command mount -t hugetlbfs nodev /mnt. In this 962306a36Sopenharmony_ci * example, the app is requesting memory of size 256MB that is backed by 1062306a36Sopenharmony_ci * huge pages. 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * For the ia64 architecture, the Linux kernel reserves Region number 4 for 1362306a36Sopenharmony_ci * huge pages. That means that if one requires a fixed address, a huge page 1462306a36Sopenharmony_ci * aligned address starting with 0x800000... will be required. If a fixed 1562306a36Sopenharmony_ci * address is not required, the kernel will select an address in the proper 1662306a36Sopenharmony_ci * range. 1762306a36Sopenharmony_ci * Other architectures, such as ppc64, i386 or x86_64 are not so constrained. 1862306a36Sopenharmony_ci */ 1962306a36Sopenharmony_ci#define _GNU_SOURCE 2062306a36Sopenharmony_ci#include <stdlib.h> 2162306a36Sopenharmony_ci#include <stdio.h> 2262306a36Sopenharmony_ci#include <unistd.h> 2362306a36Sopenharmony_ci#include <sys/mman.h> 2462306a36Sopenharmony_ci#include <fcntl.h> 2562306a36Sopenharmony_ci 2662306a36Sopenharmony_ci#define LENGTH (256UL*1024*1024) 2762306a36Sopenharmony_ci#define PROTECTION (PROT_READ | PROT_WRITE) 2862306a36Sopenharmony_ci 2962306a36Sopenharmony_ci/* Only ia64 requires this */ 3062306a36Sopenharmony_ci#ifdef __ia64__ 3162306a36Sopenharmony_ci#define ADDR (void *)(0x8000000000000000UL) 3262306a36Sopenharmony_ci#define FLAGS (MAP_SHARED | MAP_FIXED) 3362306a36Sopenharmony_ci#else 3462306a36Sopenharmony_ci#define ADDR (void *)(0x0UL) 3562306a36Sopenharmony_ci#define FLAGS (MAP_SHARED) 3662306a36Sopenharmony_ci#endif 3762306a36Sopenharmony_ci 3862306a36Sopenharmony_cistatic void check_bytes(char *addr) 3962306a36Sopenharmony_ci{ 4062306a36Sopenharmony_ci printf("First hex is %x\n", *((unsigned int *)addr)); 4162306a36Sopenharmony_ci} 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_cistatic void write_bytes(char *addr) 4462306a36Sopenharmony_ci{ 4562306a36Sopenharmony_ci unsigned long i; 4662306a36Sopenharmony_ci 4762306a36Sopenharmony_ci for (i = 0; i < LENGTH; i++) 4862306a36Sopenharmony_ci *(addr + i) = (char)i; 4962306a36Sopenharmony_ci} 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_cistatic int read_bytes(char *addr) 5262306a36Sopenharmony_ci{ 5362306a36Sopenharmony_ci unsigned long i; 5462306a36Sopenharmony_ci 5562306a36Sopenharmony_ci check_bytes(addr); 5662306a36Sopenharmony_ci for (i = 0; i < LENGTH; i++) 5762306a36Sopenharmony_ci if (*(addr + i) != (char)i) { 5862306a36Sopenharmony_ci printf("Mismatch at %lu\n", i); 5962306a36Sopenharmony_ci return 1; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci return 0; 6262306a36Sopenharmony_ci} 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ciint main(void) 6562306a36Sopenharmony_ci{ 6662306a36Sopenharmony_ci void *addr; 6762306a36Sopenharmony_ci int fd, ret; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci fd = memfd_create("hugepage-mmap", MFD_HUGETLB); 7062306a36Sopenharmony_ci if (fd < 0) { 7162306a36Sopenharmony_ci perror("memfd_create() failed"); 7262306a36Sopenharmony_ci exit(1); 7362306a36Sopenharmony_ci } 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci addr = mmap(ADDR, LENGTH, PROTECTION, FLAGS, fd, 0); 7662306a36Sopenharmony_ci if (addr == MAP_FAILED) { 7762306a36Sopenharmony_ci perror("mmap"); 7862306a36Sopenharmony_ci close(fd); 7962306a36Sopenharmony_ci exit(1); 8062306a36Sopenharmony_ci } 8162306a36Sopenharmony_ci 8262306a36Sopenharmony_ci printf("Returned address is %p\n", addr); 8362306a36Sopenharmony_ci check_bytes(addr); 8462306a36Sopenharmony_ci write_bytes(addr); 8562306a36Sopenharmony_ci ret = read_bytes(addr); 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci munmap(addr, LENGTH); 8862306a36Sopenharmony_ci close(fd); 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci return ret; 9162306a36Sopenharmony_ci} 92