public inbox for regressions@lists.linux.dev
 help / color / mirror / Atom feed
* AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
@ 2025-10-24 18:46 Michal Pecio
  2025-10-24 21:32 ` Yazen Ghannam
  0 siblings, 1 reply; 8+ messages in thread
From: Michal Pecio @ 2025-10-24 18:46 UTC (permalink / raw)
  To: x86
  Cc: regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Yazen Ghannam, Mario Limonciello, Eric DeVolder

Hi,

This report is related to discussion here:
https://lore.kernel.org/all/20251022011610.60d0ba6e.michal.pecio@gmail.com/

Commit bc7b2e629e0c ("x86/amd_nb: Use topology info to get AMD node
count") bails out if it can't find the NB of each node reportedy by
topology. Then NB features like EDAC or GART IOMMU aren't available.

Which was maybe not a bad idea, nobody expects those things to work
on selected nodes only. (I think?) But it relies on the optimistic
assumption that topology knows the true number of nodes.

Today I tested 5 older AMD64 systems with socket 754/AM2+/AM3/AM3+
on MSI/ASUS motherboards. *All* of them report more than one node if
the CPU has fewer cores than supported by the BIOS.

(I also have one AM4 system which is OK, but can't speak for others).

This is due to peculiarity of their MADT tables - they report as many
LAPICs as the BIOS can support and excess LAPICs are simply disabled.
FWIW, it's also a pattern that disabled APIC IDs have 0x80 bit set.

The kernel counts this as "hotpluggable CPUs", since supposedly it's
indistinguishable from actual multi-socket systems before ACPI 6.3,
where the "online capable" flag was added to disambiguate hotplug and
nonexistent but theoretically supported CPUs.

Or at least that's what commit fed8d8773b8e ("x86/acpi/boot: Correct
acpi_is_processor_usable() check") seems to imply.

On pre-ACPI 6.3 systems those disabled LAPICs inflate topology size
and result in breakage on recent kernels. A few examples below give
an idea what those MADTs look like and how the kernel reads them.

Regards,
Michal


Athlon 3000+ on S754:

[02Fh 0047 001h]               Local Apic ID : 00
[030h 0048 004h]       Flags (decoded below) : 00000001	# enabled
--
[037h 0055 001h]               Local Apic ID : 81
[038h 0056 004h]       Flags (decoded below) : 00000000

[    0.027690] CPU topo: Max. logical packages:   2
[    0.027691] CPU topo: Max. logical dies:       2
[    0.027692] CPU topo: Max. dies per package:   1
[    0.027703] CPU topo: Max. threads per core:   1
[    0.027704] CPU topo: Num. cores per package:     1
[    0.027705] CPU topo: Num. threads per package:   1
[    0.027706] CPU topo: Allowing 1 present CPUs plus 1 hotplug CPUs

Athlon II X2 250 on AM3+:

[02Fh 0047 001h]               Local Apic ID : 00
[030h 0048 004h]       Flags (decoded below) : 00000001 # enabled
--
[037h 0055 001h]               Local Apic ID : 01
[038h 0056 004h]       Flags (decoded below) : 00000001 # enabled
--
[03Fh 0063 001h]               Local Apic ID : 82
[040h 0064 004h]       Flags (decoded below) : 00000000
--
[047h 0071 001h]               Local Apic ID : 83
[048h 0072 004h]       Flags (decoded below) : 00000000
--
[04Fh 0079 001h]               Local Apic ID : 84
[050h 0080 004h]       Flags (decoded below) : 00000000
--
[057h 0087 001h]               Local Apic ID : 85
[058h 0088 004h]       Flags (decoded below) : 00000000
--
[05Fh 0095 001h]               Local Apic ID : 86
[060h 0096 004h]       Flags (decoded below) : 00000000
--
[067h 0103 001h]               Local Apic ID : 87
[068h 0104 004h]       Flags (decoded below) : 00000000

[    0.147372] CPU topo: Max. logical packages:   3 # not sure why not 4
[    0.147372] CPU topo: Max. logical dies:       3
[    0.147373] CPU topo: Max. dies per package:   1
[    0.147379] CPU topo: Max. threads per core:   1
[    0.147379] CPU topo: Num. cores per package:     2
[    0.147380] CPU topo: Num. threads per package:   2
[    0.147381] CPU topo: Allowing 2 present CPUs plus 6 hotplug CPUs

Phenom II X4 965 on AM3:

[02Fh 0047   1]                Local Apic ID : 00
[030h 0048   4]        Flags (decoded below) : 00000001 # enabled
--
[037h 0055   1]                Local Apic ID : 01
[038h 0056   4]        Flags (decoded below) : 00000001 # enabled
--
[03Fh 0063   1]                Local Apic ID : 02
[040h 0064   4]        Flags (decoded below) : 00000001 # enabled
--
[047h 0071   1]                Local Apic ID : 03
[048h 0072   4]        Flags (decoded below) : 00000001 # enabled
--
[04Fh 0079   1]                Local Apic ID : 84
[050h 0080   4]        Flags (decoded below) : 00000000
--
[057h 0087   1]                Local Apic ID : 85
[058h 0088   4]        Flags (decoded below) : 00000000

[    0.072112] CPU topo: Max. logical packages:   2
[    0.072112] CPU topo: Max. logical dies:       2
[    0.072113] CPU topo: Max. dies per package:   1
[    0.072118] CPU topo: Max. threads per core:   1
[    0.072118] CPU topo: Num. cores per package:     4
[    0.072119] CPU topo: Num. threads per package:   4
[    0.072120] CPU topo: Allowing 4 present CPUs plus 2 hotplug CPUs

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-10-24 18:46 AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14 Michal Pecio
@ 2025-10-24 21:32 ` Yazen Ghannam
  2025-10-27 16:18   ` Mario Limonciello
  2025-11-03  7:40   ` Michal Pecio
  0 siblings, 2 replies; 8+ messages in thread
