| // SPDX-License-Identifier: GPL-2.0 |
| #include <stdio.h> |
| #include <sys/mman.h> |
| #include <unistd.h> |
| |
| #include "utils.h" |
| |
| /* This must match the huge page & THP size */ |
| #define SIZE (16 * 1024 * 1024) |
| |
| static int test_body(void) |
| { |
| void *addr; |
| char *p; |
| |
| addr = (void *)0xa0000000; |
| |
| p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, |
| MAP_HUGETLB | MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| if (p != MAP_FAILED) { |
| /* |
| * Typically the mmap will fail because no huge pages are |
| * allocated on the system. But if there are huge pages |
| * allocated the mmap will succeed. That's fine too, we just |
| * munmap here before continuing. munmap() length of |
| * MAP_HUGETLB memory must be hugepage aligned. |
| */ |
| if (munmap(addr, SIZE)) { |
| perror("munmap"); |
| return 1; |
| } |
| } |
| |
| p = mmap(addr, SIZE, PROT_READ | PROT_WRITE, |
| MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); |
| if (p == MAP_FAILED) { |
| printf("Mapping failed @ %p\n", addr); |
| perror("mmap"); |
| return 1; |
| } |
| |
| /* |
| * Either a user or kernel access is sufficient to trigger the bug. |
| * A kernel access is easier to spot & debug, as it will trigger the |
| * softlockup or RCU stall detectors, and when the system is kicked |
| * into xmon we get a backtrace in the kernel. |
| * |
| * A good option is: |
| * getcwd(p, SIZE); |
| * |
| * For the purposes of this testcase it's preferable to spin in |
| * userspace, so the harness can kill us if we get stuck. That way we |
| * see a test failure rather than a dead system. |
| */ |
| *p = 0xf; |
| |
| munmap(addr, SIZE); |
| |
| return 0; |
| } |
| |
| static int test_main(void) |
| { |
| int i; |
| |
| /* 10,000 because it's a "bunch", and completes reasonably quickly */ |
| for (i = 0; i < 10000; i++) |
| if (test_body()) |
| return 1; |
| |
| return 0; |
| } |
| |
| int main(void) |
| { |
| return test_harness(test_main, "hugetlb_vs_thp"); |
| } |