mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2026-08-05 02:19:16 +00:00
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:
committed by
Rob Bradford
parent
c31f5d4998
commit
8ee0a07ab1
@@ -819,6 +819,7 @@ pub fn configure_vcpu(
|
||||
cpu_vendor: CpuVendor,
|
||||
topology: (u16, u16, u16, u16),
|
||||
nested: bool,
|
||||
setup_registers: bool,
|
||||
) -> super::Result<()> {
|
||||
let x2apic_id = get_x2apic_id(id, Some(topology));
|
||||
|
||||
@@ -892,17 +893,19 @@ pub fn configure_vcpu(
|
||||
|
||||
regs::setup_msrs(vcpu).map_err(Error::MsrsConfiguration)?;
|
||||
if let Some((kernel_entry_point, guest_memory)) = boot_setup {
|
||||
regs::setup_regs(vcpu, kernel_entry_point).map_err(Error::RegsConfiguration)?;
|
||||
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
||||
if setup_registers {
|
||||
regs::setup_regs(vcpu, kernel_entry_point).map_err(Error::RegsConfiguration)?;
|
||||
|
||||
// CPUs are required (by Intel sdm spec) to boot in x2apic mode if any
|
||||
// of the apic IDs is larger than 255. Experimentally, the Linux kernel
|
||||
// does not recognize the last vCPU if x2apic is not enabled when
|
||||
// there are 256 vCPUs in a flat hierarchy (i.e. max x2apic ID is 255),
|
||||
// so we need to enable x2apic in this case as well.
|
||||
let enable_x2_apic_mode = get_max_x2apic_id(topology) > MAX_SUPPORTED_CPUS_LEGACY;
|
||||
regs::setup_sregs(&guest_memory.memory(), vcpu, enable_x2_apic_mode)
|
||||
.map_err(Error::SregsConfiguration)?;
|
||||
// CPUs are required (by Intel sdm spec) to boot in x2apic mode if any
|
||||
// of the apic IDs is larger than 255. Experimentally, the Linux kernel
|
||||
// does not recognize the last vCPU if x2apic is not enabled when
|
||||
// there are 256 vCPUs in a flat hierarchy (i.e. max x2apic ID is 255),
|
||||
// so we need to enable x2apic in this case as well.
|
||||
let enable_x2_apic_mode = get_max_x2apic_id(topology) > MAX_SUPPORTED_CPUS_LEGACY;
|
||||
regs::setup_sregs(&guest_memory.memory(), vcpu, enable_x2_apic_mode)
|
||||
.map_err(Error::SregsConfiguration)?;
|
||||
}
|
||||
regs::setup_fpu(vcpu).map_err(Error::FpuConfiguration)?;
|
||||
}
|
||||
interrupts::set_lint(vcpu).map_err(|e| Error::LocalIntConfiguration(e.into()))?;
|
||||
Ok(())
|
||||
|
||||
@@ -64,7 +64,7 @@ pub use vm::{
|
||||
|
||||
pub use crate::hypervisor::{Hypervisor, HypervisorError};
|
||||
|
||||
#[derive(Debug, Copy, Clone)]
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum HypervisorType {
|
||||
#[cfg(feature = "kvm")]
|
||||
Kvm,
|
||||
|
||||
@@ -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")]
|
||||
|
||||
@@ -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)?;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user