int main(int ac, char **av) { int lc; int Hflag = 0; long page_sz, map_sz; int sflag = 0; option_t options[] = { {"H:", &Hflag, &Hopt}, {"s:", &sflag, &nr_opt}, {NULL, NULL, NULL} }; tst_parse_opts(ac, av, options, &help); check_hugepage(); if (!Hflag) { tst_tmpdir(); Hopt = tst_get_tmpdir(); } if (sflag) hugepages = SAFE_STRTOL(NULL, nr_opt, 0, LONG_MAX); page_sz = getpagesize(); map_sz = read_meminfo("Hugepagesize:") * 1024 * 2; setup(); for (lc = 0; TEST_LOOPING(lc); lc++) { /* Creat a temporary file used for huge mapping */ fildes = open(TEMPFILE, O_RDWR | O_CREAT, 0666); if (fildes < 0) tst_brkm(TBROK | TERRNO, cleanup, "opening %s failed", TEMPFILE); /* Creat a file used for normal mapping */ nfildes = open("/dev/zero", O_RDONLY, 0666); if (nfildes < 0) tst_brkm(TBROK | TERRNO, cleanup, "opening /dev/zero failed"); tst_count = 0; /* * Call mmap on /dev/zero 5 times */ for (i = 0; i < 5; i++) { addr = mmap(0, 256 * 1024 * 1024, PROT_READ, MAP_SHARED, nfildes, 0); addrlist[i] = addr; } while (range_is_mapped(cleanup, low_addr, low_addr + map_sz) == 1) { low_addr = low_addr + 0x10000000; if (low_addr < LOW_ADDR) tst_brkm(TBROK | TERRNO, cleanup, "no empty region to use"); } /* mmap using normal pages and a low memory address */ addr = mmap((void *)low_addr, page_sz, PROT_READ, MAP_SHARED | MAP_FIXED, nfildes, 0); if (addr == MAP_FAILED) tst_brkm(TBROK | TERRNO, cleanup, "mmap failed on nfildes"); while (range_is_mapped(cleanup, low_addr2, low_addr2 + map_sz) == 1) { low_addr2 = low_addr2 + 0x10000000; if (low_addr2 < LOW_ADDR2) tst_brkm(TBROK | TERRNO, cleanup, "no empty region to use"); } /* Attempt to mmap a huge page into a low memory address */ addr2 = mmap((void *)low_addr2, map_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fildes, 0); #if __WORDSIZE == 64 /* 64-bit process */ if (addr2 == MAP_FAILED) { tst_resm(TFAIL | TERRNO, "huge mmap failed unexpectedly" " with %s (64-bit)", TEMPFILE); close(fildes); continue; } else { tst_resm(TPASS, "huge mmap succeeded (64-bit)"); } #else /* 32-bit process */ if (addr2 == MAP_FAILED) tst_resm(TFAIL | TERRNO, "huge mmap failed unexpectedly" " with %s (32-bit)", TEMPFILE); else if (addr2 > 0) { tst_resm(TCONF, "huge mmap failed to test the scenario"); close(fildes); continue; } else if (addr == 0) tst_resm(TPASS, "huge mmap succeeded (32-bit)"); #endif /* Clean up things in case we are looping */ for (i = 0; i < 5; i++) { if (munmap(addrlist[i], 256 * 1024 * 1024) == -1) tst_resm(TBROK | TERRNO, "munmap of addrlist[%d] failed", i); } #if __WORDSIZE == 64 if (munmap(addr2, map_sz) == -1) tst_brkm(TFAIL | TERRNO, NULL, "huge munmap failed"); #endif if (munmap(addr, page_sz) == -1) tst_brkm(TFAIL | TERRNO, NULL, "munmap failed"); close(fildes); } cleanup(); tst_exit(); }
int main(int argc, char *argv[]) { long hpage_size; int fd; void *p; unsigned long straddle_addr; test_init(argc, argv); hpage_size = check_hugepagesize(); if (sizeof(void *) <= 4) TEST_BUG("64-bit only"); if (hpage_size > FOURGB) CONFIG("Huge page size too large"); fd = hugetlbfs_unlinked_fd(); if (fd < 0) FAIL("hugetlbfs_unlinked_fd()"); straddle_addr = FOURGB - hpage_size; /* We first try to get the mapping without MAP_FIXED */ verbose_printf("Mapping without MAP_FIXED at %lx...", straddle_addr); p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0); if (p == (void *)straddle_addr) { /* These tests irrelevant if we didn't get the * straddle address */ verbose_printf("done\n"); if (test_addr_huge(p) != 1) FAIL("Mapped address is not hugepage"); if (test_addr_huge(p + hpage_size) != 1) FAIL("Mapped address is not hugepage"); verbose_printf("Clearing below 4GB..."); memset(p, 0, hpage_size); verbose_printf("done\n"); verbose_printf("Clearing above 4GB..."); memset(p + hpage_size, 0, hpage_size); verbose_printf("done\n"); } else { verbose_printf("got %p instead, never mind\n", p); munmap(p, 2*hpage_size); } verbose_printf("Mapping with MAP_FIXED at %lx...", straddle_addr); p = mmap((void *)straddle_addr, 2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED|MAP_FIXED, fd, 0); if (p == MAP_FAILED) { /* this area crosses last low slice and first high slice */ unsigned long below_start = FOURGB - 256L*1024*1024; unsigned long above_end = 1024L*1024*1024*1024; if (range_is_mapped(below_start, above_end) == 1) { verbose_printf("region (4G-256M)-1T is not free\n"); verbose_printf("mmap() failed: %s\n", strerror(errno)); PASS_INCONCLUSIVE(); } else FAIL("mmap() FIXED failed: %s\n", strerror(errno)); } if (p != (void *)straddle_addr) { verbose_printf("got %p instead\n", p); FAIL("Wrong address with MAP_FIXED"); } verbose_printf("done\n"); if (test_addr_huge(p) != 1) FAIL("Mapped address is not hugepage"); if (test_addr_huge(p + hpage_size) != 1) FAIL("Mapped address is not hugepage"); verbose_printf("Clearing below 4GB..."); memset(p, 0, hpage_size); verbose_printf("done\n"); verbose_printf("Clearing above 4GB..."); memset(p + hpage_size, 0, hpage_size); verbose_printf("done\n"); verbose_printf("Tested above 4GB\n"); PASS(); }