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 <kadler@cloudflare.com>
Signed-off-by: Keith Adler <kadler@cloudflare.com>
Co-authored-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Alex Orozco <aorozco@google.com>
Signed-off-by: Ruben Hakobyan <hruben@meta.com>
This commit is contained in:
Ruben Hakobyan
2026-04-07 18:14:43 -07:00
committed by Rob Bradford
parent 75ed2c9f90
commit 883ca3feb2
2 changed files with 25 additions and 0 deletions

View File

@@ -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")]

View File

@@ -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<Mutex<MemoryManager>>) -> 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<Mutex<cpu::CpuManager>>,
#[cfg(feature = "sev_snp")] host_data: &Option<String>,
) -> Result<EntryPoint> {
// 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,