Skip to content

Commit 3fb0482

Browse files
committed
use correct vm type for guest_memfd
On x86, only KVM_X86_SW_PROTECTED_VM VMs support guest_memfd, so we have to explicitly specify this VM type. On Arm, all VMs support it. Signed-off-by: Patrick Roy <[email protected]>
1 parent d89ae0d commit 3fb0482

File tree

6 files changed

+44
-17
lines changed

6 files changed

+44
-17
lines changed

src/vmm/src/arch/aarch64/vm.rs

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,14 @@ use crate::arch::aarch64::gic::GicState;
88
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState};
99
use crate::vstate::vm::{VmCommon, VmError};
1010

11+
/// The VM type for this architecture that allows us to use guest_memfd. On ARM, all VMs
12+
/// support guest_memfd and no special type is needed (in fact, no concept of vm types really
13+
/// exists, and the correspoding field of the CREATE_VM ioctl determines IPA size instead,
14+
/// e.g. the size of the guest physical address space. This value cannot be hardcoded, hence
15+
/// `None` to let the `Vm` constructor now that just normal [`Kvm::create_vm`] should be called,
16+
/// which internally determines the preferred IPA size.
17+
pub const VM_TYPE_FOR_SECRET_FREEDOM: Option<u64> = None;
18+
1119
/// Structure representing the current architecture's understand of what a "virtual machine" is.
1220
#[derive(Debug)]
1321
pub struct ArchVm {
@@ -30,8 +38,8 @@ pub enum ArchVmError {
3038

3139
impl ArchVm {
3240
/// Create a new `Vm` struct.
33-
pub fn new(kvm: &Kvm) -> Result<ArchVm, VmError> {
34-
let common = Self::create_common(kvm)?;
41+
pub fn new(kvm: &Kvm, vm_type: Option<u64>) -> Result<ArchVm, VmError> {
42+
let common = Self::create_common(kvm, vm_type)?;
3543
Ok(ArchVm {
3644
common,
3745
irqchip_handle: None,

src/vmm/src/arch/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ pub use aarch64::kvm::{Kvm, KvmArchError, OptionalCapabilities};
1717
#[cfg(target_arch = "aarch64")]
1818
pub use aarch64::vcpu::*;
1919
#[cfg(target_arch = "aarch64")]
20-
pub use aarch64::vm::{ArchVm, ArchVmError, VmState};
20+
pub use aarch64::vm::{ArchVm, ArchVmError, VM_TYPE_FOR_SECRET_FREEDOM, VmState};
2121
#[cfg(target_arch = "aarch64")]
2222
pub use aarch64::{
2323
ConfigurationError, MMIO_MEM_SIZE, MMIO_MEM_START, arch_memory_regions,
@@ -35,7 +35,7 @@ pub use x86_64::kvm::{Kvm, KvmArchError};
3535
#[cfg(target_arch = "x86_64")]
3636
pub use x86_64::vcpu::*;
3737
#[cfg(target_arch = "x86_64")]
38-
pub use x86_64::vm::{ArchVm, ArchVmError, VmState};
38+
pub use x86_64::vm::{ArchVm, ArchVmError, VM_TYPE_FOR_SECRET_FREEDOM, VmState};
3939

4040
#[cfg(target_arch = "x86_64")]
4141
pub use crate::arch::x86_64::{

src/vmm/src/arch/x86_64/vm.rs

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,21 @@ use std::fmt;
55

66
use kvm_bindings::{
77
KVM_CLOCK_TSC_STABLE, KVM_IRQCHIP_IOAPIC, KVM_IRQCHIP_PIC_MASTER, KVM_IRQCHIP_PIC_SLAVE,
8-
KVM_PIT_SPEAKER_DUMMY, MsrList, kvm_clock_data, kvm_irqchip, kvm_pit_config, kvm_pit_state2,
8+
KVM_PIT_SPEAKER_DUMMY, KVM_X86_SW_PROTECTED_VM, MsrList, kvm_clock_data, kvm_irqchip,
9+
kvm_pit_config, kvm_pit_state2,
910
};
1011
use kvm_ioctls::Cap;
1112
use serde::{Deserialize, Serialize};
1213

14+
use crate::arch::Kvm;
1315
use crate::arch::x86_64::msr::MsrError;
1416
use crate::utils::u64_to_usize;
1517
use crate::vstate::memory::{GuestMemoryExtension, GuestMemoryState};
1618
use crate::vstate::vm::{VmCommon, VmError};
1719

20+
/// The VM type for this architecture that allows us to use guest_memfd.
21+
pub const VM_TYPE_FOR_SECRET_FREEDOM: Option<u64> = Some(KVM_X86_SW_PROTECTED_VM as u64);
22+
1823
/// Error type for [`Vm::restore_state`]
1924
#[allow(missing_docs)]
2025
#[cfg(target_arch = "x86_64")]
@@ -60,8 +65,8 @@ pub struct ArchVm {
6065

6166
impl ArchVm {
6267
/// Create a new `Vm` struct.
63-
pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
64-
let common = Self::create_common(kvm)?;
68+
pub fn new(kvm: &Kvm, vm_type: Option<u64>) -> Result<ArchVm, VmError> {
69+
let common = Self::create_common(kvm, vm_type)?;
6570

6671
let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;
6772

src/vmm/src/builder.rs

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,9 @@ use vm_superio::Rtc;
2020
use vm_superio::Serial;
2121
use vmm_sys_util::eventfd::EventFd;
2222

23-
use crate::arch::{ConfigurationError, configure_system_for_boot, load_kernel};
23+
use crate::arch::{
24+
ConfigurationError, VM_TYPE_FOR_SECRET_FREEDOM, configure_system_for_boot, load_kernel,
25+
};
2426
#[cfg(target_arch = "aarch64")]
2527
use crate::construct_kvm_mpidrs;
2628
use crate::cpu_config::templates::{
@@ -142,11 +144,12 @@ fn create_vmm_and_vcpus(
142144
event_manager: &mut EventManager,
143145
vcpu_count: u8,
144146
kvm_capabilities: Vec<KvmCapability>,
147+
vm_type: Option<u64>,
145148
) -> Result<(Vmm, Vec<Vcpu>), VmmError> {
146149
let kvm = Kvm::new(kvm_capabilities)?;
147150
// Set up Kvm Vm and register memory regions.
148151
// Build custom CPU config if a custom template is provided.
149-
let mut vm = Vm::new(&kvm)?;
152+
let mut vm = Vm::new(&kvm, vm_type)?;
150153

151154
let resource_allocator = ResourceAllocator::new()?;
152155

@@ -227,12 +230,17 @@ pub fn build_microvm_for_boot(
227230
.get_cpu_template()?;
228231

229232
let secret_free = vm_resources.machine_config.mem_config.secret_free;
233+
let vm_type = match secret_free {
234+
true => VM_TYPE_FOR_SECRET_FREEDOM,
235+
false => None,
236+
};
230237

231238
let (mut vmm, mut vcpus) = create_vmm_and_vcpus(
232239
instance_info,
233240
event_manager,
234241
vm_resources.machine_config.vcpu_count,
235242
cpu_template.kvm_capabilities.clone(),
243+
vm_type,
236244
)?;
237245

238246
let guest_memfd = match secret_free {
@@ -472,6 +480,7 @@ pub fn build_microvm_from_snapshot(
472480
event_manager,
473481
vm_resources.machine_config.vcpu_count,
474482
microvm_state.kvm_state.kvm_cap_modifiers.clone(),
483+
None, // TODO: secret freedom support post snapshot restore
475484
)
476485
.map_err(StartMicrovmError::Internal)?;
477486

src/vmm/src/device_manager/mmio.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -655,7 +655,7 @@ mod tests {
655655
let start_addr2 = GuestAddress(0x1000);
656656
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
657657
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
658-
let mut vm = Vm::new(&kvm).unwrap();
658+
let mut vm = Vm::new(&kvm, None).unwrap();
659659
vm.register_memory_regions(guest_mem, false).unwrap();
660660
let mut device_manager = MMIODeviceManager::new();
661661
let mut resource_allocator = ResourceAllocator::new().unwrap();
@@ -686,7 +686,7 @@ mod tests {
686686
let start_addr2 = GuestAddress(0x1000);
687687
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
688688
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
689-
let mut vm = Vm::new(&kvm).unwrap();
689+
let mut vm = Vm::new(&kvm, None).unwrap();
690690
vm.register_memory_regions(guest_mem, false).unwrap();
691691
let mut device_manager = MMIODeviceManager::new();
692692
let mut resource_allocator = ResourceAllocator::new().unwrap();
@@ -742,7 +742,7 @@ mod tests {
742742
let start_addr2 = GuestAddress(0x1000);
743743
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
744744
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
745-
let mut vm = Vm::new(&kvm).unwrap();
745+
let mut vm = Vm::new(&kvm, None).unwrap();
746746
vm.register_memory_regions(guest_mem, false).unwrap();
747747

748748
#[cfg(target_arch = "x86_64")]

src/vmm/src/vstate/vm.rs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ use kvm_ioctls::{Cap, VmFd};
1818
use userfaultfd::{FeatureFlags, Uffd, UffdBuilder};
1919
use vmm_sys_util::eventfd::EventFd;
2020

21-
use crate::arch::host_page_size;
2221
pub use crate::arch::{ArchVm as Vm, ArchVmError, VmState};
22+
use crate::arch::{Kvm, host_page_size};
2323
use crate::logger::info;
2424
use crate::persist::{CreateSnapshotError, GuestRegionUffdMapping};
2525
use crate::utils::u64_to_usize;
@@ -73,7 +73,7 @@ pub enum VmError {
7373
/// Contains Vm functions that are usable across CPU architectures
7474
impl Vm {
7575
/// Create a KVM VM
76-
pub fn create_common(kvm: &crate::vstate::kvm::Kvm) -> Result<VmCommon, VmError> {
76+
pub fn create_common(kvm: &Kvm, vm_type: Option<u64>) -> Result<VmCommon, VmError> {
7777
// It is known that KVM_CREATE_VM occasionally fails with EINTR on heavily loaded machines
7878
// with many VMs.
7979
//
@@ -97,7 +97,12 @@ impl Vm {
9797
const MAX_ATTEMPTS: u32 = 5;
9898
let mut attempt = 1;
9999
let fd = loop {
100-
match kvm.fd.create_vm() {
100+
let vm_res = match vm_type {
101+
Some(r#type) => kvm.fd.create_vm_with_type(r#type),
102+
None => kvm.fd.create_vm(),
103+
};
104+
105+
match vm_res {
101106
Ok(fd) => break fd,
102107
Err(e) if e.errno() == libc::EINTR && attempt < MAX_ATTEMPTS => {
103108
info!("Attempt #{attempt} of KVM_CREATE_VM returned EINTR");
@@ -464,7 +469,7 @@ pub(crate) mod tests {
464469
// Auxiliary function being used throughout the tests.
465470
pub(crate) fn setup_vm() -> (Kvm, Vm) {
466471
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
467-
let vm = Vm::new(&kvm).expect("Cannot create new vm");
472+
let vm = Vm::new(&kvm, None).expect("Cannot create new vm");
468473
(kvm, vm)
469474
}
470475

@@ -480,7 +485,7 @@ pub(crate) mod tests {
480485
fn test_new() {
481486
// Testing with a valid /dev/kvm descriptor.
482487
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
483-
Vm::new(&kvm).unwrap();
488+
Vm::new(&kvm, None).unwrap();
484489
}
485490

486491
#[test]

0 commit comments

Comments
 (0)