summaryrefslogtreecommitdiffstats
path: root/man2/userfaultfd.2
diff options
context:
space:
mode:
Diffstat (limited to 'man2/userfaultfd.2')
-rw-r--r--man2/userfaultfd.296
1 files changed, 48 insertions, 48 deletions
diff --git a/man2/userfaultfd.2 b/man2/userfaultfd.2
index 4fe404edd..40354065c 100644
--- a/man2/userfaultfd.2
+++ b/man2/userfaultfd.2
@@ -407,25 +407,25 @@ struct uffd_msg {
__u32 ptid; /* Thread ID of the fault */
} feat;
} pagefault;
-
+\&
struct { /* Since Linux 4.11 */
__u32 ufd; /* Userfault file descriptor
of the child process */
} fork;
-
+\&
struct { /* Since Linux 4.11 */
__u64 from; /* Old address of remapped area */
__u64 to; /* New address of remapped area */
__u64 len; /* Original mapping length */
} remap;
-
+\&
struct { /* Since Linux 4.11 */
__u64 start; /* Start address of removed area */
__u64 end; /* End address of removed area */
} remove;
...
} arg;
-
+\&
/* Padding fields omitted */
} __packed;
.EE
@@ -706,7 +706,7 @@ The following is an example of what we see when running the program:
.EX
$ \fB./userfaultfd_demo 3\fP
Address returned by mmap() = 0x7fd30106c000
-
+\&
fault_handler_thread():
poll() returns: nready = 1; POLLIN = 1; POLLERR = 0
UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106c00f
@@ -715,7 +715,7 @@ Read address 0x7fd30106c00f in main(): A
Read address 0x7fd30106c40f in main(): A
Read address 0x7fd30106c80f in main(): A
Read address 0x7fd30106cc0f in main(): A
-
+\&
fault_handler_thread():
poll() returns: nready = 1; POLLIN = 1; POLLERR = 0
UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106d00f
@@ -724,7 +724,7 @@ Read address 0x7fd30106d00f in main(): B
Read address 0x7fd30106d40f in main(): B
Read address 0x7fd30106d80f in main(): B
Read address 0x7fd30106dc0f in main(): B
-
+\&
fault_handler_thread():
poll() returns: nready = 1; POLLIN = 1; POLLERR = 0
UFFD_EVENT_PAGEFAULT event: flags = 0; address = 7fd30106e00f
@@ -740,7 +740,7 @@ Read address 0x7fd30106ec0f in main(): C
.\" SRC BEGIN (userfaultfd.c)
.EX
/* userfaultfd_demo.c
-
+\&
Licensed under the GNU General Public License version 2 or later.
*/
#define _GNU_SOURCE
@@ -758,9 +758,9 @@ Read address 0x7fd30106ec0f in main(): C
#include <sys/mman.h>
#include <sys/syscall.h>
#include <unistd.h>
-
+\&
static int page_size;
-
+\&
static void *
fault_handler_thread(void *arg)
{
@@ -769,77 +769,77 @@ fault_handler_thread(void *arg)
ssize_t nread;
struct pollfd pollfd;
struct uffdio_copy uffdio_copy;
-
+\&
static int fault_cnt = 0; /* Number of faults so far handled */
static char *page = NULL;
static struct uffd_msg msg; /* Data read from userfaultfd */
-
+\&
uffd = (long) arg;
-
+\&
/* Create a page that will be copied into the faulting region. */
-
+\&
if (page == NULL) {
page = mmap(NULL, page_size, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, \-1, 0);
if (page == MAP_FAILED)
err(EXIT_FAILURE, "mmap");
}
-
+\&
/* Loop, handling incoming events on the userfaultfd
file descriptor. */
-
+\&
for (;;) {
-
+\&
/* See what poll() tells us about the userfaultfd. */
-
+\&
pollfd.fd = uffd;
pollfd.events = POLLIN;
nready = poll(&pollfd, 1, \-1);
if (nready == \-1)
err(EXIT_FAILURE, "poll");
-
+\&
printf("\enfault_handler_thread():\en");
printf(" poll() returns: nready = %d; "
"POLLIN = %d; POLLERR = %d\en", nready,
(pollfd.revents & POLLIN) != 0,
(pollfd.revents & POLLERR) != 0);
-
+\&
/* Read an event from the userfaultfd. */
-
+\&
nread = read(uffd, &msg, sizeof(msg));
if (nread == 0) {
printf("EOF on userfaultfd!\en");
exit(EXIT_FAILURE);
}
-
+\&
if (nread == \-1)
err(EXIT_FAILURE, "read");
-
+\&
/* We expect only one kind of event; verify that assumption. */
-
+\&
if (msg.event != UFFD_EVENT_PAGEFAULT) {
fprintf(stderr, "Unexpected event on userfaultfd\en");
exit(EXIT_FAILURE);
}
-
+\&
/* Display info about the page\-fault event. */
-
+\&
printf(" UFFD_EVENT_PAGEFAULT event: ");
printf("flags = %"PRIx64"; ", msg.arg.pagefault.flags);
printf("address = %"PRIx64"\en", msg.arg.pagefault.address);
-
+\&
/* Copy the page pointed to by \[aq]page\[aq] into the faulting
region. Vary the contents that are copied in, so that it
is more obvious that each fault is handled separately. */
-
+\&
memset(page, \[aq]A\[aq] + fault_cnt % 20, page_size);
fault_cnt++;
-
+\&
uffdio_copy.src = (unsigned long) page;
-
+\&
/* We need to handle page faults in units of pages(!).
So, round faulting address down to page boundary. */
-
+\&
uffdio_copy.dst = (unsigned long) msg.arg.pagefault.address &
\[ti](page_size \- 1);
uffdio_copy.len = page_size;
@@ -847,12 +847,12 @@ fault_handler_thread(void *arg)
uffdio_copy.copy = 0;
if (ioctl(uffd, UFFDIO_COPY, &uffdio_copy) == \-1)
err(EXIT_FAILURE, "ioctl\-UFFDIO_COPY");
-
+\&
printf(" (uffdio_copy.copy returned %"PRId64")\en",
uffdio_copy.copy);
}
}
-
+\&
int
main(int argc, char *argv[])
{
@@ -864,59 +864,59 @@ main(int argc, char *argv[])
pthread_t thr; /* ID of thread that handles page faults */
struct uffdio_api uffdio_api;
struct uffdio_register uffdio_register;
-
+\&
if (argc != 2) {
fprintf(stderr, "Usage: %s num\-pages\en", argv[0]);
exit(EXIT_FAILURE);
}
-
+\&
page_size = sysconf(_SC_PAGE_SIZE);
len = strtoull(argv[1], NULL, 0) * page_size;
-
+\&
/* Create and enable userfaultfd object. */
-
+\&
uffd = syscall(SYS_userfaultfd, O_CLOEXEC | O_NONBLOCK);
if (uffd == \-1)
err(EXIT_FAILURE, "userfaultfd");
-
+\&
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
if (ioctl(uffd, UFFDIO_API, &uffdio_api) == \-1)
err(EXIT_FAILURE, "ioctl\-UFFDIO_API");
-
+\&
/* 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)
err(EXIT_FAILURE, "mmap");
-
+\&
printf("Address returned by mmap() = %p\en", 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). */
-
+\&
uffdio_register.range.start = (unsigned long) addr;
uffdio_register.range.len = len;
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
if (ioctl(uffd, UFFDIO_REGISTER, &uffdio_register) == \-1)
err(EXIT_FAILURE, "ioctl\-UFFDIO_REGISTER");
-
+\&
/* Create a thread that will process the userfaultfd events. */
-
+\&
s = pthread_create(&thr, NULL, fault_handler_thread, (void *) uffd);
if (s != 0) {
errc(EXIT_FAILURE, s, "pthread_create");
}
-
+\&
/* Main thread now touches memory in the mapping, touching
locations 1024 bytes apart. This will trigger userfaultfd
events for all pages in the region. */
-
+\&
l = 0xf; /* Ensure that faulting address is not on a page
boundary, in order to test that we correctly
handle that case in fault_handling_thread(). */
@@ -927,7 +927,7 @@ main(int argc, char *argv[])
l += 1024;
usleep(100000); /* Slow things down a little */
}
-
+\&
exit(EXIT_SUCCESS);
}
.EE