diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index 17bae5f5a..41ea7514e 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -44,6 +44,8 @@ pub const MAX_SUPPORTED_CPUS_LEGACY: u32 = 254; #[cfg(feature = "kvm")] const TSC_DEADLINE_TIMER_ECX_BIT: u8 = 24; // tsc deadline timer ecx bit. const HYPERVISOR_ECX_BIT: u8 = 31; // Hypervisor ecx bit. +const VMX_ECX_BIT: u8 = 5; // VMX for Intel +const SVM_ECX_BIT: u8 = 2; // SVM for AMD const MTRR_EDX_BIT: u8 = 12; // Hypervisor ecx bit. const INVARIANT_TSC_EDX_BIT: u8 = 8; // Invariant TSC bit on 0x8000_0007 EDX const AMX_BF16: u8 = 22; // AMX tile computation on bfloat16 numbers @@ -806,6 +808,7 @@ pub fn generate_common_cpuid( Ok(cpuid) } +#[allow(clippy::too_many_arguments)] pub fn configure_vcpu( vcpu: &dyn hypervisor::Vcpu, id: u32, @@ -814,6 +817,7 @@ pub fn configure_vcpu( kvm_hyperv: bool, cpu_vendor: CpuVendor, topology: (u16, u16, u16, u16), + nested: bool, ) -> super::Result<()> { let x2apic_id = get_x2apic_id(id, Some(topology)); @@ -832,6 +836,17 @@ pub fn configure_vcpu( entry.ebx &= 0xffffff; entry.ebx |= x2apic_id << 24; apic_id_patched = true; + if !nested { + // Disable nested virtualization for Intel + entry.ecx &= !(1 << VMX_ECX_BIT); + } + break; + } + if entry.function == 0x8000_0001 { + if !nested { + // Disable the nested virtualization for AMD + entry.ecx &= !(1 << SVM_ECX_BIT); + } break; } } diff --git a/vmm/src/config.rs b/vmm/src/config.rs index c5a74d5e4..3e41a83ba 100644 --- a/vmm/src/config.rs +++ b/vmm/src/config.rs @@ -659,6 +659,14 @@ impl CpusConfig { .map_err(Error::ParseCpus)? .is_none_or(|toggle| toggle.0); + // Nested virtualization is always turned on for aarch64 and riscv64 + // TODO: revisit this when nested support can be turned of on these architectures + #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))] + if !nested { + return Err(Error::ParseCpus(OptionParserError::InvalidValue( + "nested=off is not supported on aarch64 and riscv64 architectures".to_string(), + ))); + } Ok(CpusConfig { boot_vcpus, max_vcpus, diff --git a/vmm/src/cpu.rs b/vmm/src/cpu.rs index dfb407809..b219265f2 100644 --- a/vmm/src/cpu.rs +++ b/vmm/src/cpu.rs @@ -455,6 +455,7 @@ impl Vcpu { #[cfg(target_arch = "x86_64")] cpuid: Vec, #[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, ) -> Result<()> { #[cfg(target_arch = "aarch64")] { @@ -475,6 +476,7 @@ impl Vcpu { kvm_hyperv, self.vendor, topology, + nested, ) .map_err(Error::VcpuConfiguration)?; @@ -995,6 +997,7 @@ impl CpuManager { self.cpuid.clone(), self.config.kvm_hyperv, topology, + self.config.nested, )?; #[cfg(target_arch = "aarch64")]