Skip to content

Commit 702d17f

Browse files
committed
Enable creating guest memory regions with create_guest_memfd() and
set_user_memory_region2() This is a WIP commit. Signed-off-by: Matias Ezequiel Vara Larsen <[email protected]>
1 parent 0c6c660 commit 702d17f

File tree

2 files changed

+65
-20
lines changed

2 files changed

+65
-20
lines changed

src/vmm/src/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -819,7 +819,7 @@ pub(crate) fn setup_vm(
819819
let mut vm = Vm::new(kvm.fd())
820820
.map_err(Error::Vm)
821821
.map_err(StartMicrovmError::Internal)?;
822-
vm.memory_init(guest_memory, kvm.max_memslots())
822+
vm.memory_init(guest_memory, kvm.max_memslots(), false)
823823
.map_err(Error::Vm)
824824
.map_err(StartMicrovmError::Internal)?;
825825
Ok(vm)
@@ -833,7 +833,7 @@ pub(crate) fn setup_vm(
833833
let mut vm = Vm::new(kvm.fd(), tee_config)
834834
.map_err(Error::Vm)
835835
.map_err(StartMicrovmError::Internal)?;
836-
vm.memory_init(guest_memory, kvm.max_memslots())
836+
vm.memory_init(guest_memory, kvm.max_memslots(), false)
837837
.map_err(Error::Vm)
838838
.map_err(StartMicrovmError::Internal)?;
839839
Ok(vm)

src/vmm/src/linux/vstate.rs

Lines changed: 63 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ use libc::{c_int, c_void, siginfo_t};
1010
use std::cell::Cell;
1111
use std::fmt::{Display, Formatter};
1212
use std::io;
13+
use std::os::fd::RawFd;
1314

1415
#[cfg(feature = "tee")]
1516
use std::os::unix::io::RawFd;
@@ -46,7 +47,10 @@ use kvm_bindings::{
4647
Msrs, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
4748
KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY,
4849
};
49-
use kvm_bindings::{kvm_userspace_memory_region, KVM_API_VERSION};
50+
use kvm_bindings::{
51+
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
52+
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD,
53+
};
5054
use kvm_ioctls::*;
5155
use utils::eventfd::EventFd;
5256
use utils::signal::{register_signal_handler, sigrtmin, Killable};
@@ -111,6 +115,10 @@ pub enum Error {
111115
SetupGIC(arch::aarch64::gic::Error),
112116
/// Cannot set the memory regions.
113117
SetUserMemoryRegion(kvm_ioctls::Error),
118+
/// Cannot set the memory regions.
119+
SetUserMemoryRegion2(kvm_ioctls::Error),
120+
// Cannot create guest memfd.
121+
CreateGuestMemfd(kvm_ioctls::Error),
114122
#[cfg(feature = "amd-sev")]
115123
/// Error initializing the Secure Virtualization Backend (SEV).
116124
SevSecVirtInit(SevError),
@@ -270,6 +278,8 @@ impl Display for Error {
270278
"Cannot set the local interruption due to bad configuration: {e:?}"
271279
),
272280
SetUserMemoryRegion(e) => write!(f, "Cannot set the memory regions: {e}"),
281+
SetUserMemoryRegion2(e) => write!(f, "Cannot set the memory regions: {e}"),
282+
CreateGuestMemfd(e) => write!(f, "Cannot create guest memfd: {e}"),
273283
#[cfg(feature = "tee")]
274284
SevSecVirtInit(e) => {
275285
write!(
@@ -549,6 +559,7 @@ impl Vm {
549559
&mut self,
550560
guest_mem: &GuestMemoryMmap,
551561
kvm_max_memslots: usize,
562+
require_guest_memfd: bool,
552563
) -> Result<()> {
553564
if guest_mem.num_regions() > kvm_max_memslots {
554565
return Err(Error::NotEnoughMemorySlots);
@@ -557,19 +568,53 @@ impl Vm {
557568
// It's safe to unwrap because the guest address is valid.
558569
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
559570
info!("Guest memory starts at {:x?}", host_addr);
560-
let memory_region = kvm_userspace_memory_region {
561-
slot: index as u32,
562-
guest_phys_addr: region.start_addr().raw_value(),
563-
memory_size: region.len(),
564-
userspace_addr: host_addr as u64,
565-
flags: 0,
566-
};
567-
// Safe because we mapped the memory region, we made sure that the regions
568-
// are not overlapping.
569-
unsafe {
570-
self.fd
571-
.set_user_memory_region(memory_region)
572-
.map_err(Error::SetUserMemoryRegion)?;
571+
572+
if require_guest_memfd {
573+
let gmem = kvm_create_guest_memfd {
574+
size: region.len(),
575+
flags: 0,
576+
reserved: [0; 6],
577+
};
578+
579+
let id: RawFd = self
580+
.fd
581+
.create_guest_memfd(gmem)
582+
.map_err(Error::CreateGuestMemfd)?;
583+
584+
let memory_region = kvm_userspace_memory_region2 {
585+
slot: index as u32,
586+
flags: KVM_MEM_GUEST_MEMFD,
587+
guest_phys_addr: region.start_addr().raw_value(),
588+
memory_size: region.len(),
589+
userspace_addr: host_addr as u64,
590+
guest_memfd_offset: 0,
591+
guest_memfd: id as u32,
592+
pad1: 0,
593+
pad2: [0; 14],
594+
};
595+
596+
// Safe because we mapped the memory region, we made sure that the regions
597+
// are not overlapping.
598+
unsafe {
599+
self.fd
600+
.set_user_memory_region2(memory_region)
601+
.map_err(Error::SetUserMemoryRegion2)?;
602+
};
603+
} else {
604+
let memory_region = kvm_userspace_memory_region {
605+
slot: index as u32,
606+
guest_phys_addr: region.start_addr().raw_value(),
607+
memory_size: region.len(),
608+
userspace_addr: host_addr as u64,
609+
flags: 0,
610+
};
611+
// Safe because we mapped the memory region, we made sure that the regions
612+
// are not overlapping.
613+
unsafe {
614+
self.fd
615+
.set_user_memory_region(memory_region)
616+
.map_err(Error::SetUserMemoryRegion)?;
617+
};
573618
};
574619
}
575620

@@ -1505,7 +1550,7 @@ mod tests {
15051550
let kvm = KvmContext::new().unwrap();
15061551
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), mem_size)]).unwrap();
15071552
let mut vm = Vm::new(kvm.fd()).expect("Cannot create new vm");
1508-
assert!(vm.memory_init(&gm, kvm.max_memslots()).is_ok());
1553+
assert!(vm.memory_init(&gm, kvm.max_memslots(), false).is_ok());
15091554

15101555
let exit_evt = EventFd::new(utils::eventfd::EFD_NONBLOCK).unwrap();
15111556

@@ -1560,7 +1605,7 @@ mod tests {
15601605

15611606
// Create valid memory region and test that the initialization is successful.
15621607
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x1000)]).unwrap();
1563-
assert!(vm.memory_init(&gm, kvm_context.max_memslots()).is_ok());
1608+
assert!(vm.memory_init(&gm, kvm_context.max_memslots(), false).is_ok());
15641609

15651610
// Set the maximum number of memory slots to 1 in KvmContext to check the error
15661611
// path of memory_init. Create 2 non-overlapping memory slots.
@@ -1570,7 +1615,7 @@ mod tests {
15701615
(GuestAddress(0x1001), 0x2000),
15711616
])
15721617
.unwrap();
1573-
assert!(vm.memory_init(&gm, kvm_context.max_memslots()).is_err());
1618+
assert!(vm.memory_init(&gm, kvm_context.max_memslots(), false).is_err());
15741619
}
15751620

15761621
#[cfg(target_arch = "x86_64")]
@@ -1651,7 +1696,7 @@ mod tests {
16511696
let kvm = KvmContext::new().unwrap();
16521697
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
16531698
let mut vm = Vm::new(kvm.fd()).expect("new vm failed");
1654-
assert!(vm.memory_init(&gm, kvm.max_memslots()).is_ok());
1699+
assert!(vm.memory_init(&gm, kvm.max_memslots(), false).is_ok());
16551700

16561701
// Try it for when vcpu id is 0.
16571702
let mut vcpu = Vcpu::new_aarch64(

0 commit comments

Comments
 (0)