linux/tools/testing/selftests/vm/map_hugetlb.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2/*
   3 * Example of using hugepage memory in a user application using the mmap
   4 * system call with MAP_HUGETLB flag.  Before running this program make
   5 * sure the administrator has allocated enough default sized huge pages
   6 * to cover the 256 MB allocation.
   7 *
   8 * For ia64 architecture, Linux kernel reserves Region number 4 for hugepages.
   9 * That means the addresses starting with 0x800000... will need to be
  10 * specified.  Specifying a fixed address is not required on ppc64, i386
  11 * or x86_64.
  12 */
  13#include <stdlib.h>
  14#include <stdio.h>
  15#include <unistd.h>
  16#include <sys/mman.h>
  17#include <fcntl.h>
  18
  19#define LENGTH (256UL*1024*1024)
  20#define PROTECTION (PROT_READ | PROT_WRITE)
  21
  22#ifndef MAP_HUGETLB
  23#define MAP_HUGETLB 0x40000 /* arch specific */
  24#endif
  25
  26#ifndef MAP_HUGE_SHIFT
  27#define MAP_HUGE_SHIFT 26
  28#endif
  29
  30#ifndef MAP_HUGE_MASK
  31#define MAP_HUGE_MASK 0x3f
  32#endif
  33
  34/* Only ia64 requires this */
  35#ifdef __ia64__
  36#define ADDR (void *)(0x8000000000000000UL)
  37#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB | MAP_FIXED)
  38#else
  39#define ADDR (void *)(0x0UL)
  40#define FLAGS (MAP_PRIVATE | MAP_ANONYMOUS | MAP_HUGETLB)
  41#endif
  42
  43static void check_bytes(char *addr)
  44{
  45        printf("First hex is %x\n", *((unsigned int *)addr));
  46}
  47
  48static void write_bytes(char *addr)
  49{
  50        unsigned long i;
  51
  52        for (i = 0; i < LENGTH; i++)
  53                *(addr + i) = (char)i;
  54}
  55
  56static int read_bytes(char *addr)
  57{
  58        unsigned long i;
  59
  60        check_bytes(addr);
  61        for (i = 0; i < LENGTH; i++)
  62                if (*(addr + i) != (char)i) {
  63                        printf("Mismatch at %lu\n", i);
  64                        return 1;
  65                }
  66        return 0;
  67}
  68
  69int main(int argc, char **argv)
  70{
  71        void *addr;
  72        int ret;
  73        size_t length = LENGTH;
  74        int flags = FLAGS;
  75        int shift = 0;
  76
  77        if (argc > 1)
  78                length = atol(argv[1]) << 20;
  79        if (argc > 2) {
  80                shift = atoi(argv[2]);
  81                if (shift)
  82                        flags |= (shift & MAP_HUGE_MASK) << MAP_HUGE_SHIFT;
  83        }
  84
  85        if (shift)
  86                printf("%u kB hugepages\n", 1 << shift);
  87        else
  88                printf("Default size hugepages\n");
  89        printf("Mapping %lu Mbytes\n", (unsigned long)length >> 20);
  90
  91        addr = mmap(ADDR, length, PROTECTION, flags, -1, 0);
  92        if (addr == MAP_FAILED) {
  93                perror("mmap");
  94                exit(1);
  95        }
  96
  97        printf("Returned address is %p\n", addr);
  98        check_bytes(addr);
  99        write_bytes(addr);
 100        ret = read_bytes(addr);
 101
 102        /* munmap() length of MAP_HUGETLB memory must be hugepage aligned */
 103        if (munmap(addr, LENGTH)) {
 104                perror("munmap");
 105                exit(1);
 106        }
 107
 108        return ret;
 109}
 110