mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2025-01-01 02:36:02 +00:00
x86/cacheinfo: Delete global num_cache_leaves
Linux remembers cpu_cachinfo::num_leaves per CPU, but x86 initializes all CPUs from the same global "num_cache_leaves". This is erroneous on systems such as Meteor Lake, where each CPU has a distinct num_leaves value. Delete the global "num_cache_leaves" and initialize num_leaves on each CPU. init_cache_level() no longer needs to set num_leaves. Also, it never had to set num_levels as it is unnecessary in x86. Keep checking for zero cache leaves. Such condition indicates a bug. [ bp: Cleanup. ] Signed-off-by: Ricardo Neri <ricardo.neri-calderon@linux.intel.com> Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Cc: stable@vger.kernel.org # 6.3+ Link: https://lore.kernel.org/r/20241128002247.26726-3-ricardo.neri-calderon@linux.intel.com
This commit is contained in:
parent
b3fce429a1
commit
9677be09e5
@ -178,8 +178,6 @@ struct _cpuid4_info_regs {
|
|||||||
struct amd_northbridge *nb;
|
struct amd_northbridge *nb;
|
||||||
};
|
};
|
||||||
|
|
||||||
static unsigned short num_cache_leaves;
|
|
||||||
|
|
||||||
/* AMD doesn't have CPUID4. Emulate it here to report the same
|
/* AMD doesn't have CPUID4. Emulate it here to report the same
|
||||||
information to the user. This makes some assumptions about the machine:
|
information to the user. This makes some assumptions about the machine:
|
||||||
L2 not shared, no SMT etc. that is currently true on AMD CPUs.
|
L2 not shared, no SMT etc. that is currently true on AMD CPUs.
|
||||||
@ -717,20 +715,23 @@ void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
|
|||||||
|
|
||||||
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
|
void init_amd_cacheinfo(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
|
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
|
||||||
|
|
||||||
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
|
||||||
num_cache_leaves = find_num_cache_leaves(c);
|
ci->num_leaves = find_num_cache_leaves(c);
|
||||||
} else if (c->extended_cpuid_level >= 0x80000006) {
|
} else if (c->extended_cpuid_level >= 0x80000006) {
|
||||||
if (cpuid_edx(0x80000006) & 0xf000)
|
if (cpuid_edx(0x80000006) & 0xf000)
|
||||||
num_cache_leaves = 4;
|
ci->num_leaves = 4;
|
||||||
else
|
else
|
||||||
num_cache_leaves = 3;
|
ci->num_leaves = 3;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
|
void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
|
||||||
{
|
{
|
||||||
num_cache_leaves = find_num_cache_leaves(c);
|
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
|
||||||
|
|
||||||
|
ci->num_leaves = find_num_cache_leaves(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
void init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
||||||
@ -740,21 +741,21 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
|||||||
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
|
unsigned int new_l1d = 0, new_l1i = 0; /* Cache sizes from cpuid(4) */
|
||||||
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
|
unsigned int new_l2 = 0, new_l3 = 0, i; /* Cache sizes from cpuid(4) */
|
||||||
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
|
unsigned int l2_id = 0, l3_id = 0, num_threads_sharing, index_msb;
|
||||||
|
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(c->cpu_index);
|
||||||
|
|
||||||
if (c->cpuid_level > 3) {
|
if (c->cpuid_level > 3) {
|
||||||
static int is_initialized;
|
/*
|
||||||
|
* There should be at least one leaf. A non-zero value means
|
||||||
if (is_initialized == 0) {
|
* that the number of leaves has been initialized.
|
||||||
/* Init num_cache_leaves from boot CPU */
|
*/
|
||||||
num_cache_leaves = find_num_cache_leaves(c);
|
if (!ci->num_leaves)
|
||||||
is_initialized++;
|
ci->num_leaves = find_num_cache_leaves(c);
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Whenever possible use cpuid(4), deterministic cache
|
* Whenever possible use cpuid(4), deterministic cache
|
||||||
* parameters cpuid leaf to find the cache details
|
* parameters cpuid leaf to find the cache details
|
||||||
*/
|
*/
|
||||||
for (i = 0; i < num_cache_leaves; i++) {
|
for (i = 0; i < ci->num_leaves; i++) {
|
||||||
struct _cpuid4_info_regs this_leaf = {};
|
struct _cpuid4_info_regs this_leaf = {};
|
||||||
int retval;
|
int retval;
|
||||||
|
|
||||||
@ -790,14 +791,14 @@ void init_intel_cacheinfo(struct cpuinfo_x86 *c)
|
|||||||
* Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
|
* Don't use cpuid2 if cpuid4 is supported. For P4, we use cpuid2 for
|
||||||
* trace cache
|
* trace cache
|
||||||
*/
|
*/
|
||||||
if ((num_cache_leaves == 0 || c->x86 == 15) && c->cpuid_level > 1) {
|
if ((!ci->num_leaves || c->x86 == 15) && c->cpuid_level > 1) {
|
||||||
/* supports eax=2 call */
|
/* supports eax=2 call */
|
||||||
int j, n;
|
int j, n;
|
||||||
unsigned int regs[4];
|
unsigned int regs[4];
|
||||||
unsigned char *dp = (unsigned char *)regs;
|
unsigned char *dp = (unsigned char *)regs;
|
||||||
int only_trace = 0;
|
int only_trace = 0;
|
||||||
|
|
||||||
if (num_cache_leaves != 0 && c->x86 == 15)
|
if (ci->num_leaves && c->x86 == 15)
|
||||||
only_trace = 1;
|
only_trace = 1;
|
||||||
|
|
||||||
/* Number of times to iterate */
|
/* Number of times to iterate */
|
||||||
@ -991,14 +992,12 @@ static void ci_leaf_init(struct cacheinfo *this_leaf,
|
|||||||
|
|
||||||
int init_cache_level(unsigned int cpu)
|
int init_cache_level(unsigned int cpu)
|
||||||
{
|
{
|
||||||
struct cpu_cacheinfo *this_cpu_ci = get_cpu_cacheinfo(cpu);
|
struct cpu_cacheinfo *ci = get_cpu_cacheinfo(cpu);
|
||||||
|
|
||||||
if (!num_cache_leaves)
|
/* There should be at least one leaf. */
|
||||||
|
if (!ci->num_leaves)
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
if (!this_cpu_ci)
|
|
||||||
return -EINVAL;
|
|
||||||
this_cpu_ci->num_levels = 3;
|
|
||||||
this_cpu_ci->num_leaves = num_cache_leaves;
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user