Commit 2b12a7a1 authored by Zhang Rui's avatar Zhang Rui Committed by Dave Hansen

x86/topology: Fix multiple packages shown on a single-package system

CPUID.1F/B does not enumerate Package level explicitly, instead, all the
APIC-ID bits above the enumerated levels are assumed to be package ID
bits.

Current code gets package ID by shifting out all the APIC-ID bits that
Linux supports, rather than shifting out all the APIC-ID bits that
CPUID.1F enumerates. This introduces problems when CPUID.1F enumerates a
level that Linux does not support.

For example, on a single package AlderLake-N, there are 2 Ecore Modules
with 4 atom cores in each module.  Linux does not support the Module
level and interprets the Module ID bits as package ID and erroneously
reports a multi module system as a multi-package system.

Fix this by using APIC-ID bits above all the CPUID.1F enumerated levels
as package ID.

[ dhansen: spelling fix ]

Fixes: 7745f03e ("x86/topology: Add CPUID.1F multi-die/package support")
Suggested-by: default avatarLen Brown <len.brown@intel.com>
Signed-off-by: default avatarZhang Rui <rui.zhang@intel.com>
Signed-off-by: default avatarDave Hansen <dave.hansen@linux.intel.com>
Reviewed-by: default avatarLen Brown <len.brown@intel.com>
Cc: stable@vger.kernel.org
Link: https://lkml.kernel.org/r/20221014090147.1836-4-rui.zhang@intel.com
parent 7108b80a
...@@ -96,6 +96,7 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -96,6 +96,7 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width; unsigned int ht_mask_width, core_plus_mask_width, die_plus_mask_width;
unsigned int core_select_mask, core_level_siblings; unsigned int core_select_mask, core_level_siblings;
unsigned int die_select_mask, die_level_siblings; unsigned int die_select_mask, die_level_siblings;
unsigned int pkg_mask_width;
bool die_level_present = false; bool die_level_present = false;
int leaf; int leaf;
...@@ -111,10 +112,10 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -111,10 +112,10 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx); core_level_siblings = smp_num_siblings = LEVEL_MAX_SIBLINGS(ebx);
core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); core_plus_mask_width = ht_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
die_level_siblings = LEVEL_MAX_SIBLINGS(ebx); die_level_siblings = LEVEL_MAX_SIBLINGS(ebx);
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); pkg_mask_width = die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
sub_index = 1; sub_index = 1;
do { while (true) {
cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx); cpuid_count(leaf, sub_index, &eax, &ebx, &ecx, &edx);
/* /*
...@@ -132,8 +133,13 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -132,8 +133,13 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax); die_plus_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
} }
if (LEAFB_SUBTYPE(ecx) != INVALID_TYPE)
pkg_mask_width = BITS_SHIFT_NEXT_LEVEL(eax);
else
break;
sub_index++; sub_index++;
} while (LEAFB_SUBTYPE(ecx) != INVALID_TYPE); }
core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width; core_select_mask = (~(-1 << core_plus_mask_width)) >> ht_mask_width;
die_select_mask = (~(-1 << die_plus_mask_width)) >> die_select_mask = (~(-1 << die_plus_mask_width)) >>
...@@ -148,7 +154,7 @@ int detect_extended_topology(struct cpuinfo_x86 *c) ...@@ -148,7 +154,7 @@ int detect_extended_topology(struct cpuinfo_x86 *c)
} }
c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid, c->phys_proc_id = apic->phys_pkg_id(c->initial_apicid,
die_plus_mask_width); pkg_mask_width);
/* /*
* Reinit the apicid, now that we have extended initial_apicid. * Reinit the apicid, now that we have extended initial_apicid.
*/ */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment