mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Ahmed S. Darwish" <darwi@linutronix.de>
To: Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>
Cc: Thomas Gleixner <tglx@linutronix.de>,
	Andrew Cooper <andrew.cooper3@citrix.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	John Ogness <john.ogness@linutronix.de>,
	x86@kernel.org, x86-cpuid@lists.linux.dev,
	LKML <linux-kernel@vger.kernel.org>,
	"Ahmed S. Darwish" <darwi@linutronix.de>
Subject: [PATCH v3 15/29] x86/cacheinfo: Separate Intel and AMD leaf 0x4 code paths
Date: Wed, 19 Mar 2025 13:21:23 +0100	[thread overview]
Message-ID: <20250319122137.4004-16-darwi@linutronix.de> (raw)
In-Reply-To: <20250319122137.4004-1-darwi@linutronix.de>

The leaf 0x4 parsing code at cpuid4_cache_lookup_regs() is ugly and
convoluted.  It is tangled with multiple nested conditions to handle:

  * AMD with TOPEXT, or Hygon CPUs via leaf 0x8000001d

  * Legacy AMD fallback via leaf 0x4 emulation

  * Intel CPUs via the actual CPUID leaf 0x4

Moreover, AMD L3 northbridge initialization is also awkwardly placed
alongside the CPUID calls of the first two scenarios above.  Refactor all
of that as follows:

  * Update AMD's leaf 0x4 emulation comment to represent current state

  * Clearly label the AMD leaf 0x4 emulation function as a fallback

  * Split AMD/Hygon and Intel code paths into separate functions

  * Move AMD L3 northbridge initialization out of CPUID leaf 0x4 code,
    and into populate_cache_leaves() where it belongs.  There,
    ci_info_init() can directly store the initialized object in the
    private pointer of the <linux/cacheinfo.h> API.

Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
---
 arch/x86/kernel/cpu/cacheinfo.c | 95 +++++++++++++++++++--------------
 1 file changed, 54 insertions(+), 41 deletions(-)

diff --git a/arch/x86/kernel/cpu/cacheinfo.c b/arch/x86/kernel/cpu/cacheinfo.c
index ea6fba942d27..10a79d87ce86 100644
--- a/arch/x86/kernel/cpu/cacheinfo.c
+++ b/arch/x86/kernel/cpu/cacheinfo.c
@@ -167,12 +167,11 @@ struct _cpuid4_info_regs {
 	unsigned long size;
 };
 
-/* AMD doesn't have CPUID4. Emulate it here to report the same
-   information to the user.  This makes some assumptions about the machine:
-   L2 not shared, no SMT etc. that is currently true on AMD CPUs.
+/*
+ * Fallback AMD CPUID(4) emulation
+ * AMD CPUs with TOPOEXT can just use CPUID(0x8000001d)
+ */
 
-   In theory the TLBs could be reported as fake type (they are in "dummy").
-   Maybe later */
 union l1_cache {
 	struct {
 		unsigned line_size:8;
@@ -228,9 +227,8 @@ static const enum cache_type cache_type_map[] = {
 	[CTYPE_UNIFIED] = CACHE_TYPE_UNIFIED,
 };
 
-static void
-amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
-	   union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx)
+static void legacy_amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
+			      union _cpuid4_leaf_ebx *ebx, union _cpuid4_leaf_ecx *ecx)
 {
 	unsigned int dummy, line_size, lines_per_tag, assoc, size_in_kb;
 	union l1_cache l1i, l1d;
@@ -297,36 +295,9 @@ amd_cpuid4(int index, union _cpuid4_leaf_eax *eax,
 		(ebx->split.ways_of_associativity + 1) - 1;
 }
 
-/*
- * Fill passed _cpuid4_info_regs structure.
- * Intel-only code paths should pass NULL for the amd_northbridge
- * return pointer.
- */
-static int cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *id4,
-				    struct amd_northbridge **nb)
+static int cpuid4_info_fill_done(struct _cpuid4_info_regs *id4, union _cpuid4_leaf_eax eax,
+				 union _cpuid4_leaf_ebx ebx, union _cpuid4_leaf_ecx ecx)
 {
-	u8 cpu_vendor = boot_cpu_data.x86_vendor;
-	union _cpuid4_leaf_eax eax;
-	union _cpuid4_leaf_ebx ebx;
-	union _cpuid4_leaf_ecx ecx;
-	u32 edx;
-
-	if (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON) {
-		if (boot_cpu_has(X86_FEATURE_TOPOEXT) || cpu_vendor == X86_VENDOR_HYGON) {
-			/* AMD with TOPOEXT, or HYGON */
-			cpuid_count(0x8000001d, index, &eax.full, &ebx.full, &ecx.full, &edx);
-		} else {
-			/* Legacy AMD fallback */
-			amd_cpuid4(index, &eax, &ebx, &ecx);
-		}
-
-		if (nb)
-			*nb = amd_init_l3_cache(index);
-	} else {
-		/* Intel */
-		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
-	}
-
 	if (eax.split.type == CTYPE_NULL)
 		return -EIO;
 
@@ -341,6 +312,42 @@ static int cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *id4,
 	return 0;
 }
 
+static int amd_fill_cpuid4_info(int index, struct _cpuid4_info_regs *id4)
+{
+	union _cpuid4_leaf_eax eax;
+	union _cpuid4_leaf_ebx ebx;
+	union _cpuid4_leaf_ecx ecx;
+	u32 ignored;
+
+	if (boot_cpu_has(X86_FEATURE_TOPOEXT) || boot_cpu_data.x86_vendor == X86_VENDOR_HYGON)
+		cpuid_count(0x8000001d, index, &eax.full, &ebx.full, &ecx.full, &ignored);
+	else
+		legacy_amd_cpuid4(index, &eax, &ebx, &ecx);
+
+	return cpuid4_info_fill_done(id4, eax, ebx, ecx);
+}
+
+static int intel_fill_cpuid4_info(int index, struct _cpuid4_info_regs *id4)
+{
+	union _cpuid4_leaf_eax eax;
+	union _cpuid4_leaf_ebx ebx;
+	union _cpuid4_leaf_ecx ecx;
+	u32 ignored;
+
+	cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &ignored);
+
+	return cpuid4_info_fill_done(id4, eax, ebx, ecx);
+}
+
+static int fill_cpuid4_info(int index, struct _cpuid4_info_regs *id4)
+{
+	u8 cpu_vendor = boot_cpu_data.x86_vendor;
+
+	return (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON) ?
+		amd_fill_cpuid4_info(index, id4) :
+		intel_fill_cpuid4_info(index, id4);
+}
+
 static int find_num_cache_leaves(struct cpuinfo_x86 *c)
 {
 	unsigned int		eax, ebx, ecx, edx, op;
@@ -472,7 +479,7 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
 			struct _cpuid4_info_regs id4 = {};
 			int retval;
 
-			retval = cpuid4_cache_lookup_regs(i, &id4, NULL);
+			retval = intel_fill_cpuid4_info(i, &id4);
 			if (retval < 0)
 				continue;
 
@@ -692,17 +699,23 @@ static void get_cache_id(int cpu, struct _cpuid4_info_regs *id4)
 
 int populate_cache_leaves(unsigned int cpu)
 {
-	unsigned int idx, ret;
 	struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
 	struct cacheinfo *ci = this_cpu_ci->info_list;
+	u8 cpu_vendor = boot_cpu_data.x86_vendor;
 	struct _cpuid4_info_regs id4 = {};
-	struct amd_northbridge *nb;
+	struct amd_northbridge *nb = NULL;
+	int idx, ret;
 
 	for (idx = 0; idx < this_cpu_ci->num_leaves; idx++) {
-		ret = cpuid4_cache_lookup_regs(idx, &id4, &nb);
+		ret = fill_cpuid4_info(idx, &id4);
 		if (ret)
 			return ret;
+
 		get_cache_id(cpu, &id4);
+
+		if (cpu_vendor == X86_VENDOR_AMD || cpu_vendor == X86_VENDOR_HYGON)
+			nb = amd_init_l3_cache(idx);
+
 		ci_info_init(ci++, &id4, nb);
 		__cache_cpumap_setup(cpu, idx, &id4);
 	}
-- 
2.48.1


  parent reply	other threads:[~2025-03-19 12:22 UTC|newest]

Thread overview: 32+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2025-03-19 12:21 [PATCH v3 00/29] x86: Leaf 0x2 and leaf 0x4 refactorings Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 01/29] x86/cpu: Remove leaf 0x2 parsing loop Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 02/29] x86/cacheinfo: " Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 03/29] x86/cpu: Introduce and use leaf 0x2 parsing helpers Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 04/29] x86/cacheinfo: Use " Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 05/29] x86/cacheinfo: Refactor leaf 0x2 cache descriptor lookup Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 06/29] x86/cacheinfo: Properly name amd_cpuid4()'s first parameter Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 07/29] x86/cacheinfo: Use proper name for cacheinfo instances Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 08/29] x86/cacheinfo: Constify _cpuid4_info_regs instances Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 09/29] x86/cacheinfo: Align ci_info_init() assignment expressions Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 10/29] x86/cacheinfo: Standardize _cpuid4_info_regs instance naming Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 11/29] x86/cacheinfo: Consolidate AMD/Hygon leaf 0x8000001d calls Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 12/29] x86/cacheinfo: Separate amd_northbridge from _cpuid4_info_regs Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 13/29] x86/cacheinfo: Move AMD cache_disable_0/1 handling to separate file Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 14/29] x86/cacheinfo: Use sysfs_emit() for sysfs attributes show() Ahmed S. Darwish
2025-03-19 12:21 ` Ahmed S. Darwish [this message]
2025-03-19 12:21 ` [PATCH v3 16/29] x86/cacheinfo: Rename _cpuid4_info_regs to _cpuid4_info Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 17/29] x86/cacheinfo: Clarify type markers for leaf 0x2 cache descriptors Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 18/29] x86/cacheinfo: Use enums for cache descriptor types Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 19/29] x86/cpu: Use enums for TLB " Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 20/29] x86/cpu: Consolidate CPUID leaf 0x2 tables Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 21/29] x86/cacheinfo: Use consolidated leaf 0x2 descriptor table Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 22/29] x86/cpu: " Ahmed S. Darwish
2025-03-24  7:37   ` kernel test robot
2025-03-24 11:15     ` Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 23/29] x86/cacheinfo: Separate leaf 0x2 handling and post-processing logic Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 24/29] x86/cacheinfo: Separate Intel leaf 0x4 handling Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 25/29] x86/cacheinfo: Extract out cache level topology ID calculation Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 26/29] x86/cacheinfo: Extract out cache self-snoop checks Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 27/29] x86/cacheinfo: Relocate leaf 0x4 cache_type mapping Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 28/29] x86/cacheinfo: Introduce cpuid_amd_hygon_has_l3_cache() Ahmed S. Darwish
2025-03-19 12:21 ` [PATCH v3 29/29] x86/cacheinfo: Apply maintainer-tip coding style fixes Ahmed S. Darwish

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250319122137.4004-16-darwi@linutronix.de \
    --to=darwi@linutronix.de \
    --cc=andrew.cooper3@citrix.com \
    --cc=bp@alien8.de \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=john.ogness@linutronix.de \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@linutronix.de \
    --cc=x86-cpuid@lists.linux.dev \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®