LKML Archive mirror
 help / color / mirror / Atom feed
* [patch V6 11/19] x86/cpu: Use common topology code for AMD
  2024-02-13 21:03 [patch V6 00/19] x86/cpu: Rework topology evaluation Thomas Gleixner
@ 2024-02-13 21:04 ` Thomas Gleixner
  0 siblings, 0 replies; 5+ messages in thread
From: Thomas Gleixner @ 2024-02-13 21:04 UTC (permalink / raw
  To: LKML
  Cc: x86, Tom Lendacky, Andrew Cooper, Arjan van de Ven, Huang Rui,
	Juergen Gross, Dimitri Sivanich, Sohil Mehta, K Prateek Nayak,
	Kan Liang, Zhang Rui, Paul E. McKenney, Feng Tang,
	Andy Shevchenko, Michael Kelley, Peter Zijlstra (Intel),
	Wang Wendy

From: Thomas Gleixner <tglx@linutronix.de>

Switch it over to the new topology evaluation mechanism and remove the
random bits and pieces which are sprinkled all over the place.

No functional change intended.

Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Juergen Gross <jgross@suse.com>
Tested-by: Sohil Mehta <sohil.mehta@intel.com>
Tested-by: Michael Kelley <mhklinux@outlook.com>
Tested-by: Zhang Rui <rui.zhang@intel.com>
Tested-by: Wang Wendy <wendy.wang@intel.com>
---
V6: Remove amd_get_nodes_per_socket() completely
---
 arch/x86/include/asm/processor.h      |    2 
 arch/x86/kernel/cpu/amd.c             |  146 ----------------------------------
 arch/x86/kernel/cpu/mce/inject.c      |    3 
 arch/x86/kernel/cpu/topology_common.c |    5 -
 4 files changed, 5 insertions(+), 151 deletions(-)
---

--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -707,12 +707,10 @@ static inline u32 per_cpu_l2c_id(unsigne
 }
 
 #ifdef CONFIG_CPU_SUP_AMD
-extern u32 amd_get_nodes_per_socket(void);
 extern u32 amd_get_highest_perf(void);
 extern void amd_clear_divider(void);
 extern void amd_check_microcode(void);
 #else
-static inline u32 amd_get_nodes_per_socket(void)	{ return 0; }
 static inline u32 amd_get_highest_perf(void)		{ return 0; }
 static inline void amd_clear_divider(void)		{ }
 static inline void amd_check_microcode(void)		{ }
--- a/arch/x86/kernel/cpu/amd.c
+++ b/arch/x86/kernel/cpu/amd.c
@@ -27,13 +27,6 @@
 
 #include "cpu.h"
 
-/*
- * nodes_per_socket: Stores the number of nodes per socket.
- * Refer to Fam15h Models 00-0fh BKDG - CPUID Fn8000_001E_ECX
- * Node Identifiers[10:8]
- */
-static u32 nodes_per_socket = 1;
-
 static inline int rdmsrl_amd_safe(unsigned msr, unsigned long long *p)
 {
 	u32 gprs[8] = { 0 };
@@ -300,97 +293,6 @@ static int nearby_node(int apicid)
 }
 #endif
 
-/*
- * Fix up topo::core_id for pre-F17h systems to be in the
- * [0 .. cores_per_node - 1] range. Not really needed but
- * kept so as not to break existing setups.
- */
-static void legacy_fixup_core_id(struct cpuinfo_x86 *c)
-{
-	u32 cus_per_node;
-
-	if (c->x86 >= 0x17)
-		return;
-
-	cus_per_node = c->x86_max_cores / nodes_per_socket;
-	c->topo.core_id %= cus_per_node;
-}
-
-/*
- * Fixup core topology information for
- * (1) AMD multi-node processors
- *     Assumption: Number of cores in each internal node is the same.
- * (2) AMD processors supporting compute units
- */
-static void amd_get_topology(struct cpuinfo_x86 *c)
-{
-	/* get information required for multi-node processors */
-	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
-		int err;
-		u32 eax, ebx, ecx, edx;
-
-		cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
-
-		c->topo.die_id  = ecx & 0xff;
-
-		if (c->x86 == 0x15)
-			c->topo.cu_id = ebx & 0xff;
-
-		if (c->x86 >= 0x17) {
-			c->topo.core_id = ebx & 0xff;
-
-			if (smp_num_siblings > 1)
-				c->x86_max_cores /= smp_num_siblings;
-		}
-
-		/*
-		 * In case leaf B is available, use it to derive
-		 * topology information.
-		 */
-		err = detect_extended_topology(c);
-		if (!err)
-			c->x86_coreid_bits = get_count_order(c->x86_max_cores);
-
-		cacheinfo_amd_init_llc_id(c, c->topo.die_id);
-
-	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
-		u64 value;
-
-		rdmsrl(MSR_FAM10H_NODE_ID, value);
-		c->topo.die_id = value & 7;
-		c->topo.llc_id = c->topo.die_id;
-	} else
-		return;
-
-	if (nodes_per_socket > 1) {
-		set_cpu_cap(c, X86_FEATURE_AMD_DCM);
-		legacy_fixup_core_id(c);
-	}
-}
-
-/*
- * On a AMD dual core setup the lower bits of the APIC id distinguish the cores.
- * Assumes number of cores is a power of two.
- */
-static void amd_detect_cmp(struct cpuinfo_x86 *c)
-{
-	unsigned bits;
-
-	bits = c->x86_coreid_bits;
-	/* Low order bits define the core id (index of core in socket) */
-	c->topo.core_id = c->topo.initial_apicid & ((1 << bits)-1);
-	/* Convert the initial APIC ID into the socket ID */
-	c->topo.pkg_id = c->topo.initial_apicid >> bits;
-	/* use socket ID also for last level cache */
-	c->topo.llc_id = c->topo.die_id = c->topo.pkg_id;
-}
-
-u32 amd_get_nodes_per_socket(void)
-{
-	return nodes_per_socket;
-}
-EXPORT_SYMBOL_GPL(amd_get_nodes_per_socket);
-
 static void srat_detect_node(struct cpuinfo_x86 *c)
 {
 #ifdef CONFIG_NUMA
@@ -442,32 +344,6 @@ static void srat_detect_node(struct cpui
 #endif
 }
 
-static void early_init_amd_mc(struct cpuinfo_x86 *c)
-{
-#ifdef CONFIG_SMP
-	unsigned bits, ecx;
-
-	/* Multi core CPU? */
-	if (c->extended_cpuid_level < 0x80000008)
-		return;
-
-	ecx = cpuid_ecx(0x80000008);
-
-	c->x86_max_cores = (ecx & 0xff) + 1;
-
-	/* CPU telling us the core id bits shift? */
-	bits = (ecx >> 12) & 0xF;
-
-	/* Otherwise recompute */
-	if (bits == 0) {
-		while ((1 << bits) < c->x86_max_cores)
-			bits++;
-	}
-
-	c->x86_coreid_bits = bits;
-#endif
-}
-
 static void bsp_init_amd(struct cpuinfo_x86 *c)
 {
 	if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
@@ -500,18 +376,6 @@ static void bsp_init_amd(struct cpuinfo_
 	if (cpu_has(c, X86_FEATURE_MWAITX))
 		use_mwaitx_delay();
 
-	if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
-		u32 ecx;
-
-		ecx = cpuid_ecx(0x8000001e);
-		__max_die_per_package = nodes_per_socket = ((ecx >> 8) & 7) + 1;
-	} else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
-		u64 value;
-
-		rdmsrl(MSR_FAM10H_NODE_ID, value);
-		__max_die_per_package = nodes_per_socket = ((value >> 3) & 7) + 1;
-	}
-
 	if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
 	    !boot_cpu_has(X86_FEATURE_VIRT_SSBD) &&
 	    c->x86 >= 0x15 && c->x86 <= 0x17) {
@@ -649,8 +513,6 @@ static void early_init_amd(struct cpuinf
 	u64 value;
 	u32 dummy;
 
-	early_init_amd_mc(c);
-
 	if (c->x86 >= 0xf)
 		set_cpu_cap(c, X86_FEATURE_K8);
 
@@ -730,9 +592,6 @@ static void early_init_amd(struct cpuinf
 		}
 	}
 
-	if (cpu_has(c, X86_FEATURE_TOPOEXT))
-		smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
-
 	if (!cpu_has(c, X86_FEATURE_HYPERVISOR) && !cpu_has(c, X86_FEATURE_IBPB_BRTYPE)) {
 		if (c->x86 == 0x17 && boot_cpu_has(X86_FEATURE_AMD_IBPB))
 			setup_force_cpu_cap(X86_FEATURE_IBPB_BRTYPE);
@@ -1076,9 +935,6 @@ static void init_amd(struct cpuinfo_x86
 	if (cpu_has(c, X86_FEATURE_FSRM))
 		set_cpu_cap(c, X86_FEATURE_FSRS);
 
-	/* get apicid instead of initial apic id from cpuid */
-	c->topo.apicid = read_apic_id();
-
 	/* K6s reports MCEs but don't actually have all the MSRs */
 	if (c->x86 < 6)
 		clear_cpu_cap(c, X86_FEATURE_MCE);
@@ -1114,8 +970,6 @@ static void init_amd(struct cpuinfo_x86
 
 	cpu_detect_cache_sizes(c);
 
-	amd_detect_cmp(c);
-	amd_get_topology(c);
 	srat_detect_node(c);
 
 	init_amd_cacheinfo(c);
--- a/arch/x86/kernel/cpu/mce/inject.c
+++ b/arch/x86/kernel/cpu/mce/inject.c
@@ -433,8 +433,7 @@ static u32 get_nbc_for_node(int node_id)
 	struct cpuinfo_x86 *c = &boot_cpu_data;
 	u32 cores_per_node;
 
-	cores_per_node = (c->x86_max_cores * smp_num_siblings) / amd_get_nodes_per_socket();
-
+	cores_per_node = (c->x86_max_cores * smp_num_siblings) / topology_amd_nodes_per_pkg();
 	return cores_per_node * node_id;
 }
 
--- a/arch/x86/kernel/cpu/topology_common.c
+++ b/arch/x86/kernel/cpu/topology_common.c
@@ -72,7 +72,6 @@ bool topo_is_converted(struct cpuinfo_x8
 {
 	/* Temporary until everything is converted over. */
 	switch (boot_cpu_data.x86_vendor) {
-	case X86_VENDOR_AMD:
 	case X86_VENDOR_HYGON:
 		return false;
 	default:
@@ -133,6 +132,10 @@ static void parse_topology(struct topo_s
 	tscan->ebx1_nproc_shift = get_count_order(ebx.nproc);
 
 	switch (c->x86_vendor) {
+	case X86_VENDOR_AMD:
+		if (IS_ENABLED(CONFIG_CPU_SUP_AMD))
+			cpu_parse_topology_amd(tscan);
+		break;
 	case X86_VENDOR_CENTAUR:
 	case X86_VENDOR_ZHAOXIN:
 		parse_legacy(tscan);


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

* Re: [patch V6 11/19] x86/cpu: Use common topology code for AMD
@ 2024-03-14 10:21 Yuezhang.Mo
  2024-03-14 12:07 ` Borislav Petkov
  2024-05-08 19:53 ` [patch] x86/topology/amd: Ensure that LLC ID is initialized Thomas Gleixner
  0 siblings, 2 replies; 5+ messages in thread
From: Yuezhang.Mo @ 2024-03-14 10:21 UTC (permalink / raw
  To: tglx@linutronix.de
  Cc: andrew.cooper3@citrix.com, andy@infradead.org,
	arjan@linux.intel.com, dimitri.sivanich@hpe.com,
	feng.tang@intel.com, jgross@suse.com, kan.liang@linux.intel.com,
	kprateek.nayak@amd.com, linux-kernel@vger.kernel.org,
	mhklinux@outlook.com, paulmck@kernel.org, peterz@infradead.org,
	ray.huang@amd.com, rui.zhang@intel.com, sohil.mehta@intel.com,
	thomas.lendacky@amd.com, wendy.wang@intel.com, x86@kernel.org

I ran xfstests generic/650 and found that it failed.

The reason for the failure is that this appears in dmesg:

[  649.590421] smpboot: CPU 2 is now offline
[  650.132920] smpboot: Booting Node 0 Processor 3 APIC 0x13
[  650.133432] LVT offset 0 assigned for vector 0x400
[  650.148931] ACPI: \_PR_.P003: Found 2 idle states
[  650.149478] BUG: arch topology borken
[  650.149483]      the CLS domain not a subset of the MC domain
[  650.149486] BUG: arch topology borken
[  650.149487]      the CLS domain not a subset of the MC domain

I prepared the following script to reproduce this issue.

#! /bin/sh

sysfs_cpu_dir="/sys/devices/system/cpu"
nrcpus=$(getconf _NPROCESSORS_CONF)
hotplug_cpus=()
for ((i = 0; i < nrcpus; i++ )); do
	test -e "$sysfs_cpu_dir/cpu$i/online" && hotplug_cpus+=("$i")
done

nr_hotplug_cpus="${#hotplug_cpus[@]}"

for ((i=0; i<20;i++)); do
	idx=$(( RANDOM % nr_hotplug_cpus ))
	cpu="${hotplug_cpus[$idx]}"
	action=$(( RANDOM % 2 ))

	echo "$action" > "$sysfs_cpu_dir/cpu$cpu/online" 2>/dev/null
	sleep 0.5
done

If run the script without this commit, the issue cannot be reproduced.

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

* Re: [patch V6 11/19] x86/cpu: Use common topology code for AMD
  2024-03-14 10:21 [patch V6 11/19] x86/cpu: Use common topology code for AMD Yuezhang.Mo
@ 2024-03-14 12:07 ` Borislav Petkov
  2024-05-08 19:53 ` [patch] x86/topology/amd: Ensure that LLC ID is initialized Thomas Gleixner
  1 sibling, 0 replies; 5+ messages in thread
From: Borislav Petkov @ 2024-03-14 12:07 UTC (permalink / raw
  To: Yuezhang.Mo@sony.com
  Cc: tglx@linutronix.de, andrew.cooper3@citrix.com, andy@infradead.org,
	arjan@linux.intel.com, dimitri.sivanich@hpe.com,
	feng.tang@intel.com, jgross@suse.com, kan.liang@linux.intel.com,
	kprateek.nayak@amd.com, linux-kernel@vger.kernel.org,
	mhklinux@outlook.com, paulmck@kernel.org, peterz@infradead.org,
	ray.huang@amd.com, rui.zhang@intel.com, sohil.mehta@intel.com,
	thomas.lendacky@amd.com, wendy.wang@intel.com, x86@kernel.org

On Thu, Mar 14, 2024 at 10:21:34AM +0000, Yuezhang.Mo@sony.com wrote:
> I ran xfstests generic/650 and found that it failed.
> 
> The reason for the failure is that this appears in dmesg:

Can you send - privately is fine too - from that machine:

* output of "cpuid -r"

* full dmesg

* output of "grep -r . /sys/kernel/debug/x86/topo/"

Thx.

-- 
Regards/Gruss,
    Boris.

https://people.kernel.org/tglx/notes-about-netiquette

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

* [patch] x86/topology/amd: Ensure that LLC ID is initialized
  2024-03-14 10:21 [patch V6 11/19] x86/cpu: Use common topology code for AMD Yuezhang.Mo
  2024-03-14 12:07 ` Borislav Petkov
@ 2024-05-08 19:53 ` Thomas Gleixner
  2024-05-10  8:56   ` Yuezhang.Mo
  1 sibling, 1 reply; 5+ messages in thread
From: Thomas Gleixner @ 2024-05-08 19:53 UTC (permalink / raw
  To: Yuezhang.Mo@sony.com
  Cc: andrew.cooper3@citrix.com, andy@infradead.org,
	arjan@linux.intel.com, dimitri.sivanich@hpe.com,
	feng.tang@intel.com, jgross@suse.com, kan.liang@linux.intel.com,
	kprateek.nayak@amd.com, linux-kernel@vger.kernel.org,
	mhklinux@outlook.com, paulmck@kernel.org, peterz@infradead.org,
	ray.huang@amd.com, rui.zhang@intel.com, sohil.mehta@intel.com,
	thomas.lendacky@amd.com, wendy.wang@intel.com, x86@kernel.org

The original topology evaluation code initialized cpu_data::topo::llc_id
with the die ID initialy and then eventually overwrite it with information
gathered from a CPUID leaf.

The conversion analysis failed to spot that particular detail and omitted
this initial assignment under the assumption that each topology evaluation
path will set it up. That assumption is mostly correct, but turns out to be
wrong in case that the CPUID leaf 0x80000006 does not provide a LLC ID.

In that case LLC ID is invalid and as a consequence the setup of the
scheduling domain CPU masks is incorrect which subsequently causes the
scheduler core to complain about it during CPU hotplug:

  BUG: arch topology borken
       the CLS domain not a subset of the MC domain

Cure it by reusing legacy_set_llc() and assigning the die ID if the LLC ID
is invalid after all possible parsers have been tried.

Fixes: f7fb3b2dd92c ("x86/cpu: Provide an AMD/HYGON specific topology parser")
Reported-by: Yuezhang Mo <Yuezhang.Mo@sony.com>
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
---
Thanks to Yuezhang for providing the debug information!
---
 arch/x86/kernel/cpu/topology_amd.c |   16 +++++++---------
 1 file changed, 7 insertions(+), 9 deletions(-)

--- a/arch/x86/kernel/cpu/topology_amd.c
+++ b/arch/x86/kernel/cpu/topology_amd.c
@@ -119,7 +119,7 @@ static bool parse_8000_001e(struct topo_
 	return true;
 }
 
-static bool parse_fam10h_node_id(struct topo_scan *tscan)
+static void parse_fam10h_node_id(struct topo_scan *tscan)
 {
 	union {
 		struct {
@@ -131,20 +131,20 @@ static bool parse_fam10h_node_id(struct
 	} nid;
 
 	if (!boot_cpu_has(X86_FEATURE_NODEID_MSR))
-		return false;
+		return;
 
 	rdmsrl(MSR_FAM10H_NODE_ID, nid.msr);
 	store_node(tscan, nid.nodes_per_pkg + 1, nid.node_id);
 	tscan->c->topo.llc_id = nid.node_id;
-	return true;
 }
 
 static void legacy_set_llc(struct topo_scan *tscan)
 {
 	unsigned int apicid = tscan->c->topo.initial_apicid;
 
-	/* parse_8000_0008() set everything up except llc_id */
-	tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
+	/* If none of the parsers set LLC ID then use the die ID for it. */
+	if (tscan->c->topo.llc_id == BAD_APICID)
+		tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN];
 }
 
 static void topoext_fixup(struct topo_scan *tscan)
@@ -187,10 +187,7 @@ static void parse_topology_amd(struct to
 		return;
 
 	/* Try the NODEID MSR */
-	if (parse_fam10h_node_id(tscan))
-		return;
-
-	legacy_set_llc(tscan);
+	parse_fam10h_node_id(tscan);
 }
 
 void cpu_parse_topology_amd(struct topo_scan *tscan)
@@ -198,6 +195,7 @@ void cpu_parse_topology_amd(struct topo_
 	tscan->amd_nodes_per_pkg = 1;
 	topoext_fixup(tscan);
 	parse_topology_amd(tscan);
+	legacy_set_llc(tscan);
 
 	if (tscan->amd_nodes_per_pkg > 1)
 		set_cpu_cap(tscan->c, X86_FEATURE_AMD_DCM);

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

* Re: [patch] x86/topology/amd: Ensure that LLC ID is initialized
  2024-05-08 19:53 ` [patch] x86/topology/amd: Ensure that LLC ID is initialized Thomas Gleixner
@ 2024-05-10  8:56   ` Yuezhang.Mo
  0 siblings, 0 replies; 5+ messages in thread
From: Yuezhang.Mo @ 2024-05-10  8:56 UTC (permalink / raw
  To: Thomas Gleixner
  Cc: andrew.cooper3@citrix.com, andy@infradead.org,
	arjan@linux.intel.com, dimitri.sivanich@hpe.com,
	feng.tang@intel.com, jgross@suse.com, kan.liang@linux.intel.com,
	kprateek.nayak@amd.com, linux-kernel@vger.kernel.org,
	mhklinux@outlook.com, paulmck@kernel.org, peterz@infradead.org,
	ray.huang@amd.com, rui.zhang@intel.com, sohil.mehta@intel.com,
	thomas.lendacky@amd.com, wendy.wang@intel.com, x86@kernel.org

After applying this patch, "BUG: Arch topology is broken" no longer
appears in dmesg both on booting and running my test script.

Tested-by: Yuezhang Mo <Yuezhang.Mo@sony.com>

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

end of thread, other threads:[~2024-05-10  8:57 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-03-14 10:21 [patch V6 11/19] x86/cpu: Use common topology code for AMD Yuezhang.Mo
2024-03-14 12:07 ` Borislav Petkov
2024-05-08 19:53 ` [patch] x86/topology/amd: Ensure that LLC ID is initialized Thomas Gleixner
2024-05-10  8:56   ` Yuezhang.Mo
  -- strict thread matches above, loose matches on Subject: below --
2024-02-13 21:03 [patch V6 00/19] x86/cpu: Rework topology evaluation Thomas Gleixner
2024-02-13 21:04 ` [patch V6 11/19] x86/cpu: Use common topology code for AMD Thomas Gleixner

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).