예제 #1
0
static void test_simple_mlock(int flags)
{
	int fd = hugetlbfs_unlinked_fd();
	void *p;
	int ret;
	long hpage_size = check_hugepagesize();

	p = mmap(0, hpage_size, PROT_READ|PROT_WRITE, flags, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() failed (flags=%x): %s", flags, strerror(errno));

	ret = mlock(p, hpage_size);
	if (ret)
		FAIL("mlock() failed (flags=%x): %s", flags, strerror(errno));

	ret = munlock(p, hpage_size);
	if (ret)
		FAIL("munlock() failed (flags=%x): %s", flags, strerror(errno));

	ret = munmap(p, hpage_size);
	if (ret)
		FAIL("munmap() failed (flags=%x): %s", flags, strerror(errno));

	close(fd);
}
예제 #2
0
/* WARNING: This function relies on the hugetlb pool counters in a way that
 * is known to be racy.  Due to the expected usage of hugetlbfs test cases, the
 * risk of a race is acceptible.  This function should NOT be used for real
 * applications.
 */
int kernel_has_private_reservations(void)
{
	int fd;
	long t, f, r, s;
	long nt, nf, nr, ns;
	long hpage_size = gethugepagesize();
	void *map;

	/* Read pool counters */
	t = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL);
	f = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	r = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	s = get_huge_page_counter(hpage_size, HUGEPAGES_SURP);

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0) {
		ERROR("kernel_has_private_reservations: hugetlbfs_unlinked_fd: "
			"%s\n", strerror(errno));
		return -1;
	}
	map = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (map == MAP_FAILED) {
		ERROR("kernel_has_private_reservations: mmap: %s\n",
			strerror(errno));
		return -1;
	}

	/* Recheck the counters */
	nt = get_huge_page_counter(hpage_size, HUGEPAGES_TOTAL);
	nf = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	nr = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	ns = get_huge_page_counter(hpage_size, HUGEPAGES_SURP);

	munmap(map, hpage_size);
	close(fd);

	/*
	 * There are only three valid cases:
	 * 1) If a surplus page was allocated to create a reservation, all
	 *    four pool counters increment
	 * 2) All counters remain the same except for Hugepages_Rsvd, then
	 *    a reservation was created using an existing pool page.
	 * 3) All counters remain the same, indicates that no reservation has
	 *    been created
	 */
	if ((nt == t + 1) && (nf == f + 1) && (ns == s + 1) && (nr == r + 1)) {
		return 1;
	} else if ((nt == t) && (nf == f) && (ns == s)) {
		if (nr == r + 1)
			return 1;
		else if (nr == r)
			return 0;
	} else {
		ERROR("kernel_has_private_reservations: bad counter state - "
		      "T:%li F:%li R:%li S:%li -> T:%li F:%li R:%li S:%li\n",
			t, f, r, s, nt, nf, nr, ns);
	}
	return -1;
}
예제 #3
0
static void HPX_CONSTRUCTOR _system_init(void) {
  _hugepage_fd = hugetlbfs_unlinked_fd();
  if (_hugepage_fd < 0) {
    log_error("could not get huge tlb file descriptor.\n");
  }
  _hugepage_size = gethugepagesize();
  _hugepage_mask = _hugepage_size - 1;
}
int main(int argc, char *argv[])
{
	long hpage_size;
	int nr_hugepages;
	int fd1, fd2, err;
	char *p, *q;
	struct sigaction sa = {
		.sa_sigaction = sig_handler,
		.sa_flags = SA_SIGINFO,
	};

	test_init(argc, argv);

	hpage_size = check_hugepagesize();
	nr_hugepages = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);

	fd1 = hugetlbfs_unlinked_fd();
	if (fd1 < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	fd2 = hugetlbfs_unlinked_fd();
	if (fd2 < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	err = sigaction(SIGBUS, &sa, NULL);
	if (err)
		FAIL("Can't install SIGBUS handler: %s", strerror(errno));

	p = mmap(NULL, hpage_size * nr_hugepages,
		PROT_READ | PROT_WRITE, MAP_SHARED, fd1, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() 1: %s", strerror(errno));

	verbose_printf("Reserve all hugepages %d\n", nr_hugepages);

	q = mmap(NULL, hpage_size,
		PROT_READ | PROT_WRITE, MAP_SHARED | MAP_NORESERVE, fd2, 0);
	if (q == MAP_FAILED)
		FAIL("mmap() 2: %s", strerror(errno));

	verbose_printf("Write %c to %p to steal reserved page\n", *q, q);

	test_write(q);
	FAIL("Steal reserved page");
}
예제 #5
0
int main(int argc, char *argv[])
{
	int err;
	int fd;
	void *p;

	test_init(argc, argv);

	struct sigaction sa = {
		.sa_sigaction = sig_handler,
		.sa_flags = SA_SIGINFO,
	};

	err = sigaction(SIGSEGV, &sa, NULL);
	if (err)
		FAIL("Can't install SIGSEGV handler: %s", strerror(errno));

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	verbose_printf("instantiating page\n");

	p = mmap(NULL, 2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(): %s", strerror(errno));
	memset(p, 0, hpage_size);
	munmap(p, hpage_size);

	/* Basic protection change tests */
	test_mprotect(fd, "R->RW", hpage_size, PROT_READ,
		      hpage_size, PROT_READ|PROT_WRITE);
	test_mprotect(fd, "RW->R", hpage_size, PROT_READ|PROT_WRITE,
		      hpage_size, PROT_READ);

	/* Tests which require VMA splitting */
	test_mprotect(fd, "R->RW 1/2", 2*hpage_size, PROT_READ,
		      hpage_size, PROT_READ|PROT_WRITE);
	test_mprotect(fd, "RW->R 1/2", 2*hpage_size, PROT_READ|PROT_WRITE,
		      hpage_size, PROT_READ);

	/* PROT_NONE tests */
	test_mprotect(fd, "NONE->R", hpage_size, PROT_NONE,
		      hpage_size, PROT_READ);
	test_mprotect(fd, "NONE->RW", hpage_size, PROT_NONE,
		      hpage_size, PROT_READ|PROT_WRITE);

	PASS();
}
예제 #6
0
int main(int argc, char *argv[])
{
	int fd;

	make_test_mounts();
	test_init(argc, argv);
	in_test = 1;

	fd = hugetlbfs_unlinked_fd();

	fclose(tmp_stream);
	if (fd < 0)
		FAIL("Unable to find mount point\n");

	PASS();
}
예제 #7
0
int main(int argc, char *argv[])
{
	long hpage_size;
	int fd;
	void *p;
	volatile unsigned long *q;
	int err;
	cpu_set_t cpu0, cpu1;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	CPU_ZERO(&cpu0);
	CPU_SET(0, &cpu0);
	CPU_ZERO(&cpu1);
	CPU_SET(1, &cpu1);

	err = sched_setaffinity(getpid(), CPU_SETSIZE/8, &cpu0);
	if (err != 0)
		CONFIG("sched_setaffinity(cpu0): %s", strerror(errno));

	err = sched_setaffinity(getpid(), CPU_SETSIZE/8, &cpu1);
	if (err != 0)
		CONFIG("sched_setaffinity(): %s", strerror(errno));

	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap()");

	err = sched_setaffinity(getpid(), CPU_SETSIZE/8, &cpu0);
	if (err != 0)
		CONFIG("sched_setaffinity(cpu0): %s", strerror(errno));

	q = (volatile unsigned long *)(p + getpagesize());
	*q = 0xdeadbeef;

	PASS_INCONCLUSIVE();
}
예제 #8
0
void _map(int s, int hpages, int flags, int line)
{
	long et, ef, er, es;

	map_fd[s] = hugetlbfs_unlinked_fd();
	if (map_fd[s] < 0)
		CONFIG("Unable to open hugetlbfs file: %s", strerror(errno));
	map_size[s] = hpages * hpage_size;
	map_addr[s] = mmap(NULL, map_size[s], PROT_READ|PROT_WRITE, flags,
				map_fd[s], 0);
	if (map_addr[s] == MAP_FAILED)
		FAIL("mmap failed: %s", strerror(errno));
	touched[s] = 0;

	et = prev_total;
	ef = prev_free;
	er = prev_resv;
	es = prev_surp;

	/*
	 * When using MAP_SHARED, a reservation will be created to guarantee
	 * pages to the process.  If not enough pages are available to
	 * satisfy the reservation, surplus pages are added to the pool.
	 * NOTE: This code assumes that the whole mapping needs to be
	 * reserved and hence, will not work with partial reservations.
	 *
	 * If the kernel supports private reservations, then MAP_PRIVATE
	 * mappings behave like MAP_SHARED at mmap time.  Otherwise,
	 * no counter updates will occur.
	 */
	if ((flags & MAP_SHARED) || private_resv) {
		unsigned long shortfall = 0;
		if (hpages + prev_resv > prev_free)
			shortfall = hpages - prev_free + prev_resv;
		et += shortfall;
		ef = prev_free + shortfall;
		er = prev_resv + hpages;
		es = prev_surp + shortfall;
	}

	verify_counters(line, et, ef, er, es);
}
int main(int argc, char *argv[])
{
	int fd, rc;
	void *p;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();
	page_size = getpagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	p = mmap(NULL, 3*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
		 fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(): %s", strerror(errno));

	rc = munmap(p, hpage_size);
	if (rc != 0)
		FAIL("munmap() low hpage: %s", strerror(errno));

	rc = munmap(p + 2*hpage_size, hpage_size);
	if (rc != 0)
		FAIL("munmap() high hpage: %s", strerror(errno));

	p = p + hpage_size;

	verbose_printf("Hugepage mapping at %p\n", p);

	do_readback(p, hpage_size, "base hugepage");

	do_remap(p - page_size);
	do_remap(p + hpage_size);

	PASS();
}
예제 #10
0
파일: direct.c 프로젝트: sharugupta/OpenUH
int main(int argc, char *argv[])
{
	long hpage_size;
	int fd, dfd;
	void *p;
	size_t ret;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	dfd = open(TMPFILE, O_CREAT|O_EXCL|O_DIRECT|O_RDWR, 0600);
	if (dfd < 0) {
		if (errno == EEXIST)
			CONFIG("Temp file " TMPFILE " already exists");
		else
			CONFIG("Falied to open direct-IO file");
	}
	unlink(TMPFILE);

	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap hugetlbfs file");

	memcpy(p, P0, 8);

	/* Direct write from huge page */
	ret = write(dfd, p, IOSZ);
	if (ret != IOSZ)
		FAIL("Direct-IO write from huge page");
	if (lseek(dfd, 0, SEEK_SET) == -1)
		FAIL("lseek");

	/* Check for accuracy */
	ret = read(dfd, buf, IOSZ);
	if (ret != IOSZ)
		FAIL("Direct-IO read to normal memory");
	if (memcmp(P0, buf, 8))
		FAIL("Memory mismatch after Direct-IO write");
	if (lseek(dfd, 0, SEEK_SET) == -1)
		FAIL("lseek");

	/* Direct read to huge page */
	memset(p, 0, IOSZ);
	ret = read(dfd, p, IOSZ);
	if (ret != IOSZ)
		FAIL("Direct-IO read to huge page");

	/* Check for accuracy */
	if (memcmp(p, P0, 8))
		FAIL("Memory mismatch after Direct-IO read");

	close(dfd);
	unlink(TMPFILE);
	
	PASS();
}
예제 #11
0
/**
 * get_huge_pages - Allocate an amount of memory backed by huge pages
 * len: Size of the region to allocate, must be hugepage-aligned
 * flags: Flags specifying the behaviour of the function
 *
 * This function allocates a region of memory that is backed by huge pages
 * and hugepage-aligned. This is not a suitable drop-in for malloc() but a
 * a malloc library could use this function to create a new fixed-size heap
 * similar in principal to what morecore does for glibc malloc.
 */
void *get_huge_pages(size_t len, ghp_t flags)
{
	void *buf;
	int buf_fd = -1;
	int mmap_reserve = __hugetlb_opts.no_reserve ? MAP_NORESERVE : 0;
	int mmap_hugetlb = 0;
	int ret;

	/* Catch an altogether-too easy typo */
	if (flags & GHR_MASK)
		ERROR("Improper use of GHR_* in get_huge_pages()\n");

#ifdef MAP_HUGETLB
	mmap_hugetlb = MAP_HUGETLB;
#endif

	if (__hugetlb_opts.map_hugetlb &&
			gethugepagesize() == kernel_default_hugepage_size()) {
		/* Because we can use MAP_HUGETLB, we simply mmap the region */
		buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|MAP_ANONYMOUS|mmap_hugetlb|mmap_reserve,
			0, 0);
	} else {
		/* Create a file descriptor for the new region */
		buf_fd = hugetlbfs_unlinked_fd();
		if (buf_fd < 0) {
			WARNING("Couldn't open hugetlbfs file for %zd-sized buffer\n",
					len);
			return NULL;
		}

		/* Map the requested region */
		buf = mmap(NULL, len, PROT_READ|PROT_WRITE,
			MAP_PRIVATE|mmap_reserve, buf_fd, 0);
	}

	if (buf == MAP_FAILED) {
		if (buf_fd >= 0)
			close(buf_fd);

		WARNING("get_huge_pages: New region mapping failed (flags: 0x%lX): %s\n",
			flags, strerror(errno));
		return NULL;
	}

	/* Fault the region to ensure accesses succeed */
	ret = hugetlbfs_prefault(buf, len);
	if (ret != 0) {
		munmap(buf, len);
		if (buf_fd >= 0)
			close(buf_fd);

		WARNING("get_huge_pages: Prefaulting failed (flags: 0x%lX): %s\n",
			flags, strerror(ret));
		return NULL;
	}

	/* Close the file so we do not have to track the descriptor */
	if (buf_fd >= 0 && close(buf_fd) != 0) {
		WARNING("Failed to close new buffer fd: %s\n", strerror(errno));
		munmap(buf, len);
		return NULL;
	}

	/* woo, new buffer of shiny */
	return buf;
}
int main(int argc, char *argv[])
{
	int fd;
	int pipefd[2];
	long err;
	pid_t cpid;
	void *p;
	struct sigaction sa = {
		.sa_sigaction = sigchld_handler,
		.sa_flags = SA_SIGINFO,
	};
	struct sigaction old_sa;


	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	err = sigaction(SIGCHLD, &sa, &old_sa);
	if (err)
		FAIL("Can't install SIGCHLD handler: %s", strerror(errno));

	err = pipe(pipefd);
	if (err)
		FAIL("pipe(): %s", strerror(errno));

	cpid = fork();
	if (cpid < 0)
		FAIL("fork(): %s", strerror(errno));


	if (cpid == 0) {
		child(fd, pipefd[1]);
		exit(0);
	}

	/* Parent */
	err = read(pipefd[0], &p, sizeof(p));
	if (err == -1)
		FAIL("Reading pipe: %s\n", strerror(errno));
	if (err != sizeof(p))
		FAIL("Short read over pipe");

	verbose_printf("Parent received address %p\n", p);

	err = ptrace(PTRACE_ATTACH, cpid, NULL, NULL);
	if (err)
		FAIL("ptrace(ATTACH): %s", strerror(errno));

	while (! ready_to_trace)
		;

	do_poke(cpid, p);
	do_poke(cpid, p + getpagesize());

	err = sigaction(SIGCHLD, &old_sa, NULL);
	if (err)
		FAIL("Clearing SIGCHLD handler: %s", strerror(errno));

	ptrace(PTRACE_KILL, cpid, NULL, NULL);

	PASS();
}
예제 #13
0
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)
		FAIL("mmap() FIXED: %s", 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();
}
int main(int argc, char *argv[])
{
	int page_size;
	long hpage_size;
	long long buggy_offset, truncate_point;
	int fd;
	void *p, *q;
	volatile unsigned int *pi, *qi;
	int err;
	struct sigaction sa_fail = {
		.sa_sigaction = sigbus_handler_fail,
		.sa_flags = SA_SIGINFO,
	};
	struct sigaction sa_pass = {
		.sa_sigaction = sigbus_handler_pass,
		.sa_flags = SA_SIGINFO,
	};

	test_init(argc, argv);

	page_size = getpagesize();
	hpage_size = check_hugepagesize();

	check_free_huge_pages(3);

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	truncate_point = FOURGIG;
	buggy_offset = truncate_point / (hpage_size / page_size);
	buggy_offset = ALIGN(buggy_offset, hpage_size);

	verbose_printf("Mapping 3 hpages at offset 0x%llx...", truncate_point);
	/* First get arena of three hpages size, at file offset 4GB */
	q = mmap64(NULL, 3*hpage_size, PROT_READ|PROT_WRITE,
		 MAP_PRIVATE, fd, truncate_point);
	if (q == MAP_FAILED)
		FAIL("mmap() offset 4GB: %s", strerror(errno));
	verbose_printf("mapped at %p\n", q);
	qi = q;
	/* Touch the high page */
	*qi = 0;

	/* This part of the test makes the problem more obvious, but
	 * is not essential.  It can't be done on powerpc, where
	 * segment restrictions prohibit us from performing such a
	 * mapping, so skip it there. Similarly, ia64's address space
	 * restrictions prevent this. */
#if !defined(__powerpc__) && !defined(__powerpc64__) && !defined(__ia64__)
	/* Replace middle hpage by tinypage mapping to trigger
	 * nr_ptes BUG */
	verbose_printf("Replacing map at %p-%p...", q + hpage_size,
		       q + hpage_size + hpage_size-1);
	p = mmap64(q + hpage_size, hpage_size, PROT_READ|PROT_WRITE,
		   MAP_FIXED|MAP_PRIVATE|MAP_ANON, -1, 0);
	if (p != q + hpage_size)
		FAIL("mmap() before low hpage");
	verbose_printf("done\n");
	pi = p;
	/* Touch one page to allocate its page table */
	*pi = 0;
#endif

	/* Replace top hpage by hpage mapping at confusing file offset */
	verbose_printf("Replacing map at %p with map from offset 0x%llx...",
		       q + 2*hpage_size, buggy_offset);
	p = mmap64(q + 2*hpage_size, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_FIXED|MAP_PRIVATE, fd, buggy_offset);
	if (p != q + 2*hpage_size)
		FAIL("mmap() buggy offset 0x%llx", buggy_offset);
	verbose_printf("done\n");
	pi = p;
	/* Touch the low page with something non-zero */
	*pi = 1;

	verbose_printf("Truncating at 0x%llx...", truncate_point);
	err = ftruncate64(fd, truncate_point);
	if (err)
		FAIL("ftruncate(): %s", strerror(errno));
	verbose_printf("done\n");

	err = sigaction(SIGBUS, &sa_fail, NULL);
	if (err)
		FAIL("sigaction() fail: %s", strerror(errno));

	if (*pi != 1)
		FAIL("Data 1 has changed to %u", *pi);

	err = sigaction(SIGBUS, &sa_pass, NULL);
	if (err)
		FAIL("sigaction() pass: %s", strerror(errno));

	*qi;

	/* Should have SIGBUSed above */
	FAIL("Didn't SIGBUS on truncated page.");
}
예제 #15
0
int main(int argc, char *argv[])
{
	int page_size;
	long hpage_size;
	off_t buggy_offset;
	int fd;
	void *p, *q;
	volatile int *pi;
	int err;

	test_init(argc, argv);

	page_size = getpagesize();
	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	/* First, we make a 2 page sane hugepage mapping.  Then we
	 * memset() it to ensure that the ptes are instantiated for
	 * it.  Then we attempt to replace the second half of the map
	 * with one at a bogus offset.  We leave the first page of
	 * sane mapping in place to ensure that the corresponding
	 * pud/pmd/whatever entries aren't cleaned away.  It's those
	 * bad entries which can trigger bad_pud() checks if the
	 * backout path for the bogus mapping is buggy, which it was
	 * in some kernels. */

	verbose_printf("Free hugepages: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_FREE));

	verbose_printf("Mapping reference map...");
	/* First get arena of three hpages size, at file offset 4GB */
	p = mmap(NULL, 2*hpage_size, PROT_READ|PROT_WRITE, MAP_PRIVATE, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() offset 4GB: %s", strerror(errno));
	verbose_printf("%p-%p\n", p, p+2*hpage_size-1);

	verbose_printf("Free hugepages: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_FREE));

	/* Instantiate the pages */
	verbose_printf("Instantiating...");
	memset(p, 0, 2*hpage_size);
	pi = p;
	*pi = RANDOM_CONSTANT;
	verbose_printf("done.\n");

	verbose_printf("Free hugepages: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_FREE));

	/* Toggle the permissions on the first page.  This forces TLB
	 * entries (including hash page table on powerpc) to be
	 * flushed, so that the page tables must be accessed for the
	 * test further down.  In the buggy case, those page tables
	 * can get thrown away by a pud_clear() */
	err = mprotect(p, hpage_size, PROT_READ);
	if (err)
		FAIL("mprotect(%p, 0x%lx, PROT_READ): %s", p, hpage_size,
							strerror(errno));

	/* Replace top hpage by hpage mapping at confusing file offset */
	buggy_offset = page_size;
	verbose_printf("Replacing map at %p with map from offset 0x%lx...",
		       p + hpage_size, (unsigned long)buggy_offset);
	q = mmap(p + hpage_size, hpage_size, PROT_READ|PROT_WRITE,
		 MAP_FIXED|MAP_PRIVATE, fd, buggy_offset);
	if (q != MAP_FAILED)
		FAIL("bogus offset mmap() succeeded at %p: %s", q, strerror(errno));
	if (errno != EINVAL)
		FAIL("bogus mmap() failed with \"%s\" instead of \"%s\"",
		     strerror(errno), strerror(EINVAL));
	verbose_printf("%s\n", strerror(errno));

	verbose_printf("Free hugepages: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_FREE));

	if (*pi != RANDOM_CONSTANT)
		FAIL("Pre-existing mapping clobbered: %x instead of %x",
		     *pi, RANDOM_CONSTANT);

	verbose_printf("Free hugepages: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_FREE));

	/* The real test is whether we got a bad_pud() or similar
	 * during the run.  The check above, combined with the earlier
	 * mprotect()s to flush the TLB are supposed to catch it, but
	 * it's hard to be certain.  Once bad_pud() is called
	 * behaviour can be very strange. */
	PASS_INCONCLUSIVE();
}
예제 #16
0
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();
}
int main(int argc, char *argv[])
{
	int fd, rc;
	void *p, *q, *r;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();
	page_size = getpagesize();


	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");
	init_slice_boundary(fd);

	/* First, hugepages above, normal below */
	p = mmap((void *)(slice_boundary + hpage_size), hpage_size,
		 PROT_READ | PROT_WRITE,
		 MAP_SHARED | MAP_FIXED, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(huge above): %s", strerror(errno));

	do_readback(p, hpage_size, "huge above");

	q = mmap((void *)(slice_boundary - page_size), page_size,
		 PROT_READ | PROT_WRITE,
		 MAP_PRIVATE | MAP_ANONYMOUS | MAP_FIXED, -1, 0);
	if (q == MAP_FAILED)
		FAIL("mmap(normal below): %s", strerror(errno));

	do_readback(q, page_size, "normal below");

	verbose_printf("Attempting to remap...");

	r = mremap(q, page_size, 2*page_size, 0);
	if (r == MAP_FAILED) {
		verbose_printf("disallowed\n");
		rc = munmap(q, page_size);
		if (rc != 0)
			FAIL("munmap(normal below): %s", strerror(errno));
	} else {
		if (r != q)
			FAIL("mremap() moved without MREMAP_MAYMOVE!?");

		verbose_printf("testing...");
		do_readback(q, 2*page_size, "normal below expanded");
		rc = munmap(q, 2*page_size);
		if (rc != 0)
			FAIL("munmap(normal below expanded): %s", strerror(errno));
	}

	rc = munmap(p, hpage_size);
	if (rc != 0)
		FAIL("munmap(huge above)");

	/* Next, normal pages above, huge below */
	p = mmap((void *)(slice_boundary + hpage_size), page_size,
		 PROT_READ|PROT_WRITE,
		 MAP_SHARED | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(normal above): %s", strerror(errno));

	do_readback(p, page_size, "normal above");

	q = mmap((void *)(slice_boundary - hpage_size),
		 hpage_size, PROT_READ | PROT_WRITE,
		 MAP_SHARED | MAP_FIXED, fd, 0);
	if (q == MAP_FAILED)
		FAIL("mmap(huge below): %s", strerror(errno));

	do_readback(q, hpage_size, "huge below");

	verbose_printf("Attempting to remap...");

	r = mremap(q, hpage_size, 2*hpage_size, 0);
	if (r == MAP_FAILED) {
		verbose_printf("disallowed\n");
		rc = munmap(q, hpage_size);
		if (rc != 0)
			FAIL("munmap(huge below): %s", strerror(errno));
	} else {
		if (r != q)
			FAIL("mremap() moved without MREMAP_MAYMOVE!?");

		verbose_printf("testing...");
		do_readback(q, 2*hpage_size, "huge below expanded");
		rc = munmap(q, 2*hpage_size);
		if (rc != 0)
			FAIL("munmap(huge below expanded): %s", strerror(errno));
	}

	rc = munmap(p, page_size);
	if (rc != 0)
		FAIL("munmap(normal above)");


	PASS();
}
예제 #18
0
int main(int argc, char *argv[])
{
	long hpage_size;
	unsigned long totpages, chunk1, chunk2;
	int fd;
	void *p, *q;
	pid_t child, ret;
	int status;

	test_init(argc, argv);

	totpages = read_meminfo("HugePages_Free:");

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	chunk1 = (totpages / 2) + 1;
	chunk2 = totpages - chunk1 + 1;

	verbose_printf("overcommit: %ld hugepages available: "
		       "chunk1=%ld chunk2=%ld\n", totpages, chunk1, chunk2);

	p = mmap(NULL, chunk1*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
		 fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() chunk1: %s", strerror(errno));

	q = mmap(NULL, chunk2*hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
		 fd, chunk1*hpage_size);
	if (q == MAP_FAILED) {
		if (errno != ENOMEM)
			FAIL("mmap() chunk2: %s", strerror(errno));
		else
			PASS();
	}

	verbose_printf("Looks like we've overcommitted, testing...\n");

	/* Looks like we're overcommited, but we need to confirm that
	 * this is bad.  We touch it all in a child process because an
	 * overcommit will generally lead to a SIGKILL which we can't
	 * handle, of course. */
	child = fork();
	if (child < 0)
		FAIL("fork(): %s", strerror(errno));

	if (child == 0) {
		memset(p, 0, chunk1*hpage_size);
		memset(q, 0, chunk2*hpage_size);
		exit(0);
	}

	ret = waitpid(child, &status, 0);
	if (ret < 0)
		FAIL("waitpid(): %s", strerror(errno));

	if (WIFSIGNALED(status))
		FAIL("Killed by signal \"%s\" due to overcommit",
		     strsignal(WTERMSIG(status)));

	PASS();
}
int main(int argc, char *argv[])
{
	long hpage_size;
	int fd;
	void *p;
	volatile unsigned int *q;
	int err;
	int sigbus_count = 0;
	unsigned long initial_rsvd, rsvd;
	struct sigaction sa = {
		.sa_sigaction = sigbus_handler,
		.sa_flags = SA_SIGINFO,
	};

	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	initial_rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	verbose_printf("Reserve count before map: %lu\n", initial_rsvd);

	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, MAP_SHARED,
		 fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(): %s", strerror(errno));
	q = p;

	verbose_printf("Reserve count after map: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_RSVD));

	*q = 0;
	verbose_printf("Reserve count after touch: %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_RSVD));

	err = ftruncate(fd, 0);
	if (err)
		FAIL("ftruncate(): %s", strerror(errno));

	rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	verbose_printf("Reserve count after truncate: %lu\n", rsvd);
	if (rsvd != initial_rsvd)
		FAIL("Reserved count is not restored after truncate: %lu instead of %lu",
		     rsvd, initial_rsvd);

	err = sigaction(SIGBUS, &sa, NULL);
	if (err)
		FAIL("sigaction(): %s", strerror(errno));

	if (sigsetjmp(sig_escape, 1) == 0)
		*q; /* Fault, triggering a SIGBUS */
	else
		sigbus_count++;

	if (sigbus_count != 1)
		FAIL("Didn't SIGBUS after truncate");

	rsvd = get_huge_page_counter(hpage_size, HUGEPAGES_RSVD);
	verbose_printf("Reserve count after SIGBUS fault: %lu\n", rsvd);
	if (rsvd != initial_rsvd)
		FAIL("Reserved count is altered by SIGBUS fault: %lu instead of %lu",
		     rsvd, initial_rsvd);

	munmap(p, hpage_size);

	verbose_printf("Reserve count after munmap(): %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_RSVD));

	close(fd);

	verbose_printf("Reserve count after close(): %lu\n",
		get_huge_page_counter(hpage_size, HUGEPAGES_RSVD));

	PASS();
}
예제 #20
0
static void run_race(void *syncarea, int race_type)
{
	volatile int *trigger1, *trigger2;
	int fd;
	void *p;
	int status1, status2;
	int ret;

	memset(syncarea, 0, sizeof(*trigger1) + sizeof(*trigger2));
	trigger1 = syncarea;
	trigger2 = trigger1 + 1;

	/* Get a new file for the final page */
	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	verbose_printf("Mapping final page.. ");
	p = mmap(NULL, hpage_size, PROT_READ|PROT_WRITE, race_type, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap(): %s", strerror(errno));
	verbose_printf("%p\n", p);

	if (race_type == MAP_SHARED) {
		child1 = fork();
		if (child1 < 0)
			FAIL("fork(): %s", strerror(errno));
		if (child1 == 0)
			proc_racer(p, 0, trigger1, trigger2);

		child2 = fork();
		if (child2 < 0)
			FAIL("fork(): %s", strerror(errno));
		if (child2 == 0)
			proc_racer(p, 1, trigger2, trigger1);

		/* wait() calls */
		ret = waitpid(child1, &status1, 0);
		if (ret < 0)
			FAIL("waitpid() child 1: %s", strerror(errno));
		verbose_printf("Child 1 status: %x\n", status1);


		ret = waitpid(child2, &status2, 0);
		if (ret < 0)
			FAIL("waitpid() child 2: %s", strerror(errno));
		verbose_printf("Child 2 status: %x\n", status2);

		if (WIFSIGNALED(status1))
			FAIL("Child 1 killed by signal %s",
			     strsignal(WTERMSIG(status1)));
		if (WIFSIGNALED(status2))
		FAIL("Child 2 killed by signal %s",
		     strsignal(WTERMSIG(status2)));

		status1 = WEXITSTATUS(status1);
		status2 = WEXITSTATUS(status2);
	} else {
		struct racer_info ri1 = {
			.p = p,
			.cpu = 0,
			.mytrigger = trigger1,
			.othertrigger = trigger2,
		};
		struct racer_info ri2 = {
			.p = p,
			.cpu = 1,
			.mytrigger = trigger2,
			.othertrigger = trigger1,
		};
		void *tret1, *tret2;

		ret = pthread_create(&thread1, NULL, thread_racer, &ri1);
		if (ret != 0)
			FAIL("pthread_create() 1: %s\n", strerror(errno));

		ret = pthread_create(&thread2, NULL, thread_racer, &ri2);
		if (ret != 0)
			FAIL("pthread_create() 2: %s\n", strerror(errno));

		ret = pthread_join(thread1, &tret1);
		if (ret != 0)
			FAIL("pthread_join() 1: %s\n", strerror(errno));
		if (tret1 != &ri1)
			FAIL("Thread 1 returned %p not %p, killed?\n",
			     tret1, &ri1);
		ret = pthread_join(thread2, &tret2);
		if (ret != 0)
			FAIL("pthread_join() 2: %s\n", strerror(errno));
		if (tret2 != &ri2)
			FAIL("Thread 2 returned %p not %p, killed?\n",
			     tret2, &ri2);

		status1 = ri1.status;
		status2 = ri2.status;
	}

	if (status1 != 0)
		FAIL("Racer 1 terminated with code %d", status1);

	if (status2 != 0)
		FAIL("Racer 2 terminated with code %d", status2);
}

int main(int argc, char *argv[])
{
	unsigned long totpages;
	int fd;
	void *p, *q;
	unsigned long i;
	int race_type;

	test_init(argc, argv);

	if (argc != 2)
		CONFIG("Usage: alloc-instantiate-race <private|shared>");

	totpages = read_meminfo("HugePages_Free:");

	if (strcmp(argv[1], "shared") == 0) {
		race_type = MAP_SHARED;
	} else if (strcmp(argv[1], "private") == 0) {
		race_type = MAP_PRIVATE;
	} else {
		CONFIG("Usage: alloc-instantiate-race <private|shared>");
	}

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	/* Get a shared normal page for synchronization */
	verbose_printf("Mapping synchronization area..");
	q = mmap(NULL, getpagesize(), PROT_READ|PROT_WRITE,
		 MAP_SHARED|MAP_ANONYMOUS, -1, 0);
	if (q == MAP_FAILED)
		FAIL("mmap() sync area: %s", strerror(errno));
	verbose_printf("done\n");

	verbose_printf("Mapping %ld/%ld pages.. ", totpages-1, totpages);
	p = mmap(NULL, (totpages-1)*hpage_size, PROT_READ|PROT_WRITE,
		 MAP_SHARED, fd, 0);
	if (p == MAP_FAILED)
		FAIL("mmap() 1: %s", strerror(errno));

	/* Allocate all save one of the pages up front */
	verbose_printf("instantiating.. ");
	for (i = 0; i < (totpages - 1); i++)
		memset(p + (i * hpage_size), 0, sizeof(int));
	verbose_printf("done\n");

	run_race(q, race_type);

	PASS();
}
예제 #21
0
int main(int argc, char *argv[])
{
	long hpage_size;
	int fd;
	int err;
	unsigned long free_before, free_after;

	test_init(argc, argv);

	hpage_size = check_hugepagesize();

	fd = hugetlbfs_unlinked_fd();
	if (fd < 0)
		FAIL("hugetlbfs_unlinked_fd()");

	free_before = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);

	/*
	 * First preallocate file with with just 1 byte.  Allocation sizes
	 * are rounded up, so we should get an entire huge page.
	 */
	err = fallocate(fd, 0, 0, 1);
	if (err) {
		if (errno == EOPNOTSUPP)
			IRRELEVANT();
		if (err)
			FAIL("fallocate(): %s", strerror(errno));
	}

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 1)
		FAIL("fallocate 1 byte did not preallocate entire huge page\n");

	/*
	 * Now punch a hole with just 1 byte.  On hole punch, sizes are
	 * rounded down.  So, this operation should not create a hole.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, 1);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after == free_before)
		FAIL("fallocate hole punch 1 byte free'ed a huge page\n");

	/*
	 * Now punch a hole with of 2 * hpage_size - 1 byte.  This size
	 * should be rounded down to a single huge page and the hole created.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, (2 * hpage_size) - 1);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after != free_before)
		FAIL("fallocate hole punch 2 * hpage_size - 1 byte did not free huge page\n");

	/*
	 * Perform a preallocate operation with offset 1 and size of
	 * hpage_size.  The offset should be rounded down and the
	 * size rounded up to preallocate two huge pages.
	 */
	err = fallocate(fd, 0, 1, hpage_size);
	if (err)
		FAIL("fallocate(): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 2)
		FAIL("fallocate 1 byte offset, huge page size did not preallocate two huge pages\n");

	/*
	 * The hole punch code will only delete 'whole' huge pags that are
	 * in the specified range.  The offset is rounded up, and (offset
	 * + size) is rounded down to determine the huge pages to be deleted.
	 * In this case, after rounding the range is (hpage_size, hpage_size).
	 * So, no pages should be deleted.
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			1, hpage_size);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_before - free_after != 2)
		FAIL("fallocate hole punch 1 byte offset, huge page size incorrectly deleted a huge page\n");

	/*
	 * To delete both huge pages, the range passed to hole punch must
	 * overlap the allocated pages
	 */
	err = fallocate(fd, FALLOC_FL_PUNCH_HOLE | FALLOC_FL_KEEP_SIZE,
			0, 2 * hpage_size);
	if (err)
		FAIL("fallocate(FALLOC_FL_PUNCH_HOLE): %s", strerror(errno));

	free_after = get_huge_page_counter(hpage_size, HUGEPAGES_FREE);
	if (free_after != free_before)
		FAIL("fallocate hole punch did not delete two huge pages\n");

	PASS();
}