Beispiel #1
0
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();
}