From: Yazen Ghannam @ 2025-10-24 21:32 UTC (permalink / raw)
  To: Michal Pecio
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Mario Limonciello, Eric DeVolder, linux-kernel

On Fri, Oct 24, 2025 at 08:46:58PM +0200, Michal Pecio wrote:
> Hi,
> 
> This report is related to discussion here:
> https://lore.kernel.org/all/20251022011610.60d0ba6e.michal.pecio@gmail.com/
> 
> Commit bc7b2e629e0c ("x86/amd_nb: Use topology info to get AMD node
> count") bails out if it can't find the NB of each node reportedy by
> topology. Then NB features like EDAC or GART IOMMU aren't available.
> 
> Which was maybe not a bad idea, nobody expects those things to work
> on selected nodes only. (I think?) But it relies on the optimistic
> assumption that topology knows the true number of nodes.
> 
> Today I tested 5 older AMD64 systems with socket 754/AM2+/AM3/AM3+
> on MSI/ASUS motherboards. *All* of them report more than one node if
> the CPU has fewer cores than supported by the BIOS.
> 
> (I also have one AM4 system which is OK, but can't speak for others).
> 
> This is due to peculiarity of their MADT tables - they report as many
> LAPICs as the BIOS can support and excess LAPICs are simply disabled.
> FWIW, it's also a pattern that disabled APIC IDs have 0x80 bit set.
> 
> The kernel counts this as "hotpluggable CPUs", since supposedly it's
> indistinguishable from actual multi-socket systems before ACPI 6.3,
> where the "online capable" flag was added to disambiguate hotplug and
> nonexistent but theoretically supported CPUs.
> 
> Or at least that's what commit fed8d8773b8e ("x86/acpi/boot: Correct
> acpi_is_processor_usable() check") seems to imply.
> 
> On pre-ACPI 6.3 systems those disabled LAPICs inflate topology size
> and result in breakage on recent kernels. A few examples below give
> an idea what those MADTs look like and how the kernel reads them.
> 
> Regards,
> Michal
> 
> 
> Athlon 3000+ on S754:
> 
> [02Fh 0047 001h]               Local Apic ID : 00
> [030h 0048 004h]       Flags (decoded below) : 00000001	# enabled
> --
> [037h 0055 001h]               Local Apic ID : 81
> [038h 0056 004h]       Flags (decoded below) : 00000000
> 
> [    0.027690] CPU topo: Max. logical packages:   2
> [    0.027691] CPU topo: Max. logical dies:       2
> [    0.027692] CPU topo: Max. dies per package:   1
> [    0.027703] CPU topo: Max. threads per core:   1
> [    0.027704] CPU topo: Num. cores per package:     1
> [    0.027705] CPU topo: Num. threads per package:   1
> [    0.027706] CPU topo: Allowing 1 present CPUs plus 1 hotplug CPUs
> 
> Athlon II X2 250 on AM3+:
> 
> [02Fh 0047 001h]               Local Apic ID : 00
> [030h 0048 004h]       Flags (decoded below) : 00000001 # enabled
> --
> [037h 0055 001h]               Local Apic ID : 01
> [038h 0056 004h]       Flags (decoded below) : 00000001 # enabled
> --
> [03Fh 0063 001h]               Local Apic ID : 82
> [040h 0064 004h]       Flags (decoded below) : 00000000
> --
> [047h 0071 001h]               Local Apic ID : 83
> [048h 0072 004h]       Flags (decoded below) : 00000000
> --
> [04Fh 0079 001h]               Local Apic ID : 84
> [050h 0080 004h]       Flags (decoded below) : 00000000
> --
> [057h 0087 001h]               Local Apic ID : 85
> [058h 0088 004h]       Flags (decoded below) : 00000000
> --
> [05Fh 0095 001h]               Local Apic ID : 86
> [060h 0096 004h]       Flags (decoded below) : 00000000
> --
> [067h 0103 001h]               Local Apic ID : 87
> [068h 0104 004h]       Flags (decoded below) : 00000000
> 
> [    0.147372] CPU topo: Max. logical packages:   3 # not sure why not 4
> [    0.147372] CPU topo: Max. logical dies:       3
> [    0.147373] CPU topo: Max. dies per package:   1
> [    0.147379] CPU topo: Max. threads per core:   1
> [    0.147379] CPU topo: Num. cores per package:     2
> [    0.147380] CPU topo: Num. threads per package:   2
> [    0.147381] CPU topo: Allowing 2 present CPUs plus 6 hotplug CPUs
> 
> Phenom II X4 965 on AM3:
> 
> [02Fh 0047   1]                Local Apic ID : 00
> [030h 0048   4]        Flags (decoded below) : 00000001 # enabled
> --
> [037h 0055   1]                Local Apic ID : 01
> [038h 0056   4]        Flags (decoded below) : 00000001 # enabled
> --
> [03Fh 0063   1]                Local Apic ID : 02
> [040h 0064   4]        Flags (decoded below) : 00000001 # enabled
> --
> [047h 0071   1]                Local Apic ID : 03
> [048h 0072   4]        Flags (decoded below) : 00000001 # enabled
> --
> [04Fh 0079   1]                Local Apic ID : 84
> [050h 0080   4]        Flags (decoded below) : 00000000
> --
> [057h 0087   1]                Local Apic ID : 85
> [058h 0088   4]        Flags (decoded below) : 00000000
> 
> [    0.072112] CPU topo: Max. logical packages:   2
> [    0.072112] CPU topo: Max. logical dies:       2
> [    0.072113] CPU topo: Max. dies per package:   1
> [    0.072118] CPU topo: Max. threads per core:   1
> [    0.072118] CPU topo: Num. cores per package:     4
> [    0.072119] CPU topo: Num. threads per package:   4
> [    0.072120] CPU topo: Allowing 4 present CPUs plus 2 hotplug CPUs

So far, I think the way to go is add explicit quirk for known issues.

Please see the patch below.

Thanks,
Yazen


From eeb0745e973055d8840b536cfa842d6f2bf4ac52 Mon Sep 17 00:00:00 2001
From: Yazen Ghannam <yazen.ghannam@amd.com>
Date: Fri, 24 Oct 2025 21:19:26 +0000
Subject: [PATCH] x86/topology: Add helper to ignore bogus MADT entries

Some older Intel and AMD systems include bogus ACPI MADT entries. These
entries show as "disabled". And it's not clear if they are physically
present but offline, i.e halted. Or if they are not physically present
at all.

Ideally, if they are not physically present, then they should not be
listed in MADT. There doesn't seem to be any explicit x86 topology info
that can be used to verify if the entries are bogus or not.

Add a  helper function to collect vendor-specific checks to ignore bogus
APIC IDs. Start with known quirks for an Intel SNB model and older AMD
K10 models.

Fixes: f0551af02130 ("x86/topology: Ignore non-present APIC IDs in a present package")
Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
---
 arch/x86/kernel/cpu/topology.c | 52 ++++++++++++++++++++++++++--------
 1 file changed, 40 insertions(+), 12 deletions(-)

diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
index 6073a16628f9..704788b92395 100644
--- a/arch/x86/kernel/cpu/topology.c
+++ b/arch/x86/kernel/cpu/topology.c
@@ -219,6 +219,45 @@ static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_leve
 	return cnt;
 }
 
+/*
+ * Some older BIOSes include extra entries in MADT.
+ * Do some vendor-specific checks to ignore them.
+ */
+static bool ignore_extra_apic_entry(u32 apic_id)
+{
+	u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
+	struct cpuinfo_x86 *c = &boot_cpu_data;
+
+	/* Allow "physically not possible" cases if in a guest. */
+	if (!hypervisor_is_type(X86_HYPER_NATIVE))
+	       return false;
+
+	/* This model only supports 8 threads in a package. */
+	if (c->x86_vendor == X86_VENDOR_INTEL &&
+	    c->x86 == 0x6 && c->x86_model == 0x2d) {
+		if (topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map) >= 8)
+			goto reject;
+	}
+
+	/*
+	 * Various older models have extra entries. A common trait is that the
+	 * package ID derived from the APIC ID would be more than was ever supported.
+	 */
+	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x17) {
+		pkgid >>= x86_topo_system.dom_shifts[TOPO_PKG_DOMAIN - 1];
+
+		if (pkgid >= 8)
+			goto reject;
+	}
+
+	return false;
+
+reject:
+	pr_info_once("Ignoring hot-pluggable APIC ID %x.\n", apic_id);
+	topo_info.nr_rejected_cpus++;
+	return true;
+}
+
 static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
 {
 	int cpu, dom;
@@ -240,19 +279,8 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
 		cpuid_to_apicid[cpu] = apic_id;
 		topo_set_cpuids(cpu, apic_id, acpi_id);
 	} else {
-		u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
-
-		/*
-		 * Check for present APICs in the same package when running
-		 * on bare metal. Allow the bogosity in a guest.
-		 */
-		if (hypervisor_is_type(X86_HYPER_NATIVE) &&
-		    topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map)) {
-			pr_info_once("Ignoring hot-pluggable APIC ID %x in present package.\n",
-				     apic_id);
-			topo_info.nr_rejected_cpus++;
+		if (ignore_extra_apic_entry(apic_id))
 			return;
-		}
 
 		topo_info.nr_disabled_cpus++;
 	}
