tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/powerpc/tm/tm-signal-pagefault.c
Extension
.c
Size
7675 bytes
Lines
286
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 (poll(&pollfd, 1, -1) == -1) {
			perror("poll() failed");
			exit(EXIT_FAILURE);
		}

		nread = read(uffd, &msg, sizeof(msg));
		if (nread == 0) {
			fprintf(stderr, "read(): EOF on userfaultfd\n");
			exit(EXIT_FAILURE);
		}

		if (nread == -1) {
			perror("read() failed");
			exit(EXIT_FAILURE);
		}

		/* We expect only one kind of event */
		if (msg.event != UFFD_EVENT_PAGEFAULT) {
			fprintf(stderr, "Unexpected event on userfaultfd\n");
			exit(EXIT_FAILURE);
		}

		/*
		 * We need to handle page faults in units of pages(!).
		 * So, round faulting address down to page boundary.
		 */
		uffdio_copy.dst = msg.arg.pagefault.address & ~(pagesize-1);

		offset = (char *) uffdio_copy.dst - uf_mem;
		uffdio_copy.src = (unsigned long) &backing_mem[offset];

		uffdio_copy.len = pagesize;
		uffdio_copy.mode = 0;
		uffdio_copy.copy = 0;
		if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == -1) {
			perror("ioctl-UFFDIO_COPY failed");
			exit(EXIT_FAILURE);
		}
	}
}

void setup_uf_mem(void)
{
	long uffd;		/* userfaultfd file descriptor */
	pthread_t thr;
	struct uffdio_api uffdio_api;
	struct uffdio_register uffdio_register;
	int ret;

	pagesize = sysconf(_SC_PAGE_SIZE);

	/* Create and enable userfaultfd object */
	uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
	if (uffd == -1) {
		perror("userfaultfd() failed");
		exit(EXIT_FAILURE);
	}
	uffdio_api.api = UFFD_API;
	uffdio_api.features = 0;
	if (ioctl(uffd, UFFDIO_API, &uffdio_api) == -1) {
		perror("ioctl-UFFDIO_API failed");
		exit(EXIT_FAILURE);
	}

	/*
	 * Create a private anonymous mapping. The memory will be demand-zero
	 * paged, that is, not yet allocated. When we actually touch the memory
	 * the related page will be allocated via the userfaultfd mechanism.
	 */
	uf_mem = mmap(NULL, UF_MEM_SIZE, PROT_READ | PROT_WRITE,
		      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (uf_mem == MAP_FAILED) {
		perror("mmap() failed");
		exit(EXIT_FAILURE);
	}

	/*
	 * Register the memory range of the mapping we've just mapped to be
	 * handled by the userfaultfd object. In 'mode' we request to track
	 * missing pages (i.e. pages that have not yet been faulted-in).
	 */
	uffdio_register.range.start = (unsigned long) uf_mem;
	uffdio_register.range.len = UF_MEM_SIZE;
	uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
	if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == -1) {
		perror("ioctl-UFFDIO_REGISTER");
		exit(EXIT_FAILURE);
	}

	/* Create a thread that will process the userfaultfd events */

Annotation

Implementation Notes