1 #include <stdio.h> 2 #include <sys/mman.h> 3 #include <unistd.h> 4 5 #include "utils.h" 6 7 /* This must match the huge page & THP size */ 8 #define SIZE (16 * 1024 * 1024) 9 10 static int test_body(void) 11 { 12 void *addr; 13 char *p; 14 15 addr = (void *)0xa0000000; 16 17 p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, 18 MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 19 if (p != MAP_FAILED) { 20 /* 21 * Typically the mmap will fail because no huge pages are 22 * allocated on the system. But if there are huge pages 23 * allocated the mmap will succeed. That's fine too, we just 24 * munmap here before continuing. munmap() length of 25 * MAP_HUGETLB memory must be hugepage aligned. 26 */ 27 if (munmap(addr, SIZE)) { 28 perror("munmap"); 29 return 1; 30 } 31 } 32 33 p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, 34 MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); 35 if (p == MAP_FAILED) { 36 printf("Mapping failed @ %p\n", addr); 37 perror("mmap"); 38 return 1; 39 } 40 41 /* 42 * Either a user or kernel access is sufficient to trigger the bug. 43 * A kernel access is easier to spot & debug, as it will trigger the 44 * softlockup or RCU stall detectors, and when the system is kicked 45 * into xmon we get a backtrace in the kernel. 46 * 47 * A good option is: 48 * getcwd(p, SIZE); 49 * 50 * For the purposes of this testcase it's preferable to spin in 51 * userspace, so the harness can kill us if we get stuck. That way we 52 * see a test failure rather than a dead system. 53 */ 54 *p = 0xf; 55 56 munmap(addr, SIZE); 57 58 return 0; 59 } 60 61 static int test_main(void) 62 { 63 int i; 64 65 /* 10,000 because it's a "bunch", and completes reasonably quickly */ 66 for (i = 0; i < 10000; i++) 67 if (test_body()) 68 return 1; 69 70 return 0; 71 } 72 73 int main(void) 74 { 75 return test_harness(test_main, "hugetlb_vs_thp"); 76 } 77