Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0+
0002 /*
0003  * Hygon Processor Support for Linux
0004  *
0005  * Copyright (C) 2018 Chengdu Haiguang IC Design Co., Ltd.
0006  *
0007  * Author: Pu Wen <puwen@hygon.cn>
0008  */
0009 #include <linux/io.h>
0010 
0011 #include <asm/cpu.h>
0012 #include <asm/smp.h>
0013 #include <asm/numa.h>
0014 #include <asm/cacheinfo.h>
0015 #include <asm/spec-ctrl.h>
0016 #include <asm/delay.h>
0017 
0018 #include "cpu.h"
0019 
0020 #define APICID_SOCKET_ID_BIT 6
0021 
0022 /*
0023  * nodes_per_socket: Stores the number of nodes per socket.
0024  * Refer to CPUID Fn8000_001E_ECX Node Identifiers[10:8]
0025  */
0026 static u32 nodes_per_socket = 1;
0027 
0028 #ifdef CONFIG_NUMA
0029 /*
0030  * To workaround broken NUMA config.  Read the comment in
0031  * srat_detect_node().
0032  */
0033 static int nearby_node(int apicid)
0034 {
0035     int i, node;
0036 
0037     for (i = apicid - 1; i >= 0; i--) {
0038         node = __apicid_to_node[i];
0039         if (node != NUMA_NO_NODE && node_online(node))
0040             return node;
0041     }
0042     for (i = apicid + 1; i < MAX_LOCAL_APIC; i++) {
0043         node = __apicid_to_node[i];
0044         if (node != NUMA_NO_NODE && node_online(node))
0045             return node;
0046     }
0047     return first_node(node_online_map); /* Shouldn't happen */
0048 }
0049 #endif
0050 
0051 static void hygon_get_topology_early(struct cpuinfo_x86 *c)
0052 {
0053     if (cpu_has(c, X86_FEATURE_TOPOEXT))
0054         smp_num_siblings = ((cpuid_ebx(0x8000001e) >> 8) & 0xff) + 1;
0055 }
0056 
0057 /*
0058  * Fixup core topology information for
0059  * (1) Hygon multi-node processors
0060  *     Assumption: Number of cores in each internal node is the same.
0061  * (2) Hygon processors supporting compute units
0062  */
0063 static void hygon_get_topology(struct cpuinfo_x86 *c)
0064 {
0065     int cpu = smp_processor_id();
0066 
0067     /* get information required for multi-node processors */
0068     if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
0069         int err;
0070         u32 eax, ebx, ecx, edx;
0071 
0072         cpuid(0x8000001e, &eax, &ebx, &ecx, &edx);
0073 
0074         c->cpu_die_id  = ecx & 0xff;
0075 
0076         c->cpu_core_id = ebx & 0xff;
0077 
0078         if (smp_num_siblings > 1)
0079             c->x86_max_cores /= smp_num_siblings;
0080 
0081         /*
0082          * In case leaf B is available, use it to derive
0083          * topology information.
0084          */
0085         err = detect_extended_topology(c);
0086         if (!err)
0087             c->x86_coreid_bits = get_count_order(c->x86_max_cores);
0088 
0089         /* Socket ID is ApicId[6] for these processors. */
0090         c->phys_proc_id = c->apicid >> APICID_SOCKET_ID_BIT;
0091 
0092         cacheinfo_hygon_init_llc_id(c, cpu);
0093     } else if (cpu_has(c, X86_FEATURE_NODEID_MSR)) {
0094         u64 value;
0095 
0096         rdmsrl(MSR_FAM10H_NODE_ID, value);
0097         c->cpu_die_id = value & 7;
0098 
0099         per_cpu(cpu_llc_id, cpu) = c->cpu_die_id;
0100     } else
0101         return;
0102 
0103     if (nodes_per_socket > 1)
0104         set_cpu_cap(c, X86_FEATURE_AMD_DCM);
0105 }
0106 
0107 /*
0108  * On Hygon setup the lower bits of the APIC id distinguish the cores.
0109  * Assumes number of cores is a power of two.
0110  */
0111 static void hygon_detect_cmp(struct cpuinfo_x86 *c)
0112 {
0113     unsigned int bits;
0114     int cpu = smp_processor_id();
0115 
0116     bits = c->x86_coreid_bits;
0117     /* Low order bits define the core id (index of core in socket) */
0118     c->cpu_core_id = c->initial_apicid & ((1 << bits)-1);
0119     /* Convert the initial APIC ID into the socket ID */
0120     c->phys_proc_id = c->initial_apicid >> bits;
0121     /* use socket ID also for last level cache */
0122     per_cpu(cpu_llc_id, cpu) = c->cpu_die_id = c->phys_proc_id;
0123 }
0124 
0125 static void srat_detect_node(struct cpuinfo_x86 *c)
0126 {
0127 #ifdef CONFIG_NUMA
0128     int cpu = smp_processor_id();
0129     int node;
0130     unsigned int apicid = c->apicid;
0131 
0132     node = numa_cpu_node(cpu);
0133     if (node == NUMA_NO_NODE)
0134         node = per_cpu(cpu_llc_id, cpu);
0135 
0136     /*
0137      * On multi-fabric platform (e.g. Numascale NumaChip) a
0138      * platform-specific handler needs to be called to fixup some
0139      * IDs of the CPU.
0140      */
0141     if (x86_cpuinit.fixup_cpu_id)
0142         x86_cpuinit.fixup_cpu_id(c, node);
0143 
0144     if (!node_online(node)) {
0145         /*
0146          * Two possibilities here:
0147          *
0148          * - The CPU is missing memory and no node was created.  In
0149          *   that case try picking one from a nearby CPU.
0150          *
0151          * - The APIC IDs differ from the HyperTransport node IDs.
0152          *   Assume they are all increased by a constant offset, but
0153          *   in the same order as the HT nodeids.  If that doesn't
0154          *   result in a usable node fall back to the path for the
0155          *   previous case.
0156          *
0157          * This workaround operates directly on the mapping between
0158          * APIC ID and NUMA node, assuming certain relationship
0159          * between APIC ID, HT node ID and NUMA topology.  As going
0160          * through CPU mapping may alter the outcome, directly
0161          * access __apicid_to_node[].
0162          */
0163         int ht_nodeid = c->initial_apicid;
0164 
0165         if (__apicid_to_node[ht_nodeid] != NUMA_NO_NODE)
0166             node = __apicid_to_node[ht_nodeid];
0167         /* Pick a nearby node */
0168         if (!node_online(node))
0169             node = nearby_node(apicid);
0170     }
0171     numa_set_node(cpu, node);
0172 #endif
0173 }
0174 
0175 static void early_init_hygon_mc(struct cpuinfo_x86 *c)
0176 {
0177 #ifdef CONFIG_SMP
0178     unsigned int bits, ecx;
0179 
0180     /* Multi core CPU? */
0181     if (c->extended_cpuid_level < 0x80000008)
0182         return;
0183 
0184     ecx = cpuid_ecx(0x80000008);
0185 
0186     c->x86_max_cores = (ecx & 0xff) + 1;
0187 
0188     /* CPU telling us the core id bits shift? */
0189     bits = (ecx >> 12) & 0xF;
0190 
0191     /* Otherwise recompute */
0192     if (bits == 0) {
0193         while ((1 << bits) < c->x86_max_cores)
0194             bits++;
0195     }
0196 
0197     c->x86_coreid_bits = bits;
0198 #endif
0199 }
0200 
0201 static void bsp_init_hygon(struct cpuinfo_x86 *c)
0202 {
0203     if (cpu_has(c, X86_FEATURE_CONSTANT_TSC)) {
0204         u64 val;
0205 
0206         rdmsrl(MSR_K7_HWCR, val);
0207         if (!(val & BIT(24)))
0208             pr_warn(FW_BUG "TSC doesn't count with P0 frequency!\n");
0209     }
0210 
0211     if (cpu_has(c, X86_FEATURE_MWAITX))
0212         use_mwaitx_delay();
0213 
0214     if (boot_cpu_has(X86_FEATURE_TOPOEXT)) {
0215         u32 ecx;
0216 
0217         ecx = cpuid_ecx(0x8000001e);
0218         __max_die_per_package = nodes_per_socket = ((ecx >> 8) & 7) + 1;
0219     } else if (boot_cpu_has(X86_FEATURE_NODEID_MSR)) {
0220         u64 value;
0221 
0222         rdmsrl(MSR_FAM10H_NODE_ID, value);
0223         __max_die_per_package = nodes_per_socket = ((value >> 3) & 7) + 1;
0224     }
0225 
0226     if (!boot_cpu_has(X86_FEATURE_AMD_SSBD) &&
0227         !boot_cpu_has(X86_FEATURE_VIRT_SSBD)) {
0228         /*
0229          * Try to cache the base value so further operations can
0230          * avoid RMW. If that faults, do not enable SSBD.
0231          */
0232         if (!rdmsrl_safe(MSR_AMD64_LS_CFG, &x86_amd_ls_cfg_base)) {
0233             setup_force_cpu_cap(X86_FEATURE_LS_CFG_SSBD);
0234             setup_force_cpu_cap(X86_FEATURE_SSBD);
0235             x86_amd_ls_cfg_ssbd_mask = 1ULL << 10;
0236         }
0237     }
0238 }
0239 
0240 static void early_init_hygon(struct cpuinfo_x86 *c)
0241 {
0242     u32 dummy;
0243 
0244     early_init_hygon_mc(c);
0245 
0246     set_cpu_cap(c, X86_FEATURE_K8);
0247 
0248     rdmsr_safe(MSR_AMD64_PATCH_LEVEL, &c->microcode, &dummy);
0249 
0250     /*
0251      * c->x86_power is 8000_0007 edx. Bit 8 is TSC runs at constant rate
0252      * with P/T states and does not stop in deep C-states
0253      */
0254     if (c->x86_power & (1 << 8)) {
0255         set_cpu_cap(c, X86_FEATURE_CONSTANT_TSC);
0256         set_cpu_cap(c, X86_FEATURE_NONSTOP_TSC);
0257     }
0258 
0259     /* Bit 12 of 8000_0007 edx is accumulated power mechanism. */
0260     if (c->x86_power & BIT(12))
0261         set_cpu_cap(c, X86_FEATURE_ACC_POWER);
0262 
0263     /* Bit 14 indicates the Runtime Average Power Limit interface. */
0264     if (c->x86_power & BIT(14))
0265         set_cpu_cap(c, X86_FEATURE_RAPL);
0266 
0267 #ifdef CONFIG_X86_64
0268     set_cpu_cap(c, X86_FEATURE_SYSCALL32);
0269 #endif
0270 
0271 #if defined(CONFIG_X86_LOCAL_APIC) && defined(CONFIG_PCI)
0272     /*
0273      * ApicID can always be treated as an 8-bit value for Hygon APIC So, we
0274      * can safely set X86_FEATURE_EXTD_APICID unconditionally.
0275      */
0276     if (boot_cpu_has(X86_FEATURE_APIC))
0277         set_cpu_cap(c, X86_FEATURE_EXTD_APICID);
0278 #endif
0279 
0280     /*
0281      * This is only needed to tell the kernel whether to use VMCALL
0282      * and VMMCALL.  VMMCALL is never executed except under virt, so
0283      * we can set it unconditionally.
0284      */
0285     set_cpu_cap(c, X86_FEATURE_VMMCALL);
0286 
0287     hygon_get_topology_early(c);
0288 }
0289 
0290 static void init_hygon(struct cpuinfo_x86 *c)
0291 {
0292     early_init_hygon(c);
0293 
0294     /*
0295      * Bit 31 in normal CPUID used for nonstandard 3DNow ID;
0296      * 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway
0297      */
0298     clear_cpu_cap(c, 0*32+31);
0299 
0300     set_cpu_cap(c, X86_FEATURE_REP_GOOD);
0301 
0302     /* get apicid instead of initial apic id from cpuid */
0303     c->apicid = hard_smp_processor_id();
0304 
0305     /*
0306      * XXX someone from Hygon needs to confirm this DTRT
0307      *
0308     init_spectral_chicken(c);
0309      */
0310 
0311     set_cpu_cap(c, X86_FEATURE_ZEN);
0312     set_cpu_cap(c, X86_FEATURE_CPB);
0313 
0314     cpu_detect_cache_sizes(c);
0315 
0316     hygon_detect_cmp(c);
0317     hygon_get_topology(c);
0318     srat_detect_node(c);
0319 
0320     init_hygon_cacheinfo(c);
0321 
0322     if (cpu_has(c, X86_FEATURE_XMM2)) {
0323         /*
0324          * Use LFENCE for execution serialization.  On families which
0325          * don't have that MSR, LFENCE is already serializing.
0326          * msr_set_bit() uses the safe accessors, too, even if the MSR
0327          * is not present.
0328          */
0329         msr_set_bit(MSR_F10H_DECFG,
0330                 MSR_F10H_DECFG_LFENCE_SERIALIZE_BIT);
0331 
0332         /* A serializing LFENCE stops RDTSC speculation */
0333         set_cpu_cap(c, X86_FEATURE_LFENCE_RDTSC);
0334     }
0335 
0336     /*
0337      * Hygon processors have APIC timer running in deep C states.
0338      */
0339     set_cpu_cap(c, X86_FEATURE_ARAT);
0340 
0341     /* Hygon CPUs don't reset SS attributes on SYSRET, Xen does. */
0342     if (!cpu_has(c, X86_FEATURE_XENPV))
0343         set_cpu_bug(c, X86_BUG_SYSRET_SS_ATTRS);
0344 
0345     check_null_seg_clears_base(c);
0346 }
0347 
0348 static void cpu_detect_tlb_hygon(struct cpuinfo_x86 *c)
0349 {
0350     u32 ebx, eax, ecx, edx;
0351     u16 mask = 0xfff;
0352 
0353     if (c->extended_cpuid_level < 0x80000006)
0354         return;
0355 
0356     cpuid(0x80000006, &eax, &ebx, &ecx, &edx);
0357 
0358     tlb_lld_4k[ENTRIES] = (ebx >> 16) & mask;
0359     tlb_lli_4k[ENTRIES] = ebx & mask;
0360 
0361     /* Handle DTLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
0362     if (!((eax >> 16) & mask))
0363         tlb_lld_2m[ENTRIES] = (cpuid_eax(0x80000005) >> 16) & 0xff;
0364     else
0365         tlb_lld_2m[ENTRIES] = (eax >> 16) & mask;
0366 
0367     /* a 4M entry uses two 2M entries */
0368     tlb_lld_4m[ENTRIES] = tlb_lld_2m[ENTRIES] >> 1;
0369 
0370     /* Handle ITLB 2M and 4M sizes, fall back to L1 if L2 is disabled */
0371     if (!(eax & mask)) {
0372         cpuid(0x80000005, &eax, &ebx, &ecx, &edx);
0373         tlb_lli_2m[ENTRIES] = eax & 0xff;
0374     } else
0375         tlb_lli_2m[ENTRIES] = eax & mask;
0376 
0377     tlb_lli_4m[ENTRIES] = tlb_lli_2m[ENTRIES] >> 1;
0378 }
0379 
0380 static const struct cpu_dev hygon_cpu_dev = {
0381     .c_vendor   = "Hygon",
0382     .c_ident    = { "HygonGenuine" },
0383     .c_early_init   = early_init_hygon,
0384     .c_detect_tlb   = cpu_detect_tlb_hygon,
0385     .c_bsp_init = bsp_init_hygon,
0386     .c_init     = init_hygon,
0387     .c_x86_vendor   = X86_VENDOR_HYGON,
0388 };
0389 
0390 cpu_dev_register(hygon_cpu_dev);