Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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: Pu Wen <puwen@hygon.cn>
Signed-off-by: Borislav Petkov <bp@suse.de>
Reviewed-by: Borislav 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

authored by

Pu Wen and committed by
Borislav Petkov
d4f7423e 7eae653c

+34 -2
+1
arch/x86/include/asm/cacheinfo.h
··· 3 3 #define _ASM_X86_CACHEINFO_H 4 4 5 5 void cacheinfo_amd_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id); 6 + void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id); 6 7 7 8 #endif /* _ASM_X86_CACHEINFO_H */
+29 -2
arch/x86/kernel/cpu/cacheinfo.c
··· 602 602 else 603 603 amd_cpuid4(index, &eax, &ebx, &ecx); 604 604 amd_init_l3_cache(this_leaf, index); 605 + } else if (boot_cpu_data.x86_vendor == X86_VENDOR_HYGON) { 606 + cpuid_count(0x8000001d, index, &eax.full, 607 + &ebx.full, &ecx.full, &edx); 608 + amd_init_l3_cache(this_leaf, index); 605 609 } else { 606 610 cpuid_count(4, index, &eax.full, &ebx.full, &ecx.full, &edx); 607 611 } ··· 629 625 union _cpuid4_leaf_eax cache_eax; 630 626 int i = -1; 631 627 632 - if (c->x86_vendor == X86_VENDOR_AMD) 628 + if (c->x86_vendor == X86_VENDOR_AMD || 629 + c->x86_vendor == X86_VENDOR_HYGON) 633 630 op = 0x8000001d; 634 631 else 635 632 op = 4; ··· 683 678 } 684 679 } 685 680 681 + void cacheinfo_hygon_init_llc_id(struct cpuinfo_x86 *c, int cpu, u8 node_id) 682 + { 683 + /* 684 + * We may have multiple LLCs if L3 caches exist, so check if we 685 + * have an L3 cache by looking at the L3 cache CPUID leaf. 686 + */ 687 + if (!cpuid_edx(0x80000006)) 688 + return; 689 + 690 + /* 691 + * LLC is at the core complex level. 692 + * Core complex ID is ApicId[3] for these processors. 693 + */ 694 + per_cpu(cpu_llc_id, cpu) = c->apicid >> 3; 695 + } 696 + 686 697 void init_amd_cacheinfo(struct cpuinfo_x86 *c) 687 698 { 688 699 ··· 710 689 else 711 690 num_cache_leaves = 3; 712 691 } 692 + } 693 + 694 + void init_hygon_cacheinfo(struct cpuinfo_x86 *c) 695 + { 696 + num_cache_leaves = find_num_cache_leaves(c); 713 697 } 714 698 715 699 void init_intel_cacheinfo(struct cpuinfo_x86 *c) ··· 939 913 int index_msb, i; 940 914 struct cpuinfo_x86 *c = &cpu_data(cpu); 941 915 942 - if (c->x86_vendor == X86_VENDOR_AMD) { 916 + if (c->x86_vendor == X86_VENDOR_AMD || 917 + c->x86_vendor == X86_VENDOR_HYGON) { 943 918 if (__cache_amd_cpumap_setup(cpu, index, base)) 944 919 return; 945 920 }
+1
arch/x86/kernel/cpu/cpu.h
··· 54 54 enum cpuid_regs_idx reg); 55 55 extern void init_intel_cacheinfo(struct cpuinfo_x86 *c); 56 56 extern void init_amd_cacheinfo(struct cpuinfo_x86 *c); 57 + extern void init_hygon_cacheinfo(struct cpuinfo_x86 *c); 57 58 58 59 extern void detect_num_cpu_cores(struct cpuinfo_x86 *c); 59 60 extern int detect_extended_topology_early(struct cpuinfo_x86 *c);
+3
arch/x86/kernel/cpu/hygon.c
··· 87 87 if (!err) 88 88 c->x86_coreid_bits = get_count_order(c->x86_max_cores); 89 89 90 + cacheinfo_hygon_init_llc_id(c, cpu, node_id); 90 91 } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) { 91 92 u64 value; 92 93 ··· 321 320 hygon_detect_cmp(c); 322 321 hygon_get_topology(c); 323 322 srat_detect_node(c); 323 + 324 + init_hygon_cacheinfo(c); 324 325 325 326 if (cpu_has(c, X86_FEATURE_XMM2)) { 326 327 unsigned long long val;