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