arch, hypervisor, vmm: skip vcpu setup when using igvm and kvm

When we use igvm + kvm, we setup the regs and sregs using the cpuid
page. We still need to setup the fpu in configure_vcpu.

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 08:05:30 -07:00
committed by Rob Bradford
parent c31f5d4998
commit 8ee0a07ab1
4 changed files with 62 additions and 24 deletions

View File

@@ -546,6 +546,7 @@ impl Vcpu {
#[cfg(target_arch = "x86_64")] kvm_hyperv: bool,
#[cfg(target_arch = "x86_64")] topology: (u16, u16, u16, u16),
#[cfg(target_arch = "x86_64")] nested: bool,
#[cfg(feature = "igvm")] igvm_enabled: bool,
) -> Result<()> {
#[cfg(target_arch = "aarch64")]
{
@@ -558,17 +559,32 @@ impl Vcpu {
.map_err(Error::VcpuConfiguration)?;
info!("Configuring vCPU: cpu_id = {}", self.id);
#[cfg(target_arch = "x86_64")]
arch::configure_vcpu(
self.vcpu.as_ref(),
self.id,
boot_setup,
cpuid,
kvm_hyperv,
self.vendor,
topology,
nested,
)
.map_err(Error::VcpuConfiguration)?;
{
// When IGVM is enabled, skip standard register setup here — the IGVM
// loader populates vCPU registers from the VMSA via set_sev_control_register
// (currently KVM-specific; MSHV handles this through its own import path).
// igvm_enabled is kept as an explicit flag rather than derived from sev_snp
// state because IGVM could theoretically be used independently of SEV-SNP.
cfg_if::cfg_if! {
if #[cfg(feature = "igvm")] {
let setup_registers = !igvm_enabled;
} else {
let setup_registers = true;
}
}
arch::configure_vcpu(
self.vcpu.as_ref(),
self.id,
boot_setup,
cpuid,
kvm_hyperv,
self.vendor,
topology,
nested,
setup_registers,
)
.map_err(Error::VcpuConfiguration)?;
}
Ok(())
}
@@ -697,6 +713,8 @@ pub struct CpuManager {
sev_snp_enabled: bool,
// State of the core scheduling group leader election (VM mode).
core_scheduling_group_leader: Arc<AtomicI32>,
#[cfg(feature = "igvm")]
igvm_enabled: bool,
}
/// State of the core scheduling group leader election for VM-wide cookie
@@ -826,6 +844,7 @@ impl CpuManager {
#[cfg(feature = "tdx")] tdx_enabled: bool,
numa_nodes: &NumaNodes,
#[cfg(feature = "sev_snp")] sev_snp_enabled: bool,
#[cfg(feature = "igvm")] igvm_enabled: bool,
) -> Result<Arc<Mutex<CpuManager>>> {
if config.max_vcpus > hypervisor.get_max_vcpus() {
return Err(Error::MaximumVcpusExceeded(
@@ -902,6 +921,8 @@ impl CpuManager {
core_scheduling_group_leader: Arc::new(AtomicI32::new(
CoreSchedulingLeader::Initial as i32,
)),
#[cfg(feature = "igvm")]
igvm_enabled,
})))
}
@@ -980,8 +1001,10 @@ impl CpuManager {
vcpu: &mut Vcpu,
boot_setup: Option<(EntryPoint, &GuestMemoryAtomic<GuestMemoryMmap>)>,
) -> Result<()> {
#[cfg(feature = "sev_snp")]
if self.sev_snp_enabled {
#[cfg(all(feature = "sev_snp", feature = "mshv"))]
if self.sev_snp_enabled
&& self.hypervisor.hypervisor_type() == hypervisor::HypervisorType::Mshv
{
if let Some((kernel_entry_point, _)) = boot_setup {
vcpu.set_sev_control_register(
kernel_entry_point.entry_addr.0 / crate::igvm::HV_PAGE_SIZE,
@@ -1022,6 +1045,8 @@ impl CpuManager {
self.config.kvm_hyperv,
topology,
self.config.nested,
#[cfg(feature = "igvm")]
self.igvm_enabled,
)?;
#[cfg(target_arch = "aarch64")]

View File

@@ -738,6 +738,14 @@ impl Vm {
let tdx_enabled = config.lock().unwrap().is_tdx_enabled();
#[cfg(feature = "sev_snp")]
let sev_snp_enabled = config.lock().unwrap().is_sev_snp_enabled();
#[cfg(feature = "igvm")]
let igvm_enabled = config
.lock()
.unwrap()
.payload
.as_ref()
.and_then(|p| p.igvm.as_ref())
.is_some();
let cpus_config = config.lock().unwrap().cpus.clone();
let cpu_manager = cpu::CpuManager::new(
@@ -755,6 +763,8 @@ impl Vm {
numa_nodes,
#[cfg(feature = "sev_snp")]
sev_snp_enabled,
#[cfg(feature = "igvm")]
igvm_enabled,
)
.map_err(Error::CpuManager)?;