-- 
2.51.1


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-10-24 21:32 ` Yazen Ghannam
@ 2025-10-27 16:18   ` Mario Limonciello
  2025-10-28 14:36     ` Yazen Ghannam
  2025-11-03  7:40   ` Michal Pecio
  1 sibling, 1 reply; 8+ messages in thread
From: Mario Limonciello @ 2025-10-27 16:18 UTC (permalink / raw)
  To: Yazen Ghannam, Michal Pecio
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Eric DeVolder, linux-kernel

On 10/24/25 4:32 PM, Yazen Ghannam wrote:
> On Fri, Oct 24, 2025 at 08:46:58PM +0200, Michal Pecio wrote:
>> Hi,
>>
>> This report is related to discussion here:
>> https://lore.kernel.org/all/20251022011610.60d0ba6e.michal.pecio@gmail.com/
>>
>> Commit bc7b2e629e0c ("x86/amd_nb: Use topology info to get AMD node
>> count") bails out if it can't find the NB of each node reportedy by
>> topology. Then NB features like EDAC or GART IOMMU aren't available.
>>
>> Which was maybe not a bad idea, nobody expects those things to work
>> on selected nodes only. (I think?) But it relies on the optimistic
>> assumption that topology knows the true number of nodes.
>>
>> Today I tested 5 older AMD64 systems with socket 754/AM2+/AM3/AM3+
>> on MSI/ASUS motherboards. *All* of them report more than one node if
>> the CPU has fewer cores than supported by the BIOS.
>>
>> (I also have one AM4 system which is OK, but can't speak for others).
>>
>> This is due to peculiarity of their MADT tables - they report as many
>> LAPICs as the BIOS can support and excess LAPICs are simply disabled.
>> FWIW, it's also a pattern that disabled APIC IDs have 0x80 bit set.
>>
>> The kernel counts this as "hotpluggable CPUs", since supposedly it's
>> indistinguishable from actual multi-socket systems before ACPI 6.3,
>> where the "online capable" flag was added to disambiguate hotplug and
>> nonexistent but theoretically supported CPUs.
>>
>> Or at least that's what commit fed8d8773b8e ("x86/acpi/boot: Correct
>> acpi_is_processor_usable() check") seems to imply.
>>
>> On pre-ACPI 6.3 systems those disabled LAPICs inflate topology size
>> and result in breakage on recent kernels. A few examples below give
>> an idea what those MADTs look like and how the kernel reads them.
>>
>> Regards,
>> Michal
>>
>>
>> Athlon 3000+ on S754:
>>
>> [02Fh 0047 001h]               Local Apic ID : 00
>> [030h 0048 004h]       Flags (decoded below) : 00000001	# enabled
>> --
>> [037h 0055 001h]               Local Apic ID : 81
>> [038h 0056 004h]       Flags (decoded below) : 00000000
>>
>> [    0.027690] CPU topo: Max. logical packages:   2
>> [    0.027691] CPU topo: Max. logical dies:       2
>> [    0.027692] CPU topo: Max. dies per package:   1
>> [    0.027703] CPU topo: Max. threads per core:   1
>> [    0.027704] CPU topo: Num. cores per package:     1
>> [    0.027705] CPU topo: Num. threads per package:   1
>> [    0.027706] CPU topo: Allowing 1 present CPUs plus 1 hotplug CPUs
>>
>> Athlon II X2 250 on AM3+:
>>
>> [02Fh 0047 001h]               Local Apic ID : 00
>> [030h 0048 004h]       Flags (decoded below) : 00000001 # enabled
>> --
>> [037h 0055 001h]               Local Apic ID : 01
>> [038h 0056 004h]       Flags (decoded below) : 00000001 # enabled
>> --
>> [03Fh 0063 001h]               Local Apic ID : 82
>> [040h 0064 004h]       Flags (decoded below) : 00000000
>> --
>> [047h 0071 001h]               Local Apic ID : 83
>> [048h 0072 004h]       Flags (decoded below) : 00000000
>> --
>> [04Fh 0079 001h]               Local Apic ID : 84
>> [050h 0080 004h]       Flags (decoded below) : 00000000
>> --
>> [057h 0087 001h]               Local Apic ID : 85
>> [058h 0088 004h]       Flags (decoded below) : 00000000
>> --
>> [05Fh 0095 001h]               Local Apic ID : 86
>> [060h 0096 004h]       Flags (decoded below) : 00000000
>> --
>> [067h 0103 001h]               Local Apic ID : 87
>> [068h 0104 004h]       Flags (decoded below) : 00000000
>>
>> [    0.147372] CPU topo: Max. logical packages:   3 # not sure why not 4
>> [    0.147372] CPU topo: Max. logical dies:       3
>> [    0.147373] CPU topo: Max. dies per package:   1
>> [    0.147379] CPU topo: Max. threads per core:   1
>> [    0.147379] CPU topo: Num. cores per package:     2
>> [    0.147380] CPU topo: Num. threads per package:   2
>> [    0.147381] CPU topo: Allowing 2 present CPUs plus 6 hotplug CPUs
>>
>> Phenom II X4 965 on AM3:
>>
>> [02Fh 0047   1]                Local Apic ID : 00
>> [030h 0048   4]        Flags (decoded below) : 00000001 # enabled
>> --
>> [037h 0055   1]                Local Apic ID : 01
>> [038h 0056   4]        Flags (decoded below) : 00000001 # enabled
>> --
>> [03Fh 0063   1]                Local Apic ID : 02
>> [040h 0064   4]        Flags (decoded below) : 00000001 # enabled
>> --
>> [047h 0071   1]                Local Apic ID : 03
>> [048h 0072   4]        Flags (decoded below) : 00000001 # enabled
>> --
>> [04Fh 0079   1]                Local Apic ID : 84
>> [050h 0080   4]        Flags (decoded below) : 00000000
>> --
>> [057h 0087   1]                Local Apic ID : 85
>> [058h 0088   4]        Flags (decoded below) : 00000000
>>
>> [    0.072112] CPU topo: Max. logical packages:   2
>> [    0.072112] CPU topo: Max. logical dies:       2
>> [    0.072113] CPU topo: Max. dies per package:   1
>> [    0.072118] CPU topo: Max. threads per core:   1
>> [    0.072118] CPU topo: Num. cores per package:     4
>> [    0.072119] CPU topo: Num. threads per package:   4
>> [    0.072120] CPU topo: Allowing 4 present CPUs plus 2 hotplug CPUs
> 
> So far, I think the way to go is add explicit quirk for known issues.
> 
> Please see the patch below.
> 
> Thanks,
> Yazen
> 
> 
>  From eeb0745e973055d8840b536cfa842d6f2bf4ac52 Mon Sep 17 00:00:00 2001
> From: Yazen Ghannam <yazen.ghannam@amd.com>
> Date: Fri, 24 Oct 2025 21:19:26 +0000
> Subject: [PATCH] x86/topology: Add helper to ignore bogus MADT entries
> 
> Some older Intel and AMD systems include bogus ACPI MADT entries. These
> entries show as "disabled". And it's not clear if they are physically
> present but offline, i.e halted. Or if they are not physically present
> at all.
> 
> Ideally, if they are not physically present, then they should not be
> listed in MADT. There doesn't seem to be any explicit x86 topology info
> that can be used to verify if the entries are bogus or not.
> 
> Add a  helper function to collect vendor-specific checks to ignore bogus
> APIC IDs. Start with known quirks for an Intel SNB model and older AMD
> K10 models.
> 
> Fixes: f0551af02130 ("x86/topology: Ignore non-present APIC IDs in a present package")
> Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
> ---
>   arch/x86/kernel/cpu/topology.c | 52 ++++++++++++++++++++++++++--------
>   1 file changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
> index 6073a16628f9..704788b92395 100644
> --- a/arch/x86/kernel/cpu/topology.c
> +++ b/arch/x86/kernel/cpu/topology.c
> @@ -219,6 +219,45 @@ static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_leve
>   	return cnt;
>   }
>   
> +/*
> + * Some older BIOSes include extra entries in MADT.
> + * Do some vendor-specific checks to ignore them.
> + */
> +static bool ignore_extra_apic_entry(u32 apic_id)
> +{
> +	u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> +	struct cpuinfo_x86 *c = &boot_cpu_data;
> +
> +	/* Allow "physically not possible" cases if in a guest. */
> +	if (!hypervisor_is_type(X86_HYPER_NATIVE))
> +	       return false;
> +
> +	/* This model only supports 8 threads in a package. */
> +	if (c->x86_vendor == X86_VENDOR_INTEL &&
> +	    c->x86 == 0x6 && c->x86_model == 0x2d) {
> +		if (topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map) >= 8)
> +			goto reject;
> +	}
> +
> +	/*
> +	 * Various older models have extra entries. A common trait is that the
> +	 * package ID derived from the APIC ID would be more than was ever supported.
> +	 */
> +	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x17) {

Maybe look for lack of X86_FEATURE_ZEN instead?

> +		pkgid >>= x86_topo_system.dom_shifts[TOPO_PKG_DOMAIN - 1];
> +
> +		if (pkgid >= 8)
> +			goto reject;
> +	}
> +
> +	return false;
> +
> +reject:
> +	pr_info_once("Ignoring hot-pluggable APIC ID %x.\n", apic_id);
> +	topo_info.nr_rejected_cpus++;
> +	return true;
> +}
> +
>   static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
>   {
>   	int cpu, dom;
> @@ -240,19 +279,8 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
>   		cpuid_to_apicid[cpu] = apic_id;
>   		topo_set_cpuids(cpu, apic_id, acpi_id);
>   	} else {
> -		u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> -
> -		/*
> -		 * Check for present APICs in the same package when running
> -		 * on bare metal. Allow the bogosity in a guest.
> -		 */
> -		if (hypervisor_is_type(X86_HYPER_NATIVE) &&
> -		    topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map)) {
> -			pr_info_once("Ignoring hot-pluggable APIC ID %x in present package.\n",
> -				     apic_id);
> -			topo_info.nr_rejected_cpus++;
> +		if (ignore_extra_apic_entry(apic_id))
>   			return;
> -		}
>   
>   		topo_info.nr_disabled_cpus++;
>   	}


