Skip to content

Commit 8b0b850

Browse files
committed
Build guest memory regions using create_guest_memfd() and set_user_memory_region2()
This is a WIP commit. Signed-off-by: Matias Ezequiel Vara Larsen <[email protected]>
1 parent 4f91951 commit 8b0b850

File tree

2 files changed

+66
-21
lines changed

2 files changed

+66
-21
lines changed

src/vmm/src/builder.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -901,7 +901,7 @@ pub(crate) fn setup_vm(
901901
let mut vm = Vm::new(kvm.fd())
902902
.map_err(Error::Vm)
903903
.map_err(StartMicrovmError::Internal)?;
904-
vm.memory_init(guest_memory, kvm.max_memslots())
904+
vm.memory_init(guest_memory, kvm.max_memslots(), false)
905905
.map_err(Error::Vm)
906906
.map_err(StartMicrovmError::Internal)?;
907907
Ok(vm)
@@ -915,7 +915,7 @@ pub(crate) fn setup_vm(
915915
let mut vm = Vm::new(kvm.fd(), tee_config)
916916
.map_err(Error::Vm)
917917
.map_err(StartMicrovmError::Internal)?;
918-
vm.memory_init(guest_memory, kvm.max_memslots())
918+
vm.memory_init(guest_memory, kvm.max_memslots(), false)
919919
.map_err(Error::Vm)
920920
.map_err(StartMicrovmError::Internal)?;
921921
Ok(vm)

src/vmm/src/linux/vstate.rs

Lines changed: 64 additions & 19 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;
@@ -45,7 +46,10 @@ use kvm_bindings::{
4546
Msrs, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
4647
KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY,
4748
};
48-
use kvm_bindings::{kvm_userspace_memory_region, KVM_API_VERSION};
49+
use kvm_bindings::{
50+
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
51+
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD,
52+
};
4953
use kvm_ioctls::*;
5054
use utils::eventfd::EventFd;
5155
use utils::signal::{register_signal_handler, sigrtmin, Killable};
@@ -112,6 +116,10 @@ pub enum Error {
112116
SetUserMemoryRegion(kvm_ioctls::Error),
113117
/// Error creating memory map for SHM region.
114118
ShmMmap(io::Error),
119+
/// Cannot set the memory regions.
120+
SetUserMemoryRegion2(kvm_ioctls::Error),
121+
/// Cannot create guest memfd.
122+
CreateGuestMemfd(kvm_ioctls::Error),
115123
#[cfg(feature = "amd-sev")]
116124
/// Error initializing the Secure Virtualization Backend (SEV).
117125
SevSecVirtInit(SevError),
@@ -272,6 +280,8 @@ impl Display for Error {
272280
),
273281
SetUserMemoryRegion(e) => write!(f, "Cannot set the memory regions: {e}"),
274282
ShmMmap(e) => write!(f, "Error creating memory map for SHM region: {e}"),
283+
SetUserMemoryRegion2(e) => write!(f, "Cannot set the memory regions: {e}"),
284+
CreateGuestMemfd(e) => write!(f, "Cannot create guest memfd: {e}"),
275285
#[cfg(feature = "tee")]
276286
SevSecVirtInit(e) => {
277287
write!(
@@ -554,27 +564,62 @@ impl Vm {
554564
&mut self,
555565
guest_mem: &GuestMemoryMmap,
556566
kvm_max_memslots: usize,
567+
require_guest_memfd: bool,
557568
) -> Result<()> {
558569
if guest_mem.num_regions() > kvm_max_memslots {
559570
return Err(Error::NotEnoughMemorySlots);
560571
}
561572
for region in guest_mem.iter() {
562573
// It's safe to unwrap because the guest address is valid.
563574
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
564-
debug!("Guest memory starts at {:x?}", host_addr);
565-
let memory_region = kvm_userspace_memory_region {
566-
slot: self.next_mem_slot,
567-
guest_phys_addr: region.start_addr().raw_value(),
568-
memory_size: region.len(),
569-
userspace_addr: host_addr as u64,
570-
flags: 0,
571-
};
572-
// Safe because we mapped the memory region, we made sure that the regions
573-
// are not overlapping.
574-
unsafe {
575-
self.fd
576-
.set_user_memory_region(memory_region)
577-
.map_err(Error::SetUserMemoryRegion)?;
575+
info!("Guest memory starts at {:x?}", host_addr);
576+
577+
if require_guest_memfd {
578+
let gmem = kvm_create_guest_memfd {
579+
size: region.len(),
580+
flags: 0,
581+
reserved: [0; 6],
582+
};
583+
584+
let id: RawFd = self
585+
.fd
586+
.create_guest_memfd(gmem)
587+
.map_err(Error::CreateGuestMemfd)?;
588+
589+
let memory_region = kvm_userspace_memory_region2 {
590+
slot: self.next_mem_slot as u32,
591+
flags: KVM_MEM_GUEST_MEMFD,
592+
guest_phys_addr: region.start_addr().raw_value(),
593+
memory_size: region.len(),
594+
userspace_addr: host_addr as u64,
595+
guest_memfd_offset: 0,
596+
guest_memfd: id as u32,
597+
pad1: 0,
598+
pad2: [0; 14],
599+
};
600+
601+
// Safe because we mapped the memory region, we made sure that the regions
602+
// are not overlapping.
603+
unsafe {
604+
self.fd
605+
.set_user_memory_region2(memory_region)
606+
.map_err(Error::SetUserMemoryRegion2)?;
607+
};
608+
} else {
609+
let memory_region = kvm_userspace_memory_region {
610+
slot: self.next_mem_slot as u32,
611+
guest_phys_addr: region.start_addr().raw_value(),
612+
memory_size: region.len(),
613+
userspace_addr: host_addr as u64,
614+
flags: 0,
615+
};
616+
// Safe because we mapped the memory region, we made sure that the regions
617+
// are not overlapping.
618+
unsafe {
619+
self.fd
620+
.set_user_memory_region(memory_region)
621+
.map_err(Error::SetUserMemoryRegion)?;
622+
};
578623
};
579624
self.next_mem_slot += 1;
580625
}
@@ -1510,7 +1555,7 @@ mod tests {
15101555
let kvm = KvmContext::new().unwrap();
15111556
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), mem_size)]).unwrap();
15121557
let mut vm = Vm::new(kvm.fd()).expect("Cannot create new vm");
1513-
assert!(vm.memory_init(&gm, kvm.max_memslots()).is_ok());
1558+
assert!(vm.memory_init(&gm, kvm.max_memslots(), false).is_ok());
15141559

15151560
let exit_evt = EventFd::new(utils::eventfd::EFD_NONBLOCK).unwrap();
15161561

@@ -1565,7 +1610,7 @@ mod tests {
15651610

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

15701615
// Set the maximum number of memory slots to 1 in KvmContext to check the error
15711616
// path of memory_init. Create 2 non-overlapping memory slots.
@@ -1575,7 +1620,7 @@ mod tests {
15751620
(GuestAddress(0x1001), 0x2000),
15761621
])
15771622
.unwrap();
1578-
assert!(vm.memory_init(&gm, kvm_context.max_memslots()).is_err());
1623+
assert!(vm.memory_init(&gm, kvm_context.max_memslots(), false).is_err());
15791624
}
15801625

15811626
#[cfg(target_arch = "x86_64")]
@@ -1656,7 +1701,7 @@ mod tests {
16561701
let kvm = KvmContext::new().unwrap();
16571702
let gm = GuestMemoryMmap::from_ranges(&[(GuestAddress(0), 0x10000)]).unwrap();
16581703
let mut vm = Vm::new(kvm.fd()).expect("new vm failed");
1659-
assert!(vm.memory_init(&gm, kvm.max_memslots()).is_ok());
1704+
assert!(vm.memory_init(&gm, kvm.max_memslots(), false).is_ok());
16601705

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

0 commit comments

Comments
 (0)