|
@@ -0,0 +1,72 @@
|
|
|
|
+#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(addr, SIZE);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ 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");
|
|
|
|
+}
|