Skip to content

Commit b518c86

Browse files
committed
add concept of "secret free" VMs
Have the `struct Vm` constructor take an argument to indicate whether the VM should be secret free. Use this to determine the correct vm type for guest_memfd support, and store it inside the VM so that we don't have to pass bools to various functions. Signed-off-by: Patrick Roy <roypat@amazon.co.uk>
1 parent fc0b9fa commit b518c86

File tree

6 files changed

+74
-65
lines changed

6 files changed

+74
-65
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, secret_free: bool) -> Result<ArchVm, VmError> {
42+
let common = Self::create_common(kvm, secret_free)?;
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: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,8 @@ 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};
@@ -46,6 +47,9 @@ pub enum ArchVmError {
4647
SetTssAddress(kvm_ioctls::Error),
4748
}
4849

50+
/// The VM type for this architecture that allows us to use guest_memfd.
51+
pub const VM_TYPE_FOR_SECRET_FREEDOM: Option<u64> = Some(KVM_X86_SW_PROTECTED_VM as u64);
52+
4953
/// Structure representing the current architecture's understand of what a "virtual machine" is.
5054
#[derive(Debug)]
5155
pub struct ArchVm {
@@ -60,8 +64,8 @@ pub struct ArchVm {
6064

6165
impl ArchVm {
6266
/// Create a new `Vm` struct.
63-
pub fn new(kvm: &crate::vstate::kvm::Kvm) -> Result<ArchVm, VmError> {
64-
let common = Self::create_common(kvm)?;
67+
pub fn new(kvm: &crate::vstate::kvm::Kvm, secret_free: bool) -> Result<ArchVm, VmError> {
68+
let common = Self::create_common(kvm, secret_free)?;
6569

6670
let msrs_to_save = kvm.msrs_to_save().map_err(ArchVmError::GetMsrsToSave)?;
6771

src/vmm/src/builder.rs

Lines changed: 14 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -144,11 +144,12 @@ fn create_vmm_and_vcpus(
144144
event_manager: &mut EventManager,
145145
vcpu_count: u8,
146146
kvm_capabilities: Vec<KvmCapability>,
147+
secret_free: bool,
147148
) -> Result<(Vmm, Vec<Vcpu>), VmmError> {
148149
let kvm = Kvm::new(kvm_capabilities)?;
149150
// Set up Kvm Vm and register memory regions.
150151
// Build custom CPU config if a custom template is provided.
151-
let mut vm = Vm::new(&kvm)?;
152+
let mut vm = Vm::new(&kvm, secret_free)?;
152153

153154
let resource_allocator = ResourceAllocator::new()?;
154155

@@ -239,6 +240,7 @@ pub fn build_microvm_for_boot(
239240
event_manager,
240241
vm_resources.machine_config.vcpu_count,
241242
cpu_template.kvm_capabilities.clone(),
243+
vm_resources.machine_config.secret_free,
242244
)?;
243245

244246
vmm.vm
@@ -248,7 +250,7 @@ pub fn build_microvm_for_boot(
248250
let entry_point = load_kernel(
249251
MaybeBounce::new(
250252
boot_config.kernel_file.try_clone().unwrap(),
251-
vm_resources.machine_config.secret_free,
253+
vmm.vm.secret_free(),
252254
),
253255
vmm.vm.guest_memory(),
254256
)?;
@@ -261,7 +263,7 @@ pub fn build_microvm_for_boot(
261263

262264
Some(InitrdConfig::from_reader(
263265
vmm.vm.guest_memory(),
264-
MaybeBounce::new(initrd_file.as_fd(), vm_resources.machine_config.secret_free),
266+
MaybeBounce::new(initrd_file.as_fd(), vmm.vm.secret_free()),
265267
u64_to_usize(size),
266268
)?)
267269
}
@@ -296,24 +298,16 @@ pub fn build_microvm_for_boot(
296298
&mut boot_cmdline,
297299
vm_resources.block.devices.iter(),
298300
event_manager,
299-
vm_resources.machine_config.secret_free,
300301
)?;
301302
attach_net_devices(
302303
&mut vmm,
303304
&mut boot_cmdline,
304305
vm_resources.net_builder.iter(),
305306
event_manager,
306-
vm_resources.machine_config.secret_free,
307307
)?;
308308

309309
if let Some(unix_vsock) = vm_resources.vsock.get() {
310-
attach_unixsock_vsock_device(
311-
&mut vmm,
312-
&mut boot_cmdline,
313-
unix_vsock,
314-
event_manager,
315-
vm_resources.machine_config.secret_free,
316-
)?;
310+
attach_unixsock_vsock_device(&mut vmm, &mut boot_cmdline, unix_vsock, event_manager)?;
317311
}
318312

319313
if let Some(entropy) = vm_resources.entropy.get() {
@@ -469,6 +463,7 @@ pub fn build_microvm_from_snapshot(
469463
event_manager,
470464
vm_resources.machine_config.vcpu_count,
471465
microvm_state.kvm_state.kvm_cap_modifiers.clone(),
466+
false,
472467
)
473468
.map_err(StartMicrovmError::Internal)?;
474469

@@ -685,11 +680,10 @@ fn attach_virtio_device<T: 'static + VirtioDevice + MutEventSubscriber + Debug>(
685680
device: Arc<Mutex<T>>,
686681
cmdline: &mut LoaderKernelCmdline,
687682
is_vhost_user: bool,
688-
secret_free: bool,
689683
) -> Result<(), MmioError> {
690684
event_manager.add_subscriber(device.clone());
691685

692-
if secret_free {
686+
if vmm.vm.secret_free() {
693687
device.lock().unwrap().force_userspace_bounce_buffers();
694688
}
695689

@@ -748,7 +742,6 @@ fn attach_entropy_device(
748742
entropy_device.clone(),
749743
cmdline,
750744
false,
751-
false,
752745
)
753746
}
754747

@@ -757,7 +750,6 @@ fn attach_block_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Block>>> + Debug>(
757750
cmdline: &mut LoaderKernelCmdline,
758751
blocks: I,
759752
event_manager: &mut EventManager,
760-
secret_free: bool,
761753
) -> Result<(), StartMicrovmError> {
762754
for block in blocks {
763755
let (id, is_vhost_user) = {
@@ -782,7 +774,6 @@ fn attach_block_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Block>>> + Debug>(
782774
block.clone(),
783775
cmdline,
784776
is_vhost_user,
785-
secret_free,
786777
)?;
787778
}
788779
Ok(())
@@ -793,20 +784,11 @@ fn attach_net_devices<'a, I: Iterator<Item = &'a Arc<Mutex<Net>>> + Debug>(
793784
cmdline: &mut LoaderKernelCmdline,
794785
net_devices: I,
795786
event_manager: &mut EventManager,
796-
secret_free: bool,
797787
) -> Result<(), StartMicrovmError> {
798788
for net_device in net_devices {
799789
let id = net_device.lock().expect("Poisoned lock").id().clone();
800790
// The device mutex mustn't be locked here otherwise it will deadlock.
801-
attach_virtio_device(
802-
event_manager,
803-
vmm,
804-
id,
805-
net_device.clone(),
806-
cmdline,
807-
false,
808-
secret_free,
809-
)?;
791+
attach_virtio_device(event_manager, vmm, id, net_device.clone(), cmdline, false)?;
810792
}
811793
Ok(())
812794
}
@@ -816,19 +798,10 @@ fn attach_unixsock_vsock_device(
816798
cmdline: &mut LoaderKernelCmdline,
817799
unix_vsock: &Arc<Mutex<Vsock<VsockUnixBackend>>>,
818800
event_manager: &mut EventManager,
819-
secret_free: bool,
820801
) -> Result<(), MmioError> {
821802
let id = String::from(unix_vsock.lock().expect("Poisoned lock").id());
822803
// The device mutex mustn't be locked here otherwise it will deadlock.
823-
attach_virtio_device(
824-
event_manager,
825-
vmm,
826-
id,
827-
unix_vsock.clone(),
828-
cmdline,
829-
false,
830-
secret_free,
831-
)
804+
attach_virtio_device(event_manager, vmm, id, unix_vsock.clone(), cmdline, false)
832805
}
833806

834807
fn attach_balloon_device(
@@ -839,15 +812,7 @@ fn attach_balloon_device(
839812
) -> Result<(), MmioError> {
840813
let id = String::from(balloon.lock().expect("Poisoned lock").id());
841814
// The device mutex mustn't be locked here otherwise it will deadlock.
842-
attach_virtio_device(
843-
event_manager,
844-
vmm,
845-
id,
846-
balloon.clone(),
847-
cmdline,
848-
false,
849-
false,
850-
)
815+
attach_virtio_device(event_manager, vmm, id, balloon.clone(), cmdline, false)
851816
}
852817

853818
// Adds `O_NONBLOCK` to the stdout flags.
@@ -1023,7 +988,6 @@ pub(crate) mod tests {
1023988
cmdline,
1024989
block_dev_configs.devices.iter(),
1025990
event_manager,
1026-
false,
1027991
)
1028992
.unwrap();
1029993
block_files
@@ -1038,7 +1002,7 @@ pub(crate) mod tests {
10381002
let mut net_builder = NetBuilder::new();
10391003
net_builder.build(net_config).unwrap();
10401004

1041-
let res = attach_net_devices(vmm, cmdline, net_builder.iter(), event_manager, false);
1005+
let res = attach_net_devices(vmm, cmdline, net_builder.iter(), event_manager);
10421006
res.unwrap();
10431007
}
10441008

@@ -1059,7 +1023,7 @@ pub(crate) mod tests {
10591023
Arc::new(Mutex::new(mmds)),
10601024
);
10611025

1062-
attach_net_devices(vmm, cmdline, net_builder.iter(), event_manager, false).unwrap();
1026+
attach_net_devices(vmm, cmdline, net_builder.iter(), event_manager).unwrap();
10631027
}
10641028

10651029
pub(crate) fn insert_vsock_device(
@@ -1072,7 +1036,7 @@ pub(crate) mod tests {
10721036
let vsock = VsockBuilder::create_unixsock_vsock(vsock_config).unwrap();
10731037
let vsock = Arc::new(Mutex::new(vsock));
10741038

1075-
attach_unixsock_vsock_device(vmm, cmdline, &vsock, event_manager, false).unwrap();
1039+
attach_unixsock_vsock_device(vmm, cmdline, &vsock, event_manager).unwrap();
10761040

10771041
assert!(
10781042
vmm.mmio_device_manager

src/vmm/src/device_manager/mmio.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -659,7 +659,7 @@ mod tests {
659659
let start_addr2 = GuestAddress(0x1000);
660660
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
661661
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
662-
let mut vm = Vm::new(&kvm).unwrap();
662+
let mut vm = Vm::new(&kvm, false).unwrap();
663663
vm.register_memory_regions(guest_mem).unwrap();
664664
let mut device_manager = MMIODeviceManager::new();
665665
let mut resource_allocator = ResourceAllocator::new().unwrap();
@@ -690,7 +690,7 @@ mod tests {
690690
let start_addr2 = GuestAddress(0x1000);
691691
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
692692
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
693-
let mut vm = Vm::new(&kvm).unwrap();
693+
let mut vm = Vm::new(&kvm, false).unwrap();
694694
vm.register_memory_regions(guest_mem).unwrap();
695695
let mut device_manager = MMIODeviceManager::new();
696696
let mut resource_allocator = ResourceAllocator::new().unwrap();
@@ -746,7 +746,7 @@ mod tests {
746746
let start_addr2 = GuestAddress(0x1000);
747747
let guest_mem = multi_region_mem_raw(&[(start_addr1, 0x1000), (start_addr2, 0x1000)]);
748748
let kvm = Kvm::new(vec![]).expect("Cannot create Kvm");
749-
let mut vm = Vm::new(&kvm).unwrap();
749+
let mut vm = Vm::new(&kvm, false).unwrap();
750750
vm.register_memory_regions(guest_mem).unwrap();
751751

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

0 commit comments

Comments
 (0)