Prior to the topology parsing rewrite and the switchover to the new parsing logic for AMD processors in commit c749ce393b8f ("x86/cpu: Use common topology code for AMD"), the "initial_apicid" on these platforms was: - First initialized to the LocalApicId from CPUID leaf 0x1 EBX[31:24]. - Then overwritten by the ExtendedLocalApicId in CPUID leaf 0xb EDX[31:0] on processors that supported topoext. With the new parsing flow introduced in commit f7fb3b2dd92c ("x86/cpu: Provide an AMD/HYGON specific topology parser"), parse_8000_001e() now unconditionally overwrites the "initial_apicid" already parsed during cpu_parse_topology_ext(). Although this has not been a problem on baremetal platforms, on virtualized AMD guests that feature more than 255 cores, QEMU 0's out the CPUID leaf 0x8000001e on CPUs with "CoreID" > 255 to prevent collision of these IDs in EBX[7:0] which can only represent a maximum of 255 cores [1]. This results in the following FW_BUG being logged when booting a guest with more than 255 cores: [Firmware Bug]: CPU 512: APIC ID mismatch. CPUID: 0x0000 APIC: 0x0200 Rely on the APICID parsed during cpu_parse_topology_ext() from CPUID leaf 0x80000026 or 0xb and only use the APICID from leaf 0x8000001e if cpu_parse_topology_ext() failed (has_topoext is false). On platforms that support the 0xb leaf (Zen2 or later, AMD guests on QEMU) or the extended leaf 0x80000026 (Zen4 or later), the "initial_apicid" is now set to the value parsed from EDX[31:0]. On older AMD/Hygon platforms that does not support the 0xb leaf but supports the TOPOEXT extension (Fam 0x15, 0x16, 0x17[Zen1], and Hygon), the current behavior is retained where "initial_apicid" is set using the 0x8000001e leaf. Link: https://github.com/qemu/qemu/commit/35ac5dfbcaa4b [1] Debugged-by: Naveen N Rao (AMD) Debugged-by: Sairaj Kodilkar Fixes: c749ce393b8f ("x86/cpu: Use common topology code for AMD") Tested-by: Naveen N Rao (AMD) Signed-off-by: K Prateek Nayak --- Changelog v2..v3: o No changes. --- arch/x86/kernel/cpu/topology_amd.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index bb00dc6433eb..ac0ba8495eec 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -81,20 +81,28 @@ static bool parse_8000_001e(struct topo_scan *tscan, bool has_topoext) cpuid_leaf(0x8000001e, &leaf); - tscan->c->topo.initial_apicid = leaf.ext_apic_id; - - /* - * If leaf 0xb is available, then the domain shifts are set - * already and nothing to do here. Only valid for family >= 0x17. - */ - if (!has_topoext && tscan->c->x86 >= 0x17) { + if (!has_topoext) { /* - * Leaf 0x80000008 set the CORE domain shift already. - * Update the SMT domain, but do not propagate it. + * Prefer initial_apicid parsed from XTOPOLOGY leaf + * 0x8000026 or 0xb if available. Otherwise prefer the + * one from leaf 0x8000001e over 0x1. */ - unsigned int nthreads = leaf.core_nthreads + 1; + tscan->c->topo.initial_apicid = leaf.ext_apic_id; - topology_update_dom(tscan, TOPO_SMT_DOMAIN, get_count_order(nthreads), nthreads); + /* + * If XTOPOLOGY leaf is available, then the domain shifts are set + * already and nothing to do here. Only valid for family >= 0x17. + */ + if (tscan->c->x86 >= 0x17) { + /* + * Leaf 0x80000008 set the CORE domain shift already. + * Update the SMT domain, but do not propagate it. + */ + unsigned int nthreads = leaf.core_nthreads + 1; + + topology_update_dom(tscan, TOPO_SMT_DOMAIN, + get_count_order(nthreads), nthreads); + } } store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id); -- 2.34.1