x86/cacheinfo: Introduce cpuid_amd_hygon_has_l3_cache()

Multiple code paths at cacheinfo.c and amd_nb.c check for AMD/Hygon CPUs
L3 cache presensce by directly checking leaf 0x80000006 EDX output.

Extract that logic into its own function.  While at it, rework the
AMD/Hygon LLC topology ID caclculation comments for clarity.

Signed-off-by: Ahmed S. Darwish <darwi@linutronix.de>
Signed-off-by: Ingo Molnar <mingo@kernel.org>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Link: https://lore.kernel.org/r/20250324133324.23458-29-darwi@linutronix.de
This commit is contained in:
Ahmed S. Darwish 2025-03-24 14:33:23 +01:00 committed by Ingo Molnar
parent eeeebc4fc6
commit 6c963c42fc
3 changed files with 26 additions and 22 deletions

View File

@ -207,4 +207,13 @@ static inline u32 hypervisor_cpuid_base(const char *sig, u32 leaves)
return 0;
}
/*
* CPUID(0x80000006) parsing helpers
*/
static inline bool cpuid_amd_hygon_has_l3_cache(void)
{
return cpuid_edx(0x80000006);
}
#endif /* _ASM_X86_CPUID_API_H */

View File

@ -13,7 +13,9 @@
#include <linux/export.h>
#include <linux/spinlock.h>
#include <linux/pci_ids.h>
#include <asm/amd_nb.h>
#include <asm/cpuid.h>
static u32 *flush_words;
@ -91,10 +93,7 @@ static int amd_cache_northbridges(void)
if (amd_gart_present())
amd_northbridges.flags |= AMD_NB_GART;
/*
* Check for L3 cache presence.
*/
if (!cpuid_edx(0x80000006))
if (!cpuid_amd_hygon_has_l3_cache())
return 0;
/*

View File

@ -281,29 +281,29 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
return i;
}
/*
* AMD/Hygon CPUs may have multiple LLCs if L3 caches exist.
*/
void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
{
/*
* We may have multiple LLCs if L3 caches exist, so check if we
* have an L3 cache by looking at the L3 cache CPUID leaf.
*/
if (!cpuid_edx(0x80000006))
if (!cpuid_amd_hygon_has_l3_cache())
return;
if (c->x86 < 0x17) {
/* LLC is at the node level. */
/* Pre-Zen: LLC is at the node level */
c->topo.llc_id = die_id;
} else if (c->x86 == 0x17 && c->x86_model <= 0x1F) {
/*
* LLC is at the core complex level.
* Core complex ID is ApicId[3] for these processors.
* Family 17h up to 1F models: LLC is at the core
* complex level. Core complex ID is ApicId[3].
*/
c->topo.llc_id = c->topo.apicid >> 3;
} else {
/*
* LLC ID is calculated from the number of threads sharing the
* cache.
* */
* Newer families: LLC ID is calculated from the number
* of threads sharing the L3 cache.
*/
u32 eax, ebx, ecx, edx, num_sharing_cache = 0;
u32 llc_index = find_num_cache_leaves(c) - 1;
@ -321,16 +321,12 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, u16 die_id)
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c)
{
/*
* We may have multiple LLCs if L3 caches exist, so check if we
* have an L3 cache by looking at the L3 cache CPUID leaf.
*/
if (!cpuid_edx(0x80000006))
if (!cpuid_amd_hygon_has_l3_cache())
return;
/*
* LLC is at the core complex level.
* Core complex ID is ApicId[3] for these processors.
* Hygons are similar to AMD Family 17h up to 1F models: LLC is
* at the core complex level. Core complex ID is ApicId[3].
*/
c->topo.llc_id = c->topo.apicid >> 3;
}