Commit d4f7423e authored by Pu Wen's avatar Pu Wen Committed by Borislav Petkov
Browse files

x86/cpu: Get cache info and setup cache cpumap for Hygon Dhyana



The Hygon Dhyana CPU has a topology extensions bit in CPUID. With
this bit, the kernel can get the cache information. So add support in
cpuid4_cache_lookup_regs() to get the correct cache size.

The Hygon Dhyana CPU also discovers num_cache_leaves via CPUID leaf
0x8000001d, so add support to it in find_num_cache_leaves().

Also add cacheinfo_hygon_init_llc_id() and init_hygon_cacheinfo()
functions to initialize Dhyana cache info. Setup cache cpumap in the
same way as AMD does.

Signed-off-by: default avatarPu Wen <puwen@hygon.cn>
Signed-off-by: default avatarBorislav Petkov <bp@suse.de>
Reviewed-by: default avatarBorislav Petkov <bp@suse.de>
Cc: bp@alien8.de
Cc: tglx@linutronix.de
Cc: mingo@redhat.com
Cc: hpa@zytor.com
Cc: x86@kernel.org
Cc: thomas.lendacky@amd.com
Link: https://lkml.kernel.org/r/2a686b2ac0e2f5a1f2f5f101124d9dd44f949731.1537533369.git.puwen@hygon.cn
parent 7eae653c
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -3,5 +3,6 @@
#define _ASM_X86_CACHEINFO_H

void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);
void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id);

#endif /* _ASM_X86_CACHEINFO_H */
+29 −2
Original line number Diff line number Diff line
@@ -602,6 +602,10 @@ cpuid4_cache_lookup_regs(int index, struct _cpuid4_info_regs *this_leaf)
		else
			amd_cpuid4(index, &eax, &ebx, &ecx);
		amd_init_l3_cache(this_leaf, index);
	} else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) {
		cpuid_count(0x8000001d, index, &eax.full,
			    &ebx.full, &ecx.full, &edx);
		amd_init_l3_cache(this_leaf, index);
	} else {
		cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx);
	}
@@ -625,7 +629,8 @@ static int find_num_cache_leaves(struct cpuinfo_x86 *c)
	union _cpuid4_leaf_eax	cache_eax;
	int 			i = -1;

	if (c->x86_vendor == X86_VENDOR_AMD)
	if (c->x86_vendor == X86_VENDOR_AMD ||
	    c->x86_vendor == X86_VENDOR_HYGON)
		op = 0x8000001d;
	else
		op = 4;
@@ -678,6 +683,22 @@ void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id)
	}
}

void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_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))
		return;

	/*
	 * LLC is at the core complex level.
	 * Core complex ID is ApicId[3] for these processors.
	 */
	per_cpu(cpu_llc_id, cpu) = c->apicid >> 3;
}

void init_amd_cacheinfo(struct cpuinfo_x86 *c)
{

@@ -691,6 +712,11 @@ void init_amd_cacheinfo(struct cpuinfo_x86 *c)
	}
}

void init_hygon_cacheinfo(struct cpuinfo_x86 *c)
{
	num_cache_leaves = find_num_cache_leaves(c);
}

void init_intel_cacheinfo(struct cpuinfo_x86 *c)
{
	/* Cache sizes */
@@ -913,7 +939,8 @@ static void __cache_cpumap_setup(unsigned int cpu, int index,
	int index_msb, i;
	struct cpuinfo_x86 *c = &cpu_data(cpu);

	if (c->x86_vendor == X86_VENDOR_AMD) {
	if (c->x86_vendor == X86_VENDOR_AMD ||
	    c->x86_vendor == X86_VENDOR_HYGON) {
		if (__cache_amd_cpumap_setup(cpu, index, base))
			return;
	}
+1 −0
Original line number Diff line number Diff line
@@ -54,6 +54,7 @@ extern u32 get_scattered_cpuid_leaf(unsigned int level,
				    enum cpuid_regs_idx reg);
extern void init_intel_cacheinfo(struct cpuinfo_x86 *c);
extern void init_amd_cacheinfo(struct cpuinfo_x86 *c);
extern void init_hygon_cacheinfo(struct cpuinfo_x86 *c);

extern void detect_num_cpu_cores(struct cpuinfo_x86 *c);
extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
+3 −0
Original line number Diff line number Diff line
@@ -87,6 +87,7 @@ static void hygon_get_topology(struct cpuinfo_x86 *c)
		if (!err)
			c->x86_coreid_bits = get_count_order(c->x86_max_cores);

		cacheinfo_hygon_init_llc_id(c, cpu, node_id);
	} else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
		u64 value;

@@ -321,6 +322,8 @@ static void init_hygon(struct cpuinfo_x86 *c)
	hygon_get_topology(c);
	srat_detect_node(c);

	init_hygon_cacheinfo(c);

	if (cpu_has(c, X86_FEATURE_XMM2)) {
		unsigned long long val;
		int ret;