Skip to content

Commit 8a17c3e

Browse files
ricardobranco777pevik
authored andcommitted
userfaultfd: Add test using UFFDIO_ZEROPAGE
Signed-off-by: Ricardo Branco <rbranco@suse.de> Reviewed-by: Petr Vorel <pvorel@suse.cz> Reviewed-by: Cyril Hrubis <chrubis@suse.cz> Link: #1280
1 parent 16530be commit 8a17c3e

4 files changed

Lines changed: 104 additions & 0 deletions

File tree

runtest/syscalls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1772,6 +1772,7 @@ umount2_02 umount2_02
17721772
userfaultfd01 userfaultfd01
17731773
userfaultfd02 userfaultfd02
17741774
userfaultfd03 userfaultfd03
1775+
userfaultfd04 userfaultfd04
17751776

17761777
ustat01 ustat01
17771778
ustat02 ustat02
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
11
/userfaultfd01
22
/userfaultfd02
33
/userfaultfd03
4+
/userfaultfd04

testcases/kernel/syscalls/userfaultfd/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,3 +14,4 @@ include $(top_srcdir)/include/mk/generic_leaf_target.mk
1414
userfaultfd01: CFLAGS += -pthread
1515
userfaultfd02: CFLAGS += -pthread
1616
userfaultfd03: CFLAGS += -pthread
17+
userfaultfd04: CFLAGS += -pthread
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2025 SUSE LLC
4+
* Author: Christian Amann <camann@suse.com>
5+
* Author: Ricardo Branco <rbranco@suse.com>
6+
*/
7+
8+
/*\
9+
* Force a pagefault event and handle it using :manpage:`userfaultfd(2)`
10+
* from a different thread using UFFDIO_ZEROPAGE.
11+
*/
12+
13+
#include "config.h"
14+
#include <poll.h>
15+
#include "tst_test.h"
16+
#include "tst_safe_macros.h"
17+
#include "tst_safe_pthread.h"
18+
#include "lapi/userfaultfd.h"
19+
20+
static int page_size;
21+
static char *page;
22+
static int uffd;
23+
24+
static void set_pages(void)
25+
{
26+
page_size = sysconf(_SC_PAGE_SIZE);
27+
page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
28+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
29+
}
30+
31+
static void reset_pages(void)
32+
{
33+
SAFE_MUNMAP(page, page_size);
34+
}
35+
36+
static void *handle_thread(void)
37+
{
38+
static struct uffd_msg msg;
39+
struct uffdio_zeropage uffdio_zeropage = {};
40+
41+
struct pollfd pollfd;
42+
int nready;
43+
44+
pollfd.fd = uffd;
45+
pollfd.events = POLLIN;
46+
nready = poll(&pollfd, 1, -1);
47+
if (nready == -1)
48+
tst_brk(TBROK | TERRNO, "Error on poll");
49+
50+
SAFE_READ(1, uffd, &msg, sizeof(msg));
51+
52+
if (msg.event != UFFD_EVENT_PAGEFAULT)
53+
tst_brk(TBROK | TERRNO, "Received unexpected UFFD_EVENT %d", msg.event);
54+
55+
uffdio_zeropage.range.start = msg.arg.pagefault.address
56+
& ~(page_size - 1);
57+
uffdio_zeropage.range.len = page_size;
58+
59+
SAFE_IOCTL(uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
60+
61+
close(uffd);
62+
return NULL;
63+
}
64+
65+
static void run(void)
66+
{
67+
pthread_t thr;
68+
struct uffdio_api uffdio_api = {};
69+
struct uffdio_register uffdio_register;
70+
71+
set_pages();
72+
73+
uffd = SAFE_USERFAULTFD(O_CLOEXEC | O_NONBLOCK, false);
74+
75+
uffdio_api.api = UFFD_API;
76+
SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
77+
78+
uffdio_register.range.start = (unsigned long) page;
79+
uffdio_register.range.len = page_size;
80+
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
81+
82+
SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
83+
84+
SAFE_PTHREAD_CREATE(&thr, NULL, (void *) handle_thread, NULL);
85+
86+
for (int i = 0; i < page_size; i++) {
87+
if (page[i] != 0) {
88+
tst_res(TFAIL, "page[%d]=0x%x not zero", i, page[i]);
89+
return;
90+
}
91+
}
92+
93+
tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE");
94+
95+
SAFE_PTHREAD_JOIN(thr, NULL);
96+
reset_pages();
97+
}
98+
99+
static struct tst_test test = {
100+
.test_all = run,
101+
};

0 commit comments

Comments
 (0)