^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-10-27 16:18   ` Mario Limonciello
@ 2025-10-28 14:36     ` Yazen Ghannam
  0 siblings, 0 replies; 8+ messages in thread
From: Yazen Ghannam @ 2025-10-28 14:36 UTC (permalink / raw)
  To: Mario Limonciello
  Cc: Michal Pecio, x86, regressions, Thomas Gleixner, Ingo Molnar,
	Borislav Petkov, Eric DeVolder, linux-kernel

On Mon, Oct 27, 2025 at 11:18:38AM -0500, Mario Limonciello wrote:
> On 10/24/25 4:32 PM, Yazen Ghannam wrote:

[...]

> > +/*
> > + * Some older BIOSes include extra entries in MADT.
> > + * Do some vendor-specific checks to ignore them.
> > + */
> > +static bool ignore_extra_apic_entry(u32 apic_id)
> > +{
> > +	u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> > +	struct cpuinfo_x86 *c = &boot_cpu_data;
> > +
> > +	/* Allow "physically not possible" cases if in a guest. */
> > +	if (!hypervisor_is_type(X86_HYPER_NATIVE))
> > +	       return false;
> > +
> > +	/* This model only supports 8 threads in a package. */
> > +	if (c->x86_vendor == X86_VENDOR_INTEL &&
> > +	    c->x86 == 0x6 && c->x86_model == 0x2d) {
> > +		if (topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map) >= 8)
> > +			goto reject;
> > +	}
> > +
> > +	/*
> > +	 * Various older models have extra entries. A common trait is that the
> > +	 * package ID derived from the APIC ID would be more than was ever supported.
> > +	 */
> > +	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x17) {
> 
> Maybe look for lack of X86_FEATURE_ZEN instead?

Thanks. Yep, good idea.

> 
> > +		pkgid >>= x86_topo_system.dom_shifts[TOPO_PKG_DOMAIN - 1];
> > +
> > +		if (pkgid >= 8)
> > +			goto reject;
> > +	}
> > +
> > +	return false;
> > +
> > +reject:
> > +	pr_info_once("Ignoring hot-pluggable APIC ID %x.\n", apic_id);
> > +	topo_info.nr_rejected_cpus++;
> > +	return true;
> > +}
> > +

Michal, does this patch resolve the issue on you systems?

Thanks,
Yazen

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-10-24 21:32 ` Yazen Ghannam
  2025-10-27 16:18   ` Mario Limonciello
@ 2025-11-03  7:40   ` Michal Pecio
  2025-11-03 14:38     ` Yazen Ghannam
  1 sibling, 1 reply; 8+ messages in thread
From: Michal Pecio @ 2025-11-03  7:40 UTC (permalink / raw)
  To: Yazen Ghannam
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Mario Limonciello, Eric DeVolder, linux-kernel

On Fri, 24 Oct 2025 17:32:04 -0400, Yazen Ghannam wrote:
> So far, I think the way to go is add explicit quirk for known issues.
> 
> Please see the patch below.
> 
> Thanks,
> Yazen
> 
> 
> From eeb0745e973055d8840b536cfa842d6f2bf4ac52 Mon Sep 17 00:00:00 2001
> From: Yazen Ghannam <yazen.ghannam@amd.com>
> Date: Fri, 24 Oct 2025 21:19:26 +0000
> Subject: [PATCH] x86/topology: Add helper to ignore bogus MADT entries
> 
> Some older Intel and AMD systems include bogus ACPI MADT entries. These
> entries show as "disabled". And it's not clear if they are physically
> present but offline, i.e halted. Or if they are not physically present
> at all.
> 
> Ideally, if they are not physically present, then they should not be
> listed in MADT. There doesn't seem to be any explicit x86 topology info
> that can be used to verify if the entries are bogus or not.
> 
> Add a  helper function to collect vendor-specific checks to ignore bogus
> APIC IDs. Start with known quirks for an Intel SNB model and older AMD
> K10 models.
> 
> Fixes: f0551af02130 ("x86/topology: Ignore non-present APIC IDs in a present package")
> Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
> ---
>  arch/x86/kernel/cpu/topology.c | 52 ++++++++++++++++++++++++++--------
>  1 file changed, 40 insertions(+), 12 deletions(-)
> 
> diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
> index 6073a16628f9..704788b92395 100644
> --- a/arch/x86/kernel/cpu/topology.c
> +++ b/arch/x86/kernel/cpu/topology.c
> @@ -219,6 +219,45 @@ static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_leve
>  	return cnt;
>  }
>  
> +/*
> + * Some older BIOSes include extra entries in MADT.
> + * Do some vendor-specific checks to ignore them.
> + */
> +static bool ignore_extra_apic_entry(u32 apic_id)
> +{
> +	u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> +	struct cpuinfo_x86 *c = &boot_cpu_data;
> +
> +	/* Allow "physically not possible" cases if in a guest. */
> +	if (!hypervisor_is_type(X86_HYPER_NATIVE))
> +	       return false;
> +
> +	/* This model only supports 8 threads in a package. */
> +	if (c->x86_vendor == X86_VENDOR_INTEL &&
> +	    c->x86 == 0x6 && c->x86_model == 0x2d) {
> +		if (topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map) >= 8)

Looks like possible functional change compared to the code it replaces,
perhaps it should be a separate patch?

> +			goto reject;
> +	}
> +
> +	/*
> +	 * Various older models have extra entries. A common trait is that the
> +	 * package ID derived from the APIC ID would be more than was ever supported.
> +	 */
> +	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x17) {
> +		pkgid >>= x86_topo_system.dom_shifts[TOPO_PKG_DOMAIN - 1];
> +
> +		if (pkgid >= 8)
> +			goto reject;

Yes, this works. The excess entries are counted as "rejected" rather
than "hotpluggable", package count is correct and EDAC/GART are back.

But to be exact, the known case is (apic_id >= 0x80) rather than
(pkgid >= 8). The latter assumes not only that there are no more than
8 packages, but also that their IDs start from zero.

I have this AM4 system with some proprietary HP BIOS:

[02Fh 0047 001h]               Local Apic ID : 10
[037h 0055 001h]               Local Apic ID : 11
[03Fh 0063 001h]               Local Apic ID : 12
[047h 0071 001h]               Local Apic ID : 13

domain: Thread     shift: 0 dom_size:     1 max_threads:     1
domain: Core       shift: 4 dom_size:    16 max_threads:    16
domain: Module     shift: 4 dom_size:     1 max_threads:    16
domain: Tile       shift: 4 dom_size:     1 max_threads:    16
domain: Die        shift: 4 dom_size:     1 max_threads:    16
domain: DieGrp     shift: 4 dom_size:     1 max_threads:    16
domain: Package    shift: 4 dom_size:     1 max_threads:    16

It seems that pkgid is 0x1 here, which is not a problem because
it's single socket, but dunno if HP or somebody else couldn't do
similar things in an 8-socket system and end up with pkgid > 8.


By the way, do you know what's the reason I don't have /sys directories
for those phantom CPUs (before this patch) and should I have them if
they were legitimate hotplug CPUs?

Maybe there is already some check performed in other part of the kernel
which rejects those CPUs and which could be replicated here.

> +	}
> +
> +	return false;
> +
> +reject:
> +	pr_info_once("Ignoring hot-pluggable APIC ID %x.\n", apic_id);
> +	topo_info.nr_rejected_cpus++;
> +	return true;
> +}
> +
>  static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
>  {
>  	int cpu, dom;
> @@ -240,19 +279,8 @@ static __init void topo_register_apic(u32 apic_id, u32 acpi_id, bool present)
>  		cpuid_to_apicid[cpu] = apic_id;
>  		topo_set_cpuids(cpu, apic_id, acpi_id);
>  	} else {
> -		u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> -
> -		/*
> -		 * Check for present APICs in the same package when running
> -		 * on bare metal. Allow the bogosity in a guest.
> -		 */
> -		if (hypervisor_is_type(X86_HYPER_NATIVE) &&
> -		    topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map)) {
> -			pr_info_once("Ignoring hot-pluggable APIC ID %x in present package.\n",
> -				     apic_id);
> -			topo_info.nr_rejected_cpus++;
> +		if (ignore_extra_apic_entry(apic_id))
>  			return;
> -		}
>  
>  		topo_info.nr_disabled_cpus++;
>  	}
> -- 
> 2.51.1
> 

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-11-03  7:40   ` Michal Pecio
@ 2025-11-03 14:38     ` Yazen Ghannam
  2025-11-03 17:12       ` Michal Pecio
  0 siblings, 1 reply; 8+ messages in thread
From: Yazen Ghannam @ 2025-11-03 14:38 UTC (permalink / raw)
  To: Michal Pecio
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Mario Limonciello, Eric DeVolder, linux-kernel

On Mon, Nov 03, 2025 at 08:40:21AM +0100, Michal Pecio wrote:
> On Fri, 24 Oct 2025 17:32:04 -0400, Yazen Ghannam wrote:
> > So far, I think the way to go is add explicit quirk for known issues.
> > 
> > Please see the patch below.
> > 
> > Thanks,
> > Yazen
> > 
> > 
> > From eeb0745e973055d8840b536cfa842d6f2bf4ac52 Mon Sep 17 00:00:00 2001
> > From: Yazen Ghannam <yazen.ghannam@amd.com>
> > Date: Fri, 24 Oct 2025 21:19:26 +0000
> > Subject: [PATCH] x86/topology: Add helper to ignore bogus MADT entries
> > 
> > Some older Intel and AMD systems include bogus ACPI MADT entries. These
> > entries show as "disabled". And it's not clear if they are physically
> > present but offline, i.e halted. Or if they are not physically present
> > at all.
> > 
> > Ideally, if they are not physically present, then they should not be
> > listed in MADT. There doesn't seem to be any explicit x86 topology info
> > that can be used to verify if the entries are bogus or not.
> > 
> > Add a  helper function to collect vendor-specific checks to ignore bogus
> > APIC IDs. Start with known quirks for an Intel SNB model and older AMD
> > K10 models.
> > 
> > Fixes: f0551af02130 ("x86/topology: Ignore non-present APIC IDs in a present package")
> > Signed-off-by: Yazen Ghannam <yazen.ghannam@amd.com>
> > ---
> >  arch/x86/kernel/cpu/topology.c | 52 ++++++++++++++++++++++++++--------
> >  1 file changed, 40 insertions(+), 12 deletions(-)
> > 
> > diff --git a/arch/x86/kernel/cpu/topology.c b/arch/x86/kernel/cpu/topology.c
> > index 6073a16628f9..704788b92395 100644
> > --- a/arch/x86/kernel/cpu/topology.c
> > +++ b/arch/x86/kernel/cpu/topology.c
> > @@ -219,6 +219,45 @@ static unsigned int topo_unit_count(u32 lvlid, enum x86_topology_domains at_leve
> >  	return cnt;
> >  }
> >  
> > +/*
> > + * Some older BIOSes include extra entries in MADT.
> > + * Do some vendor-specific checks to ignore them.
> > + */
> > +static bool ignore_extra_apic_entry(u32 apic_id)
> > +{
> > +	u32 pkgid = topo_apicid(apic_id, TOPO_PKG_DOMAIN);
> > +	struct cpuinfo_x86 *c = &boot_cpu_data;
> > +
> > +	/* Allow "physically not possible" cases if in a guest. */
> > +	if (!hypervisor_is_type(X86_HYPER_NATIVE))
> > +	       return false;
> > +
> > +	/* This model only supports 8 threads in a package. */
> > +	if (c->x86_vendor == X86_VENDOR_INTEL &&
> > +	    c->x86 == 0x6 && c->x86_model == 0x2d) {
> > +		if (topo_unit_count(pkgid, TOPO_PKG_DOMAIN, phys_cpu_present_map) >= 8)
> 
> Looks like possible functional change compared to the code it replaces,
> perhaps it should be a separate patch?
> 

Yes, that's right. I just wanted to put everything together as a quick
check. We can clean it up if things work.

> > +			goto reject;
> > +	}
> > +
> > +	/*
> > +	 * Various older models have extra entries. A common trait is that the
> > +	 * package ID derived from the APIC ID would be more than was ever supported.
> > +	 */
> > +	if (c->x86_vendor == X86_VENDOR_AMD && c->x86 < 0x17) {
> > +		pkgid >>= x86_topo_system.dom_shifts[TOPO_PKG_DOMAIN - 1];
> > +
> > +		if (pkgid >= 8)
> > +			goto reject;
> 
> Yes, this works. The excess entries are counted as "rejected" rather
> than "hotpluggable", package count is correct and EDAC/GART are back.
> 

Cool, thanks for confirming.

> But to be exact, the known case is (apic_id >= 0x80) rather than
> (pkgid >= 8). The latter assumes not only that there are no more than
> 8 packages, but also that their IDs start from zero.
> 

Yes, that's right. I see these checks as quirks for old systems only. We
just need catch the bogus cases. These shouldn't be generally
applicable. Though it'd be good to catch as many cases in as few
conditions as possible. My thinking is we start with more narrow
conditions and expand them if there are other reported cases.

> I have this AM4 system with some proprietary HP BIOS:
> 
> [02Fh 0047 001h]               Local Apic ID : 10
> [037h 0055 001h]               Local Apic ID : 11
> [03Fh 0063 001h]               Local Apic ID : 12
> [047h 0071 001h]               Local Apic ID : 13
> 
> domain: Thread     shift: 0 dom_size:     1 max_threads:     1
> domain: Core       shift: 4 dom_size:    16 max_threads:    16
> domain: Module     shift: 4 dom_size:     1 max_threads:    16
> domain: Tile       shift: 4 dom_size:     1 max_threads:    16
> domain: Die        shift: 4 dom_size:     1 max_threads:    16
> domain: DieGrp     shift: 4 dom_size:     1 max_threads:    16
> domain: Package    shift: 4 dom_size:     1 max_threads:    16
> 
> It seems that pkgid is 0x1 here, which is not a problem because
> it's single socket, but dunno if HP or somebody else couldn't do
> similar things in an 8-socket system and end up with pkgid > 8.
> 

So is this another bogus case?

And, if so, it works because of the "ignore hotpluggable in present
package" check?

> 
> By the way, do you know what's the reason I don't have /sys directories
> for those phantom CPUs (before this patch) and should I have them if
> they were legitimate hotplug CPUs?
> 
> Maybe there is already some check performed in other part of the kernel
> which rejects those CPUs and which could be replicated here.
> 

Sorry, I don't know. Maybe others can comment if they have any pointers.

Thanks,
Yazen

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-11-03 14:38     ` Yazen Ghannam
@ 2025-11-03 17:12       ` Michal Pecio
  2025-11-04 15:23         ` Yazen Ghannam
  0 siblings, 1 reply; 8+ messages in thread
