Home | History | Annotate | Download | only in mm
      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