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 | |