From: Michal Pecio @ 2025-11-03 17:12 UTC (permalink / raw)
  To: Yazen Ghannam
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Mario Limonciello, Eric DeVolder, linux-kernel

On Mon, 3 Nov 2025 09:38:51 -0500, Yazen Ghannam wrote:
> > I have this AM4 system with some proprietary HP BIOS:
> > 
> > [02Fh 0047 001h]               Local Apic ID : 10
> > [037h 0055 001h]               Local Apic ID : 11
> > [03Fh 0063 001h]               Local Apic ID : 12
> > [047h 0071 001h]               Local Apic ID : 13
> > 
> > domain: Thread     shift: 0 dom_size:     1 max_threads:     1
> > domain: Core       shift: 4 dom_size:    16 max_threads:    16
> > domain: Module     shift: 4 dom_size:     1 max_threads:    16
> > domain: Tile       shift: 4 dom_size:     1 max_threads:    16
> > domain: Die        shift: 4 dom_size:     1 max_threads:    16
> > domain: DieGrp     shift: 4 dom_size:     1 max_threads:    16
> > domain: Package    shift: 4 dom_size:     1 max_threads:    16
> > 
> > It seems that pkgid is 0x1 here, which is not a problem because
> > it's single socket, but dunno if HP or somebody else couldn't do
> > similar things in an 8-socket system and end up with pkgid > 8.
> >   
> 
> So is this another bogus case?

