summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--arch/x86/kernel/cpu/common.c3
-rw-r--r--arch/x86/kernel/cpu/topology.h3
-rw-r--r--arch/x86/kernel/cpu/topology_common.c46
3 files changed, 51 insertions, 1 deletions
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index d674e7bdd6e4..004ae9cfcb63 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -892,6 +892,9 @@ void detect_ht(struct cpuinfo_x86 *c)
#ifdef CONFIG_SMP
int index_msb, core_bits;
+ if (topo_is_converted(c))
+ return;
+
if (detect_ht_early(c) < 0)
return;
diff --git a/arch/x86/kernel/cpu/topology.h b/arch/x86/kernel/cpu/topology.h
index 99c94c519b5d..934a100b9fe6 100644
--- a/arch/x86/kernel/cpu/topology.h
+++ b/arch/x86/kernel/cpu/topology.h
@@ -6,6 +6,9 @@ struct topo_scan {
struct cpuinfo_x86 *c;
unsigned int dom_shifts[TOPO_MAX_DOMAIN];
unsigned int dom_ncpus[TOPO_MAX_DOMAIN];
+
+ /* Legacy CPUID[1]:EBX[23:16] number of logical processors */
+ unsigned int ebx1_nproc_shift;
};
bool topo_is_converted(struct cpuinfo_x86 *c);
diff --git a/arch/x86/kernel/cpu/topology_common.c b/arch/x86/kernel/cpu/topology_common.c
index 873d7c3fe7ac..b0ff1fc84a13 100644
--- a/arch/x86/kernel/cpu/topology_common.c
+++ b/arch/x86/kernel/cpu/topology_common.c
@@ -24,6 +24,48 @@ void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom,
}
}
+static unsigned int __maybe_unused parse_num_cores_legacy(struct cpuinfo_x86 *c)
+{
+ struct {
+ u32 cache_type : 5,
+ unused : 21,
+ ncores : 6;
+ } eax;
+
+ if (c->cpuid_level < 4)
+ return 1;
+
+ cpuid_subleaf_reg(4, 0, CPUID_EAX, &eax);
+ if (!eax.cache_type)
+ return 1;
+
+ return eax.ncores + 1;
+}
+
+static void __maybe_unused parse_legacy(struct topo_scan *tscan)
+{
+ unsigned int cores, core_shift, smt_shift = 0;
+ struct cpuinfo_x86 *c = tscan->c;
+
+ cores = parse_num_cores_legacy(c);
+ core_shift = get_count_order(cores);
+
+ if (cpu_has(c, X86_FEATURE_HT)) {
+ if (!WARN_ON_ONCE(tscan->ebx1_nproc_shift < core_shift))
+ smt_shift = tscan->ebx1_nproc_shift - core_shift;
+ /*
+ * The parser expects leaf 0xb/0x1f format, which means
+ * the number of logical processors at core level is
+ * counting threads.
+ */
+ core_shift += smt_shift;
+ cores <<= smt_shift;
+ }
+
+ topology_set_dom(tscan, TOPO_SMT_DOMAIN, smt_shift, 1U << smt_shift);
+ topology_set_dom(tscan, TOPO_CORE_DOMAIN, core_shift, cores);
+}
+
bool topo_is_converted(struct cpuinfo_x86 *c)
{
/* Temporary until everything is converted over. */
@@ -47,7 +89,7 @@ static bool fake_topology(struct topo_scan *tscan)
* which has useless CPUID information.
*/
topology_set_dom(tscan, TOPO_SMT_DOMAIN, 0, 1);
- topology_set_dom(tscan, TOPO_CORE_DOMAIN, 1, 1);
+ topology_set_dom(tscan, TOPO_CORE_DOMAIN, 0, 1);
return tscan->c->cpuid_level < 1 || xen_pv_domain();
}
@@ -88,6 +130,8 @@ static void parse_topology(struct topo_scan *tscan, bool early)
/* The above is sufficient for UP */
if (!IS_ENABLED(CONFIG_SMP))
return;
+
+ tscan->ebx1_nproc_shift = get_count_order(ebx.nproc);
}
static void topo_set_ids(struct topo_scan *tscan)