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 <tbarrett@crusoeenergy.com>
This commit is contained in:
Thomas Barrett 2024-01-26 18:43:45 +00:00 committed by Bo Chen
parent 1617736937
commit 5ec47d4883

View File

@ -830,10 +830,6 @@ pub fn configure_vcpu(
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x8000_001e, Some(0), CpuidReg::EAX, x2apic_id); 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 // Set ApicId in cpuid for each vcpu
// SAFETY: get host cpuid when eax=1 // SAFETY: get host cpuid when eax=1
let mut cpu_ebx = unsafe { core::arch::x86_64::__cpuid(1) }.ebx; 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; cpu_ebx |= x2apic_id << 24;
CpuidPatch::set_cpuid_reg(&mut cpuid, 0x1, None, CpuidReg::EBX, cpu_ebx); 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 // The TSC frequency CPUID leaf should not be included when running with HyperV emulation
if !kvm_hyperv { if !kvm_hyperv {
if let Some(tsc_khz) = vcpu.tsc_khz().map_err(Error::GetTscFrequency)? { 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 core_width = (8 - (cores_per_die - 1).leading_zeros()) + thread_width;
let die_width = (8 - (dies_per_package - 1).leading_zeros()) + core_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 // CPU Topology leaf 0xb
CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width); CpuidPatch::set_cpuid_reg(cpuid, 0xb, Some(0), CpuidReg::EAX, thread_width);
CpuidPatch::set_cpuid_reg( CpuidPatch::set_cpuid_reg(