Skip to content

Commit b2cbebf

Browse files
committed
add support for set_user_memory_region2
Signed-off-by: Jake Correnti <jakecorrenti+github@proton.me>
1 parent 3fbdd07 commit b2cbebf

File tree

2 files changed

+115
-0
lines changed

2 files changed

+115
-0
lines changed

src/ioctls/vm.rs

Lines changed: 109 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -111,6 +111,97 @@ impl VmFd {
111111
}
112112
}
113113

114+
/// Creates/modifies a guest physical memory slot.
115+
///
116+
/// See the documentation for `KVM_SET_USER_MEMORY_REGION2`.
117+
///
118+
/// # Arguments
119+
///
120+
/// * `user_memory_region2` - Guest physical memory slot. For details check the
121+
/// `kvm_userspace_memory_region2` structure in the
122+
///
123+
/// # Safety
124+
///
125+
/// This function is unsafe because there is no guarantee `userspace_addr` points to a valid
126+
/// memory region, nor the memory region lives as long as the kernel needs it to.
127+
///
128+
/// The caller of this method must make sure that:
129+
/// - the raw pointer (`userspace_addr`) points to valid memory
130+
/// - the regions provided to KVM are not overlapping other memory regions.
131+
/// - the guest_memfd points at a file created via KVM_CREATE_GUEST_MEMFD on
132+
/// the current VM, and the target range must not be bound to any other memory region
133+
///
134+
/// # Example
135+
///
136+
/// ```rust
137+
/// # extern crate kvm_ioctls;
138+
/// extern crate kvm_bindings;
139+
///
140+
/// use kvm_bindings::{
141+
/// kvm_create_guest_memfd, kvm_enable_cap, kvm_userspace_memory_region2, KVM_CAP_GUEST_MEMFD,
142+
/// KVM_CAP_USER_MEMORY2, KVM_MEM_GUEST_MEMFD,
143+
/// };
144+
/// use kvm_ioctls::Kvm;
145+
/// use std::os::fd::RawFd;
146+
///
147+
/// # #[cfg(target_arch = "x86_64")]
148+
/// {
149+
/// let kvm = Kvm::new().unwrap();
150+
/// let vm = kvm.create_vm().unwrap();
151+
///
152+
/// let address_space = unsafe { libc::mmap(0 as _, 10000, 3, 34, -1, 0) };
153+
/// let userspace_addr = address_space as *const u8 as u64;
154+
///
155+
/// let mut config = kvm_enable_cap {
156+
/// cap: KVM_CAP_GUEST_MEMFD,
157+
/// ..Default::default()
158+
/// };
159+
///
160+
/// if vm.enable_cap(&config).is_err() {
161+
/// return;
162+
/// }
163+
/// let gmem = kvm_create_guest_memfd {
164+
/// size: 0x10000,
165+
/// flags: 0,
166+
/// reserved: [0; 6],
167+
/// };
168+
///
169+
/// let fd: RawFd = unsafe { vm.create_guest_memfd(gmem).unwrap() };
170+
///
171+
/// config.cap = KVM_CAP_USER_MEMORY2;
172+
///
173+
/// if vm.enable_cap(&config).is_err() {
174+
/// return;
175+
/// }
176+
///
177+
/// let mem_region = kvm_userspace_memory_region2 {
178+
/// slot: 0,
179+
/// flags: KVM_MEM_GUEST_MEMFD,
180+
/// guest_phys_addr: 0x10000 as u64,
181+
/// memory_size: 0x10000 as u64,
182+
/// userspace_addr,
183+
/// guest_memfd_offset: 0,
184+
/// guest_memfd: fd as u32,
185+
/// pad1: 0,
186+
/// pad2: [0; 14],
187+
/// };
188+
/// unsafe {
189+
/// vm.set_user_memory_region2(mem_region).unwrap();
190+
/// };
191+
/// }
192+
/// ```
193+
pub unsafe fn set_user_memory_region2(
194+
&self,
195+
user_memory_region2: kvm_userspace_memory_region2,
196+
) -> Result<()> {
197+
let ret = ioctl_with_ref(self, KVM_SET_USER_MEMORY_REGION2(), &user_memory_region2);
198+
if ret == 0 {
199+
Ok(())
200+
} else {
201+
Err(errno::Error::last())
202+
}
203+
}
204+
114205
/// Sets the address of the three-page region in the VM's address space.
115206
///
116207
/// See the documentation for `KVM_SET_TSS_ADDR`.
@@ -1877,6 +1968,24 @@ mod tests {
18771968
assert!(unsafe { vm.set_user_memory_region(invalid_mem_region) }.is_err());
18781969
}
18791970

1971+
#[test]
1972+
fn test_set_invalid_memory2() {
1973+
let kvm = Kvm::new().unwrap();
1974+
let vm = kvm.create_vm().unwrap();
1975+
let invalid_mem_region = kvm_userspace_memory_region2 {
1976+
slot: 0,
1977+
flags: 0,
1978+
guest_phys_addr: 0,
1979+
memory_size: 0,
1980+
userspace_addr: 0,
1981+
guest_memfd_offset: 0,
1982+
guest_memfd: 0,
1983+
pad1: 0,
1984+
pad2: [0; 14],
1985+
};
1986+
assert!(unsafe { vm.set_user_memory_region2(invalid_mem_region) }.is_err());
1987+
}
1988+
18801989
#[test]
18811990
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
18821991
fn test_set_tss_address() {

src/kvm_ioctls.rs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,12 @@ ioctl_iow_nr!(
3838
0x46,
3939
kvm_userspace_memory_region
4040
);
41+
ioctl_iow_nr!(
42+
KVM_SET_USER_MEMORY_REGION2,
43+
KVMIO,
44+
0x49,
45+
kvm_userspace_memory_region2
46+
);
4147
/* Available with KVM_CAP_SET_TSS_ADDR */
4248
#[cfg(any(target_arch = "x86", target_arch = "x86_64"))]
4349
ioctl_io_nr!(KVM_SET_TSS_ADDR, KVMIO, 0x47);

0 commit comments

Comments
 (0)