1#include <fcntl.h> 2#include <stdio.h> 3#include <stdlib.h> 4#include <unistd.h> 5 6#include <sys/ioctl.h> 7#include <sys/mman.h> 8#include <sys/prctl.h> 9#include <sys/stat.h> 10#include <sys/types.h> 11 12#include <linux/types.h> 13 14#define MB (1UL << 20) 15#define PAGE_SIZE sysconf(_SC_PAGESIZE) 16 17#define GUP_FAST_BENCHMARK _IOWR('g', 1, struct gup_benchmark) 18 19struct gup_benchmark { 20 __u64 delta_usec; 21 __u64 addr; 22 __u64 size; 23 __u32 nr_pages_per_call; 24 __u32 flags; 25}; 26 27int main(int argc, char **argv) 28{ 29 struct gup_benchmark gup; 30 unsigned long size = 128 * MB; 31 int i, fd, opt, nr_pages = 1, thp = -1, repeats = 1, write = 0; 32 char *p; 33 34 while ((opt = getopt(argc, argv, "m:r:n:tT")) != -1) { 35 switch (opt) { 36 case 'm': 37 size = atoi(optarg) * MB; 38 break; 39 case 'r': 40 repeats = atoi(optarg); 41 break; 42 case 'n': 43 nr_pages = atoi(optarg); 44 break; 45 case 't': 46 thp = 1; 47 break; 48 case 'T': 49 thp = 0; 50 break; 51 case 'w': 52 write = 1; 53 default: 54 return -1; 55 } 56 } 57 58 gup.nr_pages_per_call = nr_pages; 59 gup.flags = write; 60 61 fd = open("/sys/kernel/debug/gup_benchmark", O_RDWR); 62 if (fd == -1) 63 perror("open"), exit(1); 64 65 p = mmap(NULL, size, PROT_READ | PROT_WRITE, 66 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 67 if (p == MAP_FAILED) 68 perror("mmap"), exit(1); 69 gup.addr = (unsigned long)p; 70 71 if (thp == 1) 72 madvise(p, size, MADV_HUGEPAGE); 73 else if (thp == 0) 74 madvise(p, size, MADV_NOHUGEPAGE); 75 76 for (; (unsigned long)p < gup.addr + size; p += PAGE_SIZE) 77 p[0] = 0; 78 79 for (i = 0; i < repeats; i++) { 80 gup.size = size; 81 if (ioctl(fd, GUP_FAST_BENCHMARK, &gup)) 82 perror("ioctl"), exit(1); 83 84 printf("Time: %lld us", gup.delta_usec); 85 if (gup.size != size) 86 printf(", truncated (size: %lld)", gup.size); 87 printf("\n"); 88 } 89 90 return 0; 91} 92