Skip to content

Commit

Permalink
Enable creating guest memory regions with create_guest_memfd() and
Browse files Browse the repository at this point in the history
set_user_memory_region2()

This is a WIP commit.

Signed-off-by: Matias Ezequiel Vara Larsen <[email protected]>
  • Loading branch information
MatiasVara committed Jul 29, 2024
1 parent 0c6c660 commit 702d17f
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 20 deletions.
4 changes: 2 additions & 2 deletions src/vmm/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -819,7 +819,7 @@ pub(crate) fn setup_vm(
let mut vm = Vm::new(kvm.fd())
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;
vm.memory_init(guest_memory, kvm.max_memslots())
vm.memory_init(guest_memory, kvm.max_memslots(), false)
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;
Ok(vm)
Expand All @@ -833,7 +833,7 @@ pub(crate) fn setup_vm(
let mut vm = Vm::new(kvm.fd(), tee_config)
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;
vm.memory_init(guest_memory, kvm.max_memslots())
vm.memory_init(guest_memory, kvm.max_memslots(), false)
.map_err(Error::Vm)
.map_err(StartMicrovmError::Internal)?;
Ok(vm)
Expand Down
81 changes: 63 additions & 18 deletions src/vmm/src/linux/vstate.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use libc::{c_int, c_void, siginfo_t};
use std::cell::Cell;
use std::fmt::{Display, Formatter};
use std::io;
use std::os::fd::RawFd;

#[cfg(feature = "tee")]
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -46,7 +47,10 @@ use kvm_bindings::{
Msrs, KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
KVM_MAX_CPUID_ENTRIES, KVM_PIT_SPEAKER_DUMMY,
};
use kvm_bindings::{kvm_userspace_memory_region, KVM_API_VERSION};
use kvm_bindings::{
kvm_create_guest_memfd, kvm_userspace_memory_region, kvm_userspace_memory_region2,
KVM_API_VERSION, KVM_MEM_GUEST_MEMFD,
};
use kvm_ioctls::*;
use utils::eventfd::EventFd;
use utils::signal::{register_signal_handler, sigrtmin, Killable};
Expand Down Expand Up @@ -111,6 +115,10 @@ pub enum Error {
SetupGIC(arch::aarch64::gic::Error),
/// Cannot set the memory regions.
SetUserMemoryRegion(kvm_ioctls::Error),
/// Cannot set the memory regions.
SetUserMemoryRegion2(kvm_ioctls::Error),
// Cannot create guest memfd.
CreateGuestMemfd(kvm_ioctls::Error),
#[cfg(feature = "amd-sev")]
/// Error initializing the Secure Virtualization Backend (SEV).
SevSecVirtInit(SevError),
Expand Down Expand Up @@ -270,6 +278,8 @@ impl Display for Error {
"Cannot set the local interruption due to bad configuration: {e:?}"
),
SetUserMemoryRegion(e) => write!(f, "Cannot set the memory regions: {e}"),
SetUserMemoryRegion2(e) => write!(f, "Cannot set the memory regions: {e}"),
CreateGuestMemfd(e) => write!(f, "Cannot create guest memfd: {e}"),
#[cfg(feature = "tee")]
SevSecVirtInit(e) => {
write!(
Expand Down Expand Up @@ -549,6 +559,7 @@ impl Vm {
&mut self,
guest_mem: &GuestMemoryMmap,
kvm_max_memslots: usize,
require_guest_memfd: bool,
) -> Result<()> {
if guest_mem.num_regions() > kvm_max_memslots {
return Err(Error::NotEnoughMemorySlots);
Expand All @@ -557,19 +568,53 @@ impl Vm {
// It's safe to unwrap because the guest address is valid.
let host_addr = guest_mem.get_host_address(region.start_addr()).unwrap();
info!("Guest memory starts at {:x?}", host_addr);
let memory_region = kvm_userspace_memory_region {
slot: index as u32,
guest_phys_addr: region.start_addr().raw_value(),
memory_size: region.len(),
userspace_addr: host_addr as u64,
flags: 0,
};
// Safe because we mapped the memory region, we made sure that the regions
// are not overlapping.
unsafe {
self.fd
.set_user_memory_region(memory_region)
.map_err(Error::SetUserMemoryRegion)?;

if require_guest_memfd {
let gmem = kvm_create_guest_memfd {
size: region.len(),
flags: 0,
reserved: [0; 6],
};

let id: RawFd = self
.fd
.create_guest_memfd(gmem)
.map_err(Error::CreateGuestMemfd)?;

let memory_region = kvm_userspace_memory_region2 {
slot: index as u32,
flags: KVM_MEM_GUEST_MEMFD,
guest_phys_addr: region.start_addr().raw_value(),
memory_size: region.len(),
userspace_addr: host_addr as u64,
guest_memfd_offset: 0,
guest_memfd: id as u32,
pad1: 0,
pad2: [0; 14],
};

// Safe because we mapped the memory region, we made sure that the regions
// are not overlapping.
unsafe {
self.fd
.set_user_memory_region2(memory_region)
.map_err(Error::SetUserMemoryRegion2)?;
};
} else {
let memory_region = kvm_userspace_memory_region {
slot: index as u32,
guest_phys_addr: region.start_addr().raw_value(),
memory_size: region.len(),
userspace_addr: host_addr as u64,
flags: 0,
};
// Safe because we mapped the memory region, we made sure that the regions
// are not overlapping.
unsafe {
self.fd
.set_user_memory_region(memory_region)
.map_err(Error::SetUserMemoryRegion)?;
};
};
}

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

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

Expand Down Expand Up @@ -1560,7 +1605,7 @@ mod tests {

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

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

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

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

0 comments on commit 702d17f

Please sign in to comment.