From 883ca3feb2965c5fc9742498d826fddd673a1157 Mon Sep 17 00:00:00 2001 From: Ruben Hakobyan Date: Tue, 7 Apr 2026 18:14:43 -0700 Subject: [PATCH] vmm: reserve memory regions for stage0 and VMSA on KVM SEV-SNP A bootloader/firmware (e.g. stage0) and the VMSA page require dedicated memory regions at fixed GPAs. Add reserve_region_for_stage0() to allocate these regions before IGVM loading begins: - Stage0 at GPA 0xffc0_0000 (4 MB) - VMSA page at GPA 0xffff_ffff_f000 (4 KB) These reservations are KVM-only; MSHV handles stage0/VMSA placement through its own isolated import path. Also add fw_cfg device creation and SYS_statx to the vCPU seccomp allowlist (needed by stage0's file access pattern). Co-authored-by: Keith Adler Signed-off-by: Keith Adler Co-authored-by: Alex Orozco Signed-off-by: Alex Orozco Signed-off-by: Ruben Hakobyan --- vmm/src/seccomp_filters.rs | 1 + vmm/src/vm.rs | 24 ++++++++++++++++++++++++ 2 files changed, 25 insertions(+) diff --git a/vmm/src/seccomp_filters.rs b/vmm/src/seccomp_filters.rs index bc17cde4e..877ea907d 100644 --- a/vmm/src/seccomp_filters.rs +++ b/vmm/src/seccomp_filters.rs @@ -917,6 +917,7 @@ fn vcpu_thread_rules( (libc::SYS_sendto, vec![]), (libc::SYS_shutdown, vec![]), (libc::SYS_sigaltstack, vec![]), + (libc::SYS_statx, vec![]), (libc::SYS_tgkill, vec![]), (libc::SYS_tkill, vec![]), #[cfg(target_arch = "x86_64")] diff --git a/vmm/src/vm.rs b/vmm/src/vm.rs index 74ca6a7ed..600689669 100644 --- a/vmm/src/vm.rs +++ b/vmm/src/vm.rs @@ -46,6 +46,10 @@ use gdbstub_arch::aarch64::reg::AArch64CoreRegs as CoreRegs; use gdbstub_arch::x86::reg::X86_64CoreRegs as CoreRegs; #[cfg(target_arch = "aarch64")] use hypervisor::arch::aarch64::regs::AARCH64_PMU_IRQ; +#[cfg(all(feature = "kvm", feature = "sev_snp"))] +use hypervisor::kvm::{ + BOOTLOADER_SIZE, BOOTLOADER_START, KVM_VMSA_PAGE_ADDRESS, KVM_VMSA_PAGE_SIZE, +}; use hypervisor::{HypervisorVmConfig, HypervisorVmError, VmOps}; #[cfg(feature = "igvm")] use igvm::IgvmFile; @@ -1040,6 +1044,9 @@ impl Vm { ) .map_err(Error::DeviceManager)?; + #[cfg(feature = "fw_cfg")] + Self::create_fw_cfg_if_enabled(config, device_manager)?; + Ok(load_payload_handle) } @@ -1510,6 +1517,16 @@ impl Vm { Ok(EntryPoint { entry_addr }) } + #[cfg(all(feature = "kvm", feature = "sev_snp"))] + fn reserve_bootloader_regions(memory_manager: &Arc>) -> Result<()> { + let mut mm = memory_manager.lock().unwrap(); + mm.add_ram_region(BOOTLOADER_START, BOOTLOADER_SIZE) + .map_err(Error::MemoryManager)?; + mm.add_ram_region(KVM_VMSA_PAGE_ADDRESS, KVM_VMSA_PAGE_SIZE) + .map_err(Error::MemoryManager)?; + Ok(()) + } + #[cfg(feature = "igvm")] #[allow(clippy::needless_pass_by_value)] fn load_igvm( @@ -1518,6 +1535,13 @@ impl Vm { cpu_manager: Arc>, #[cfg(feature = "sev_snp")] host_data: &Option, ) -> Result { + // Only reserve bootloader/VMSA regions for KVM + SEV-SNP; other hypervisors + // (e.g. MSHV) handle this through their own import path. + #[cfg(all(feature = "kvm", feature = "sev_snp"))] + if cpu_manager.lock().unwrap().sev_snp_enabled() { + Self::reserve_bootloader_regions(&memory_manager)?; + } + let res = igvm_loader::load_igvm( igvm_file, memory_manager,