No, it isn't bogus. It's a quad-core Carrizo APU with its four LAPICs,
but their numbers start from 0x10 rather than 0x00. And AFAIU, the
calculated pkgid vaule will be 1.

If HP or other vendor would do similar thing on an 8-socket system,
the assumption that (pkgid < 8) could no longer hold, even if the CPUs
are completely real.

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14
  2025-11-03 17:12       ` Michal Pecio
@ 2025-11-04 15:23         ` Yazen Ghannam
  0 siblings, 0 replies; 8+ messages in thread
From: Yazen Ghannam @ 2025-11-04 15:23 UTC (permalink / raw)
  To: Michal Pecio
  Cc: x86, regressions, Thomas Gleixner, Ingo Molnar, Borislav Petkov,
	Mario Limonciello, Eric DeVolder, linux-kernel

On Mon, Nov 03, 2025 at 06:12:45PM +0100, Michal Pecio wrote:
> On Mon, 3 Nov 2025 09:38:51 -0500, Yazen Ghannam wrote:
> > > I have this AM4 system with some proprietary HP BIOS:
> > > 
> > > [02Fh 0047 001h]               Local Apic ID : 10
> > > [037h 0055 001h]               Local Apic ID : 11
> > > [03Fh 0063 001h]               Local Apic ID : 12
> > > [047h 0071 001h]               Local Apic ID : 13
> > > 
> > > domain: Thread     shift: 0 dom_size:     1 max_threads:     1
> > > domain: Core       shift: 4 dom_size:    16 max_threads:    16
> > > domain: Module     shift: 4 dom_size:     1 max_threads:    16
> > > domain: Tile       shift: 4 dom_size:     1 max_threads:    16
> > > domain: Die        shift: 4 dom_size:     1 max_threads:    16
> > > domain: DieGrp     shift: 4 dom_size:     1 max_threads:    16
> > > domain: Package    shift: 4 dom_size:     1 max_threads:    16
> > > 
> > > It seems that pkgid is 0x1 here, which is not a problem because
> > > it's single socket, but dunno if HP or somebody else couldn't do
> > > similar things in an 8-socket system and end up with pkgid > 8.
> > >   
> > 
> > So is this another bogus case?
> 
> No, it isn't bogus. It's a quad-core Carrizo APU with its four LAPICs,
> but their numbers start from 0x10 rather than 0x00. And AFAIU, the
> calculated pkgid vaule will be 1.
> 

