tools/testing/selftests/mm/hugepage-mremap.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/hugepage-mremap.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/hugepage-mremap.c
Extension
.c
Size
5211 bytes
Lines
179
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (*(addr + i) != (char)i) {
			ksft_print_msg("Mismatch at %lu\n", i);
			return 1;
		}
	return 0;
}

static void register_region_with_uffd(char *addr, size_t len)
{
	long uffd; /* userfaultfd file descriptor */
	struct uffdio_api uffdio_api;

	/* Create and enable userfaultfd object. */
	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
	if (uffd == -1) {
		switch (errno) {
		case EPERM:
			ksft_exit_skip("Insufficient permissions, try running as root.\n");
			break;
		case ENOSYS:
			ksft_exit_skip("userfaultfd is not supported/not enabled.\n");
			break;
		default:
			ksft_exit_fail_msg("userfaultfd failed with %s\n", strerror(errno));
			break;
		}
	}

	uffdio_api.api = UFFD_API;
	uffdio_api.features = 0;
	if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1)
		ksft_exit_fail_msg("ioctl-UFFDIO_API: %s\n", strerror(errno));

	/* Create a private anonymous mapping. The memory will be
	 * demand-zero paged--that is, not yet allocated. When we
	 * actually touch the memory, it will be allocated via
	 * the userfaultfd.
	 */

	addr = mmap(NULL, len, PROT_READ | PROT_WRITE,
		    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (addr == MAP_FAILED)
		ksft_exit_fail_msg("mmap: %s\n", strerror(errno));

	ksft_print_msg("Address returned by mmap() = %p\n", addr);

	/* Register the memory range of the mapping we just created for
	 * handling by the userfaultfd object. In mode, we request to track
	 * missing pages (i.e., pages that have not yet been faulted in).
	 */
	if (uffd_register(uffd, addr, len, true, false, false))
		ksft_exit_fail_msg("ioctl-UFFDIO_REGISTER: %s\n", strerror(errno));
}

int main(int argc, char *argv[])
{
	size_t length = 0;
	int ret = 0, fd;

	ksft_print_header();
	ksft_set_plan(1);

	if (argc >= 2 && !strcmp(argv[1], "-h"))
		ksft_exit_fail_msg("Usage: %s [length_in_MB]\n", argv[0]);

	/* Read memory length as the first arg if valid, otherwise fallback to
	 * the default length.
	 */
	if (argc >= 2)
		length = (size_t)atoi(argv[1]);
	else
		length = DEFAULT_LENGTH_MB;

	length = MB_TO_BYTES(length);
	fd = memfd_create(argv[0], MFD_HUGETLB);
	if (fd < 0)
		ksft_exit_fail_msg("Open failed: %s\n", strerror(errno));

	/* mmap to a PUD aligned address to hopefully trigger pmd sharing. */
	unsigned long suggested_addr = 0x7eaa40000000;
	void *haddr = mmap((void *)suggested_addr, length, PROTECTION,
			   MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);
	ksft_print_msg("Map haddr: Returned address is %p\n", haddr);
	if (haddr == MAP_FAILED)
		ksft_exit_fail_msg("mmap1: %s\n", strerror(errno));

	/* mmap again to a dummy address to hopefully trigger pmd sharing. */
	suggested_addr = 0x7daa40000000;
	void *daddr = mmap((void *)suggested_addr, length, PROTECTION,
			   MAP_HUGETLB | MAP_SHARED | MAP_POPULATE, fd, 0);

Annotation

Implementation Notes