1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
|
// 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");
}
|