Oh I see. That's interesting.

Though something still feels off about it, because these systems never
had 16 threads/cores.

> If HP or other vendor would do similar thing on an 8-socket system,
> the assumption that (pkgid < 8) could no longer hold, even if the CPUs
> are completely real.

The proposed check only applies to older systems. Were there any
8-socket AMD systems in production? I'm only aware of systems up to 4
sockets from those days. Hence the arbitrary value check.

Now there are systems with 8 "AMD nodes". However, before Zen these
would be 2 AMD nodes per socket. With 4 sockets you'd get 8 AMD nodes.
Naples had 4 AMD nodes per socket, but the max system had 2 sockets.

But I think I see your point that this check would break if the pkgid
values can start from an arbitrary number. If such a case is reported,
then this could be a new quirk or rework of the existing quirks.

Thanks,
Yazen

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2025-11-04 15:24 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-10-24 18:46 AMD topology broken on various 754/AM2+/AM3/AM3+ systems causes NB/EDAC/GART regression since 6.14 Michal Pecio
2025-10-24 21:32 ` Yazen Ghannam
2025-10-27 16:18   ` Mario Limonciello
2025-10-28 14:36     ` Yazen Ghannam
2025-11-03  7:40   ` Michal Pecio
2025-11-03 14:38     ` Yazen Ghannam
2025-11-03 17:12       ` Michal Pecio
2025-11-04 15:23         ` Yazen Ghannam

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox