From 598ebce64c4cfaca54cbecdc25a7ef56ea701051 Mon Sep 17 00:00:00 2001 From: "Borislav Petkov (AMD)" Date: Tue, 21 Jul 2026 21:15:12 +0530 Subject: x86/topo: Map vendor CPU types to generic Linux such types MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sashiko reported¹ that a confusion could ensue if a vendor-specific CPU type 0 (performance) gets attempted to be used in a x86_cpu_id match table. The current logic treats 0 as the wildcard X86_CPU_TYPE_ANY and such a thing would end up matching the wrong CPUs. This is all backwards because we started using the vendor-specific CPU type number instead of using a Linux-defined, generic CPU type which is agnostic. Convert the current logic to it before users start appearing. ¹https://sashiko.dev/#/patchset/20260629094349.533301-1-Vishal.Badole%40amd.com Signed-off-by: Borislav Petkov (AMD) Signed-off-by: Vishal Badole Link: https://patch.msgid.link/20260721154514.2506972-2-Vishal.Badole@amd.com --- arch/x86/include/asm/processor.h | 18 ++++++++++++++---- arch/x86/include/asm/topology.h | 7 ------- arch/x86/kernel/acpi/cppc.c | 4 ++-- arch/x86/kernel/cpu/match.c | 30 +----------------------------- arch/x86/kernel/cpu/topology.h | 1 + arch/x86/kernel/cpu/topology_amd.c | 6 ++++-- arch/x86/kernel/cpu/topology_common.c | 8 ++++++-- 7 files changed, 28 insertions(+), 46 deletions(-) (limited to 'arch/x86') diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 87b1d4c0727e..fc0350fe8f5e 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -68,9 +68,13 @@ extern u16 __read_mostly tlb_lld_2m; extern u16 __read_mostly tlb_lld_4m; extern u16 __read_mostly tlb_lld_1g; -/* - * CPU type and hardware bug flags. Kept separately for each CPU. - */ +enum x86_topology_cpu_type { + /* X86_CPU_TYPE_ANY */ + TOPO_CPU_TYPE_ANY = 0, + TOPO_CPU_TYPE_PERFORMANCE, + TOPO_CPU_TYPE_EFFICIENCY, + TOPO_CPU_TYPE_UNKNOWN, +}; struct cpuinfo_topology { // Real APIC ID read from the local APIC @@ -104,7 +108,7 @@ struct cpuinfo_topology { // Hardware defined CPU-type union { - u32 cpu_type; + u32 hw_cpu_type; struct { // CPUID.1A.EAX[23-0] u32 intel_native_model_id :24; @@ -119,8 +123,14 @@ struct cpuinfo_topology { amd_type :4; }; }; + + // Linux vendor-agnostic CPU type + enum x86_topology_cpu_type cpu_type; }; +/* + * CPU type and hardware bug flags. Kept separately for each CPU. + */ struct cpuinfo_x86 { union { /* diff --git a/arch/x86/include/asm/topology.h b/arch/x86/include/asm/topology.h index 8fb61d2465eb..ef76ba674f1b 100644 --- a/arch/x86/include/asm/topology.h +++ b/arch/x86/include/asm/topology.h @@ -114,12 +114,6 @@ enum x86_topology_domains { TOPO_MAX_DOMAIN, }; -enum x86_topology_cpu_type { - TOPO_CPU_TYPE_PERFORMANCE, - TOPO_CPU_TYPE_EFFICIENCY, - TOPO_CPU_TYPE_UNKNOWN, -}; - struct x86_topology_system { unsigned int dom_shifts[TOPO_MAX_DOMAIN]; unsigned int dom_size[TOPO_MAX_DOMAIN]; @@ -160,7 +154,6 @@ extern unsigned int __num_nodes_per_package; struct cpuinfo_x86; const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c); -enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); static inline unsigned int topology_max_packages(void) { diff --git a/arch/x86/kernel/acpi/cppc.c b/arch/x86/kernel/acpi/cppc.c index be4c5e9e5ff6..b8f5dd0a8117 100644 --- a/arch/x86/kernel/acpi/cppc.c +++ b/arch/x86/kernel/acpi/cppc.c @@ -241,7 +241,6 @@ EXPORT_SYMBOL_GPL(amd_detect_prefcore); */ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) { - enum x86_topology_cpu_type core_type = get_topology_cpu_type(&cpu_data(cpu)); bool prefcore; int ret; u32 tmp; @@ -273,8 +272,9 @@ int amd_get_boost_ratio_numerator(unsigned int cpu, u64 *numerator) /* detect if running on heterogeneous design */ if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) { - switch (core_type) { + switch (cpu_data(cpu).topo.cpu_type) { case TOPO_CPU_TYPE_UNKNOWN: + case TOPO_CPU_TYPE_ANY: pr_warn("Undefined core type found for cpu %d\n", cpu); break; case TOPO_CPU_TYPE_PERFORMANCE: diff --git a/arch/x86/kernel/cpu/match.c b/arch/x86/kernel/cpu/match.c index 4604802692da..7ab077f0cc66 100644 --- a/arch/x86/kernel/cpu/match.c +++ b/arch/x86/kernel/cpu/match.c @@ -5,34 +5,6 @@ #include #include -/** - * x86_match_vendor_cpu_type - helper function to match the hardware defined - * cpu-type for a single entry in the x86_cpu_id - * table. Note, this function does not match the - * generic cpu-types TOPO_CPU_TYPE_EFFICIENCY and - * TOPO_CPU_TYPE_PERFORMANCE. - * @c: Pointer to the cpuinfo_x86 structure of the CPU to match. - * @m: Pointer to the x86_cpu_id entry to match against. - * - * Return: true if the cpu-type matches, false otherwise. - */ -static bool x86_match_vendor_cpu_type(struct cpuinfo_x86 *c, const struct x86_cpu_id *m) -{ - if (m->type == X86_CPU_TYPE_ANY) - return true; - - /* Hybrid CPUs are special, they are assumed to match all cpu-types */ - if (cpu_feature_enabled(X86_FEATURE_HYBRID_CPU)) - return true; - - if (c->x86_vendor == X86_VENDOR_INTEL) - return m->type == c->topo.intel_type; - if (c->x86_vendor == X86_VENDOR_AMD) - return m->type == c->topo.amd_type; - - return false; -} - /** * x86_match_cpu - match current CPU against an array of x86_cpu_ids * @match: Pointer to array of x86_cpu_ids. Last entry terminated with @@ -81,7 +53,7 @@ const struct x86_cpu_id *x86_match_cpu(const struct x86_cpu_id *match) continue; if (m->feature != X86_FEATURE_ANY && !cpu_has(c, m->feature)) continue; - if (!x86_match_vendor_cpu_type(c, m)) + if (m->type != X86_CPU_TYPE_ANY && c->topo.cpu_type != m->type) continue; return m; } diff --git a/arch/x86/kernel/cpu/topology.h b/arch/x86/kernel/cpu/topology.h index 37326297f80c..74e02bacd854 100644 --- a/arch/x86/kernel/cpu/topology.h +++ b/arch/x86/kernel/cpu/topology.h @@ -22,6 +22,7 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom, bool cpu_parse_topology_ext(struct topo_scan *tscan); void cpu_parse_topology_amd(struct topo_scan *tscan); void cpu_topology_fixup_amd(struct topo_scan *tscan); +enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c); static inline u32 topo_shift_apicid(u32 apicid, enum x86_topology_domains dom) { diff --git a/arch/x86/kernel/cpu/topology_amd.c b/arch/x86/kernel/cpu/topology_amd.c index da080d732e10..c5a6944df86a 100644 --- a/arch/x86/kernel/cpu/topology_amd.c +++ b/arch/x86/kernel/cpu/topology_amd.c @@ -177,8 +177,10 @@ static void topoext_fixup(struct topo_scan *tscan) static void parse_topology_amd(struct topo_scan *tscan) { - if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) - tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); + if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) { + tscan->c->topo.hw_cpu_type = cpuid_ebx(0x80000026); + tscan->c->topo.cpu_type = get_topology_cpu_type(tscan->c); + } /* * Try to get SMT, CORE, TILE, and DIE shifts from extended diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c index cf7513416b70..b9d025f3373a 100644 --- a/arch/x86/kernel/cpu/topology_common.c +++ b/arch/x86/kernel/cpu/topology_common.c @@ -168,8 +168,12 @@ static void parse_topology(struct topo_scan *tscan, bool early) case X86_VENDOR_INTEL: if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan)) parse_legacy(tscan); - if (c->cpuid_level >= 0x1a) - c->topo.cpu_type = cpuid_eax(0x1a); + + if (c->cpuid_level >= 0x1a) { + c->topo.hw_cpu_type = cpuid_eax(0x1a); + c->topo.cpu_type = get_topology_cpu_type(c); + } + break; } } -- cgit v1.2.3