162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Example of using hugepage memory in a user application using the mmap 462306a36Sopenharmony_ci * system call with MAP_HUGETLB flag. Before running this program make 562306a36Sopenharmony_ci * sure the administrator has allocated enough default sized huge pages 662306a36Sopenharmony_ci * to cover the 256 MB allocation. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages. 962306a36Sopenharmony_ci * That means the addresses starting with 0x800000... will need to be 1062306a36Sopenharmony_ci * specified. Specifying a fixed address is not required on ppc64, i386 1162306a36Sopenharmony_ci * or x86_64. 1262306a36Sopenharmony_ci */ 1362306a36Sopenharmony_ci#include <stdlib.h> 1462306a36Sopenharmony_ci#include <stdio.h> 1562306a36Sopenharmony_ci#include <unistd.h> 1662306a36Sopenharmony_ci#include <sys/mman.h> 1762306a36Sopenharmony_ci#include <fcntl.h> 1862306a36Sopenharmony_ci#include "vm_util.h" 1962306a36Sopenharmony_ci 2062306a36Sopenharmony_ci#define LENGTH (256UL*1024*1024) 2162306a36Sopenharmony_ci#define PROTECTION (PROT_READ | PROT_WRITE) 2262306a36Sopenharmony_ci 2362306a36Sopenharmony_ci/* Only ia64 requires this */ 2462306a36Sopenharmony_ci#ifdef __ia64__ 2562306a36Sopenharmony_ci#define ADDR (void *)(0x8000000000000000UL) 2662306a36Sopenharmony_ci#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED) 2762306a36Sopenharmony_ci#else 2862306a36Sopenharmony_ci#define ADDR (void *)(0x0UL) 2962306a36Sopenharmony_ci#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB) 3062306a36Sopenharmony_ci#endif 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_cistatic void check_bytes(char *addr) 3362306a36Sopenharmony_ci{ 3462306a36Sopenharmony_ci printf("First hex is %x\n", *((unsigned int *)addr)); 3562306a36Sopenharmony_ci} 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_cistatic void write_bytes(char *addr, size_t length) 3862306a36Sopenharmony_ci{ 3962306a36Sopenharmony_ci unsigned long i; 4062306a36Sopenharmony_ci 4162306a36Sopenharmony_ci for (i = 0; i < length; i++) 4262306a36Sopenharmony_ci *(addr + i) = (char)i; 4362306a36Sopenharmony_ci} 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_cistatic int read_bytes(char *addr, size_t length) 4662306a36Sopenharmony_ci{ 4762306a36Sopenharmony_ci unsigned long i; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci check_bytes(addr); 5062306a36Sopenharmony_ci for (i = 0; i < length; i++) 5162306a36Sopenharmony_ci if (*(addr + i) != (char)i) { 5262306a36Sopenharmony_ci printf("Mismatch at %lu\n", i); 5362306a36Sopenharmony_ci return 1; 5462306a36Sopenharmony_ci } 5562306a36Sopenharmony_ci return 0; 5662306a36Sopenharmony_ci} 5762306a36Sopenharmony_ci 5862306a36Sopenharmony_ciint main(int argc, char **argv) 5962306a36Sopenharmony_ci{ 6062306a36Sopenharmony_ci void *addr; 6162306a36Sopenharmony_ci int ret; 6262306a36Sopenharmony_ci size_t hugepage_size; 6362306a36Sopenharmony_ci size_t length = LENGTH; 6462306a36Sopenharmony_ci int flags = FLAGS; 6562306a36Sopenharmony_ci int shift = 0; 6662306a36Sopenharmony_ci 6762306a36Sopenharmony_ci hugepage_size = default_huge_page_size(); 6862306a36Sopenharmony_ci /* munmap with fail if the length is not page aligned */ 6962306a36Sopenharmony_ci if (hugepage_size > length) 7062306a36Sopenharmony_ci length = hugepage_size; 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci if (argc > 1) 7362306a36Sopenharmony_ci length = atol(argv[1]) << 20; 7462306a36Sopenharmony_ci if (argc > 2) { 7562306a36Sopenharmony_ci shift = atoi(argv[2]); 7662306a36Sopenharmony_ci if (shift) 7762306a36Sopenharmony_ci flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT; 7862306a36Sopenharmony_ci } 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci if (shift) 8162306a36Sopenharmony_ci printf("%u kB hugepages\n", 1 << (shift - 10)); 8262306a36Sopenharmony_ci else 8362306a36Sopenharmony_ci printf("Default size hugepages\n"); 8462306a36Sopenharmony_ci printf("Mapping %lu Mbytes\n", (unsigned long)length >> 20); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci addr = mmap(ADDR, length, PROTECTION, flags, -1, 0); 8762306a36Sopenharmony_ci if (addr == MAP_FAILED) { 8862306a36Sopenharmony_ci perror("mmap"); 8962306a36Sopenharmony_ci exit(1); 9062306a36Sopenharmony_ci } 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci printf("Returned address is %p\n", addr); 9362306a36Sopenharmony_ci check_bytes(addr); 9462306a36Sopenharmony_ci write_bytes(addr, length); 9562306a36Sopenharmony_ci ret = read_bytes(addr, length); 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */ 9862306a36Sopenharmony_ci if (munmap(addr, length)) { 9962306a36Sopenharmony_ci perror("munmap"); 10062306a36Sopenharmony_ci exit(1); 10162306a36Sopenharmony_ci } 10262306a36Sopenharmony_ci 10362306a36Sopenharmony_ci return ret; 10462306a36Sopenharmony_ci} 105