From 5ec47d4883666387ea58d2d9124838c2639d1e37 Mon Sep 17 00:00:00 2001 From: Thomas Barrett Date: Fri, 26 Jan 2024 18:43:45 +0000 Subject: [PATCH] arch: x86_64: enable HTT flag When the HTT flag CPUID.1.EDX[HTT] is 0, it indicates that there is only a single logical processor in the package. When HTT is 1, it indicates that CPUID.1.EBX[23:16] contains the number of logical processors in the package. When this information is not included in CPUID leaf 0x1, some cpu topology enumeration software such as hwloc are known to crash. Signed-off-by: Thomas Barrett --- arch/src/x86_64/mod.rs | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/arch/src/x86_64/mod.rs b/arch/src/x86_64/mod.rs index b90095ef7..08641af17 100644 --- a/arch/src/x86_64/mod.rs +++ b/arch/src/x86_64/mod.rs @@ -830,10 +830,6 @@ pub fn configure_vcpu( CpuidPatch::set_cpuid_reg(&mut cpuid, 0x8000_001e, Some(0), CpuidReg::EAX, x2apic_id); } - if let Some(t) = topology { - update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id); - } - // Set ApicId in cpuid for each vcpu // SAFETY: get host cpuid when eax=1 let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx; @@ -841,6 +837,10 @@ pub fn configure_vcpu( cpu_ebx |= x2apic_id << 24; CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx); + if let Some(t) = topology { + update_cpuid_topology(&mut cpuid, t.0, t.1, t.2, cpu_vendor, id); + } + // The TSC frequency CPUID leaf should not be included when running with HyperV emulation if !kvm_hyperv { if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? { @@ -1277,6 +1277,15 @@ fn update_cpuid_topology( let core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width; let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_width; + let mut cpu_ebx = CpuidPatch::get_cpuid_reg(cpuid, 0x1, None, CpuidReg::EBX).unwrap_or(0); + cpu_ebx |= ((dies_per_package as u32) * (cores_per_die as u32) * (threads_per_core as u32)) + & 0xff << 16; + CpuidPatch::set_cpuid_reg(cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx); + + let mut cpu_edx = CpuidPatch::get_cpuid_reg(cpuid, 0x1, None, CpuidReg::EDX).unwrap_or(0); + cpu_edx |= 1 << 28; + CpuidPatch::set_cpuid_reg(cpuid, 0x1, None, CpuidReg::EDX, cpu_edx); + // CPU Topology leaf 0xb CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width); CpuidPatch::set_cpuid_reg(