Struct swap::userfaultfd::Userfaultfd
source · pub struct Userfaultfd {
uffd: Uffd,
}
Expand description
Wrapper for [userfaultfd::Uffd
] to be used in the vmm-swap feature.
§Safety
The userfaultfd operations (UFFDIO_COPY
and UFFDIO_ZEROPAGE
) looks unsafe since it fills a
memory content directly. But they actually are not unsafe operation but UFFDIO_REGISTER
should
be the unsafe operation for Rust memory safety.
According to the Rust document,
All runtime-allocated memory in a Rust program begins its life as uninitialized.
The userfaultfd operations actually does not change/overwrite the existing memory contents but they just setup the “uninitialized” pages. If the page was already initialized, the userfaultfd operations fail and return EEXIST error (which is not documented unfortunately). So they originally does not affect the Rust memory safety.
The “uninitialized” page in this context has 2 patterns:
- pages which is never touched or,
- pages which is never touched after MADV_REMOVE
Filling the (1) pages with any contents should not affect the Rust memory safety.
Filling the (2) pages potentially may break the memory used by Rust. But the safety should be
examined at MADV_REMOVE
and UFFDIO_REGISTER
timing.
Fields§
§uffd: Uffd
Implementations§
source§impl Userfaultfd
impl Userfaultfd
sourcepub fn new() -> Result<Self>
pub fn new() -> Result<Self>
Creates a new userfaultfd using userfaultfd(2) syscall.
This is public for tests.
sourcepub unsafe fn register(&self, addr: usize, len: usize) -> Result<IoctlFlags>
pub unsafe fn register(&self, addr: usize, len: usize) -> Result<IoctlFlags>
Register a range of memory to the userfaultfd.
After this registration, any page faults on the range will be caught by the userfaultfd.
§Arguments
addr
- the starting address of the range of memory.len
- the length in bytes of the range of memory.
§Safety
[addr, addr+len) must lie within a [MemoryMapping], and that mapping
must live for the lifespan of the userfaultfd kernel object (which may be distinct from the
Userfaultfd
rust object in this process).
sourcepub fn unregister(&self, addr: usize, len: usize) -> Result<()>
pub fn unregister(&self, addr: usize, len: usize) -> Result<()>
Unregister a range of memory from the userfaultfd.
§Arguments
addr
- the starting address of the range of memory.len
- the length in bytes of the range of memory.
sourcepub fn zero(&self, addr: usize, len: usize, wake: bool) -> Result<usize>
pub fn zero(&self, addr: usize, len: usize, wake: bool) -> Result<usize>
Initialize page(s) and fill it with zero.
§Arguments
addr
- the starting address of the page(s) to be initialzed with zero.len
- the length in bytes of the page(s).wake
- whether or not to unblock the faulting thread.
sourcepub fn copy(
&self,
addr: usize,
len: usize,
data: *const u8,
wake: bool
) -> Result<usize>
pub fn copy( &self, addr: usize, len: usize, data: *const u8, wake: bool ) -> Result<usize>
Copy the data
to the page(s) starting from addr
.
§Arguments
addr
- the starting address of the page(s) to be initialzed with data.len
- the length in bytes of the page(s).data
- the starting address of the content.wake
- whether or not to unblock the faulting thread.
sourcepub fn wake(&self, addr: usize, len: usize) -> Result<()>
pub fn wake(&self, addr: usize, len: usize) -> Result<()>
Wake the faulting thread blocked by the page(s).
If the page is not initialized, the thread causes a page fault again.
§Arguments
addr
- the starting address of the page(s).len
- the length in bytes of the page(s).
sourcepub fn read_event(&self) -> Result<Option<UffdEvent>>
pub fn read_event(&self) -> Result<Option<UffdEvent>>
Read an event from the userfaultfd.
Return None
immediately if no events is ready to read.
sourcepub fn try_clone(&self) -> Result<Self>
pub fn try_clone(&self) -> Result<Self>
Try to clone Userfaultfd