arch: vmm: disable nested virtualization if needed

User can now disable nested virtualization for Intel and AMD
if configured by the CLI.

Signed-off-by: Muminul Islam <muislam@microsoft.com>
This commit is contained in:
Muminul Islam
2025-10-27 16:28:21 -07:00
committed by Rob Bradford
parent d8360ddc8e
commit 658a7f9175
3 changed files with 26 additions and 0 deletions

View File

@@ -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;
}
}

View File

@@ -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,

View File

@@ -455,6 +455,7 @@ impl Vcpu {
#[cfg(target_arch = "x86_64")] cpuid: Vec<CpuIdEntry>,
#[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")]