tools/testing/selftests/kvm/lib/userfaultfd_util.c
Source file repositories/reference/linux-study-clean/tools/testing/selftests/kvm/lib/userfaultfd_util.c
File Facts
- System
- Linux kernel
- Corpus path
tools/testing/selftests/kvm/lib/userfaultfd_util.c- Extension
.c- Size
- 5877 bytes
- Lines
- 207
- 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.
- Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.
- Defines or uses C structs; map object ownership, embedded links, reference counts, and lock ownership.
Dependency Surface
inttypes.hstdio.hstdlib.htime.hpoll.hpthread.hlinux/userfaultfd.hsys/epoll.hsys/syscall.hkvm_util.htest_util.hmemstress.huserfaultfd_util.h
Detected Declarations
function Copyrightfunction uffd_stop_demand_paging
Annotated Snippet
if (evt.data.u32 == 1) {
char tmp_chr;
TEST_ASSERT(!(evt.events & (EPOLLERR | EPOLLHUP)),
"Reader thread received EPOLLERR or EPOLLHUP on pipe.");
r = read(reader_args->pipe, &tmp_chr, 1);
TEST_ASSERT(r == 1,
"Error reading pipefd in uffd reader thread");
break;
}
TEST_ASSERT(!(evt.events & (EPOLLERR | EPOLLHUP)),
"Reader thread received EPOLLERR or EPOLLHUP on uffd.");
r = read(uffd, &msg, sizeof(msg));
if (r == -1) {
TEST_ASSERT(errno == EAGAIN,
"Error reading from UFFD: errno = %d", errno);
continue;
}
TEST_ASSERT(r == sizeof(msg),
"Read on uffd returned unexpected number of bytes (%d)", r);
if (!(msg.event & UFFD_EVENT_PAGEFAULT))
continue;
if (reader_args->delay)
usleep(reader_args->delay);
r = reader_args->handler(reader_args->uffd_mode, uffd, &msg);
TEST_ASSERT(r >= 0,
"Reader thread handler fn returned negative value %d", r);
pages++;
}
ts_diff = timespec_elapsed(start);
PER_VCPU_DEBUG("userfaulted %ld pages over %ld.%.9lds. (%f/sec)\n",
pages, ts_diff.tv_sec, ts_diff.tv_nsec,
pages / ((double)ts_diff.tv_sec + (double)ts_diff.tv_nsec / NSEC_PER_SEC));
return NULL;
}
struct uffd_desc *uffd_setup_demand_paging(int uffd_mode, useconds_t delay,
void *hva, u64 len,
u64 num_readers,
uffd_handler_t handler)
{
struct uffd_desc *uffd_desc;
bool is_minor = (uffd_mode == UFFDIO_REGISTER_MODE_MINOR);
int uffd;
struct uffdio_api uffdio_api;
struct uffdio_register uffdio_register;
u64 expected_ioctls = ((u64)1) << _UFFDIO_COPY;
int ret, i;
PER_PAGE_DEBUG("Userfaultfd %s mode, faults resolved with %s\n",
is_minor ? "MINOR" : "MISSING",
is_minor ? "UFFDIO_CONTINUE" : "UFFDIO_COPY");
uffd_desc = malloc(sizeof(struct uffd_desc));
TEST_ASSERT(uffd_desc, "Failed to malloc uffd descriptor");
uffd_desc->pipefds = calloc(sizeof(int), num_readers);
TEST_ASSERT(uffd_desc->pipefds, "Failed to alloc pipes");
uffd_desc->readers = calloc(sizeof(pthread_t), num_readers);
TEST_ASSERT(uffd_desc->readers, "Failed to alloc reader threads");
uffd_desc->reader_args = calloc(sizeof(struct uffd_reader_args), num_readers);
TEST_ASSERT(uffd_desc->reader_args, "Failed to alloc reader_args");
uffd_desc->num_readers = num_readers;
/* In order to get minor faults, prefault via the alias. */
if (is_minor)
expected_ioctls = ((u64)1) << _UFFDIO_CONTINUE;
uffd = syscall(__NR_userfaultfd, O_CLOEXEC | O_NONBLOCK);
TEST_ASSERT(uffd >= 0, "uffd creation failed, errno: %d", errno);
uffdio_api.api = UFFD_API;
uffdio_api.features = 0;
TEST_ASSERT(ioctl(uffd, UFFDIO_API, &uffdio_api) != -1,
"ioctl UFFDIO_API failed: %" PRIu64,
(u64)uffdio_api.api);
uffdio_register.range.start = (u64)hva;
uffdio_register.range.len = len;
uffdio_register.mode = uffd_mode;
Annotation
- Immediate include surface: `inttypes.h`, `stdio.h`, `stdlib.h`, `time.h`, `poll.h`, `pthread.h`, `linux/userfaultfd.h`, `sys/epoll.h`.
- Detected declarations: `function Copyright`, `function uffd_stop_demand_paging`.
- Atlas domain: Support Tooling And Documentation / tools.
- Implementation status: source implementation candidate.
Implementation Notes
- This generated page is the file-by-file coverage layer; curated subsystem chapters should link here when they synthesize a multi-file control flow.
- Core OS pages should be promoted from atlas-only to deep-reviewed when they explain data structures, invariants, locking, lifecycle, and C implementation snippets.
- Driver-family pages are intentionally pattern-oriented unless they are part of the selected PCIe/NVMe representative device path.