Skip to content

Commit 132c38a

Browse files
userfaultfd: Add test using UFFDIO_ZEROPAGE
Signed-off-by: Ricardo Branco <[email protected]>
1 parent 7336cf2 commit 132c38a

File tree

4 files changed

+123
-0
lines changed

4 files changed

+123
-0
lines changed

runtest/syscalls

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1773,6 +1773,7 @@ userfaultfd01 userfaultfd01
17731773
userfaultfd02 userfaultfd02
17741774
userfaultfd03 userfaultfd03
17751775
userfaultfd04 userfaultfd04
1776+
userfaultfd05 userfaultfd05
17761777

17771778
ustat01 ustat01
17781779
ustat02 ustat02

testcases/kernel/syscalls/userfaultfd/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,4 @@
22
/userfaultfd02
33
/userfaultfd03
44
/userfaultfd04
5+
/userfaultfd05

testcases/kernel/syscalls/userfaultfd/Makefile

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,4 @@ userfaultfd01: CFLAGS += -pthread
1515
userfaultfd02: CFLAGS += -pthread
1616
userfaultfd03: CFLAGS += -pthread
1717
userfaultfd04: CFLAGS += -pthread
18+
userfaultfd05: CFLAGS += -pthread
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// SPDX-License-Identifier: GPL-2.0-or-later
2+
/*
3+
* Copyright (c) 2025 SUSE LLC
4+
* Author: Christian Amann <[email protected]>
5+
* Author: Ricardo Branco <[email protected]>
6+
*
7+
* Test userfaultfd
8+
*
9+
* Force a pagefault event and handle it using userfaultfd
10+
* from a different thread using UFFDIO_ZEROPAGE
11+
*/
12+
13+
#include "config.h"
14+
#include "tst_test.h"
15+
16+
#include <poll.h>
17+
18+
#include "tst_safe_macros.h"
19+
#include "tst_safe_pthread.h"
20+
#include "lapi/userfaultfd.h"
21+
22+
static int page_size;
23+
static char *page;
24+
static int uffd;
25+
26+
static int sys_userfaultfd(int flags)
27+
{
28+
return tst_syscall(__NR_userfaultfd, flags);
29+
}
30+
31+
static void set_pages(void)
32+
{
33+
page_size = sysconf(_SC_PAGE_SIZE);
34+
page = SAFE_MMAP(NULL, page_size, PROT_READ | PROT_WRITE,
35+
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
36+
}
37+
38+
static void handle_thread(void)
39+
{
40+
static struct uffd_msg msg;
41+
struct uffdio_zeropage uffdio_zeropage;
42+
43+
struct pollfd pollfd;
44+
int nready;
45+
46+
pollfd.fd = uffd;
47+
pollfd.events = POLLIN;
48+
nready = poll(&pollfd, 1, -1);
49+
if (nready == -1)
50+
tst_brk(TBROK | TERRNO,
51+
"Error on poll");
52+
53+
SAFE_READ(1, uffd, &msg, sizeof(msg));
54+
55+
if (msg.event != UFFD_EVENT_PAGEFAULT)
56+
tst_brk(TBROK | TERRNO,
57+
"Received unexpected UFFD_EVENT");
58+
59+
uffdio_zeropage.range.start = msg.arg.pagefault.address
60+
& ~(page_size - 1);
61+
uffdio_zeropage.range.len = page_size;
62+
uffdio_zeropage.mode = 0;
63+
64+
SAFE_IOCTL(uffd, UFFDIO_ZEROPAGE, &uffdio_zeropage);
65+
66+
close(uffd);
67+
}
68+
69+
static void run(void)
70+
{
71+
pthread_t thr;
72+
struct uffdio_api uffdio_api;
73+
struct uffdio_register uffdio_register;
74+
75+
set_pages();
76+
77+
TEST(sys_userfaultfd(O_CLOEXEC | O_NONBLOCK));
78+
79+
if (TST_RET == -1) {
80+
if (TST_ERR == EPERM) {
81+
tst_res(TCONF, "Hint: check /proc/sys/vm/unprivileged_userfaultfd");
82+
tst_brk(TCONF | TTERRNO,
83+
"userfaultfd() requires CAP_SYS_PTRACE on this system");
84+
} else
85+
tst_brk(TBROK | TTERRNO,
86+
"Could not create userfault file descriptor");
87+
}
88+
89+
uffd = TST_RET;
90+
uffdio_api.api = UFFD_API;
91+
uffdio_api.features = 0;
92+
SAFE_IOCTL(uffd, UFFDIO_API, &uffdio_api);
93+
94+
uffdio_register.range.start = (unsigned long) page;
95+
uffdio_register.range.len = page_size;
96+
uffdio_register.mode = UFFDIO_REGISTER_MODE_MISSING;
97+
98+
SAFE_IOCTL(uffd, UFFDIO_REGISTER, &uffdio_register);
99+
100+
SAFE_PTHREAD_CREATE(&thr, NULL,
101+
(void * (*)(void *)) handle_thread, NULL);
102+
103+
(void)page[0xf];
104+
105+
for (int i = 0; i < page_size; i++) {
106+
if (page[i] != '\0') {
107+
tst_res(TFAIL, "page[%d]=0x%x not zero", i, page[i]);
108+
return;
109+
}
110+
}
111+
112+
tst_res(TPASS, "Pagefault handled with UFFDIO_ZEROPAGE");
113+
114+
SAFE_PTHREAD_JOIN(thr, NULL);
115+
}
116+
117+
static struct tst_test test = {
118+
.test_all = run,
119+
.min_kver = "4.3",
120+
};

0 commit comments

Comments
 (0)