1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/cpu.h> 3 4 #include <asm/apic.h> 5 #include <asm/cpuid/api.h> 6 #include <asm/memtype.h> 7 #include <asm/msr.h> 8 #include <asm/processor.h> 9 10 #include "cpu.h" 11 12 static bool parse_8000_0008(struct topo_scan *tscan) 13 { 14 struct { 15 // ecx 16 u32 cpu_nthreads : 8, // Number of physical threads - 1 17 : 4, // Reserved 18 apicid_coreid_len : 4, // Number of thread core ID bits (shift) in APIC ID 19 perf_tsc_len : 2, // Performance time-stamp counter size 20 : 14; // Reserved 21 } ecx; 22 unsigned int sft; 23 24 if (tscan->c->extended_cpuid_level < 0x80000008) 25 return false; 26 27 cpuid_leaf_reg(0x80000008, CPUID_ECX, &ecx); 28 29 /* If the thread bits are 0, then get the shift value from ecx.cpu_nthreads */ 30 sft = ecx.apicid_coreid_len; 31 if (!sft) 32 sft = get_count_order(ecx.cpu_nthreads + 1); 33 34 /* 35 * cpu_nthreads describes the number of threads in the package 36 * sft is the number of APIC ID bits per package 37 * 38 * As the number of actual threads per core is not described in 39 * this leaf, just set the CORE domain shift and let the later 40 * parsers set SMT shift. Assume one thread per core by default 41 * which is correct if there are no other CPUID leafs to parse. 42 */ 43 topology_update_dom(tscan, TOPO_SMT_DOMAIN, 0, 1); 44 topology_set_dom(tscan, TOPO_CORE_DOMAIN, sft, ecx.cpu_nthreads + 1); 45 return true; 46 } 47 48 static void store_node(struct topo_scan *tscan, u16 nr_nodes, u16 node_id) 49 { 50 /* 51 * Starting with Fam 17h the DIE domain could probably be used to 52 * retrieve the node info on AMD/HYGON. Analysis of CPUID dumps 53 * suggests it's the topmost bit(s) of the CPU cores area, but 54 * that's guess work and neither enumerated nor documented. 55 * 56 * Up to Fam 16h this does not work at all and the legacy node ID 57 * has to be used. 58 */ 59 tscan->amd_nodes_per_pkg = nr_nodes; 60 tscan->amd_node_id = node_id; 61 } 62 63 static bool parse_8000_001e(struct topo_scan *tscan) 64 { 65 struct { 66 // eax 67 u32 ext_apic_id : 32; // Extended APIC ID 68 // ebx 69 u32 core_id : 8, // Unique per-socket logical core unit ID 70 core_nthreads : 8, // #Threads per core (zero-based) 71 : 16; // Reserved 72 // ecx 73 u32 node_id : 8, // Node (die) ID of invoking logical CPU 74 nnodes_per_socket : 3, // #nodes in invoking logical CPU's package/socket 75 : 21; // Reserved 76 // edx 77 u32 : 32; // Reserved 78 } leaf; 79 80 if (!boot_cpu_has(X86_FEATURE_TOPOEXT)) 81 return false; 82 83 cpuid_read(0x8000001e, &leaf); 84 85 /* 86 * If leaf 0xb/0x26 is available, then the APIC ID and the domain 87 * shifts are set already. 88 */ 89 if (!cpu_feature_enabled(X86_FEATURE_XTOPOLOGY)) { 90 tscan->c->topo.initial_apicid = leaf.ext_apic_id; 91 92 /* 93 * Leaf 0x8000008 sets the CORE domain shift but not the 94 * SMT domain shift. On CPUs with family >= 0x17, there 95 * might be hyperthreads. 96 */ 97 if (tscan->c->x86 >= 0x17) { 98 /* Update the SMT domain, but do not propagate it. */ 99 unsigned int nthreads = leaf.core_nthreads + 1; 100 101 topology_update_dom(tscan, TOPO_SMT_DOMAIN, 102 get_count_order(nthreads), nthreads); 103 } 104 } 105 106 store_node(tscan, leaf.nnodes_per_socket + 1, leaf.node_id); 107 108 if (tscan->c->x86_vendor == X86_VENDOR_AMD) { 109 if (tscan->c->x86 == 0x15) 110 tscan->c->topo.cu_id = leaf.core_id; 111 112 cacheinfo_amd_init_llc_id(tscan->c, leaf.node_id); 113 } else { 114 /* 115 * Package ID is ApicId[6..] on certain Hygon CPUs. See 116 * commit e0ceeae708ce for explanation. The topology info 117 * is screwed up: The package shift is always 6 and the 118 * node ID is bit [4:5]. 119 */ 120 if (!boot_cpu_has(X86_FEATURE_HYPERVISOR) && tscan->c->x86_model <= 0x3) { 121 topology_set_dom(tscan, TOPO_CORE_DOMAIN, 6, 122 tscan->dom_ncpus[TOPO_CORE_DOMAIN]); 123 } 124 cacheinfo_hygon_init_llc_id(tscan->c); 125 } 126 return true; 127 } 128 129 static void parse_fam10h_node_id(struct topo_scan *tscan) 130 { 131 union { 132 struct { 133 u64 node_id : 3, 134 nodes_per_pkg : 3, 135 unused : 58; 136 }; 137 u64 msr; 138 } nid; 139 140 if (!boot_cpu_has(X86_FEATURE_NODEID_MSR)) 141 return; 142 143 rdmsrq(MSR_FAM10H_NODE_ID, nid.msr); 144 store_node(tscan, nid.nodes_per_pkg + 1, nid.node_id); 145 tscan->c->topo.llc_id = nid.node_id; 146 } 147 148 static void legacy_set_llc(struct topo_scan *tscan) 149 { 150 unsigned int apicid = tscan->c->topo.initial_apicid; 151 152 /* If none of the parsers set LLC ID then use the die ID for it. */ 153 if (tscan->c->topo.llc_id == BAD_APICID) 154 tscan->c->topo.llc_id = apicid >> tscan->dom_shifts[TOPO_CORE_DOMAIN]; 155 } 156 157 static void topoext_fixup(struct topo_scan *tscan) 158 { 159 struct cpuinfo_x86 *c = tscan->c; 160 u64 msrval; 161 162 /* Try to re-enable TopologyExtensions if switched off by BIOS */ 163 if (cpu_has(c, X86_FEATURE_TOPOEXT) || c->x86_vendor != X86_VENDOR_AMD || 164 c->x86 != 0x15 || c->x86_model < 0x10 || c->x86_model > 0x6f) 165 return; 166 167 if (msr_set_bit(MSR_AMD64_CPUID_EXT_FEAT, 168 MSR_AMD64_CPUID_EXT_FEAT_TOPOEXT_BIT) <= 0) 169 return; 170 171 rdmsrq(MSR_AMD64_CPUID_EXT_FEAT, msrval); 172 if (msrval & MSR_AMD64_CPUID_EXT_FEAT_TOPOEXT) { 173 set_cpu_cap(c, X86_FEATURE_TOPOEXT); 174 pr_info_once(FW_INFO "CPU: Re-enabling disabled Topology Extensions Support.\n"); 175 } 176 } 177 178 static void parse_topology_amd(struct topo_scan *tscan) 179 { 180 if (cpu_feature_enabled(X86_FEATURE_AMD_HTR_CORES)) 181 tscan->c->topo.cpu_type = cpuid_ebx(0x80000026); 182 183 /* 184 * Try to get SMT, CORE, TILE, and DIE shifts from extended 185 * CPUID leaf 0x8000_0026 on supported processors first. If 186 * extended CPUID leaf 0x8000_0026 is not supported, try to 187 * get SMT and CORE shift from leaf 0xb. If either leaf is 188 * available, cpu_parse_topology_ext() will return true. 189 * 190 * If XTOPOLOGY leaves (0x26/0xb) are not available, try to 191 * get the CORE shift from leaf 0x8000_0008 first. 192 */ 193 if (!cpu_parse_topology_ext(tscan) && !parse_8000_0008(tscan)) 194 return; 195 196 /* 197 * Prefer leaf 0x8000001e if available to get the SMT shift and 198 * the initial APIC ID if XTOPOLOGY leaves are not available. 199 */ 200 if (parse_8000_001e(tscan)) 201 return; 202 203 /* Try the NODEID MSR */ 204 parse_fam10h_node_id(tscan); 205 } 206 207 void cpu_parse_topology_amd(struct topo_scan *tscan) 208 { 209 tscan->amd_nodes_per_pkg = 1; 210 topoext_fixup(tscan); 211 parse_topology_amd(tscan); 212 legacy_set_llc(tscan); 213 214 if (tscan->amd_nodes_per_pkg > 1) 215 set_cpu_cap(tscan->c, X86_FEATURE_AMD_DCM); 216 } 217 218 void cpu_topology_fixup_amd(struct topo_scan *tscan) 219 { 220 struct cpuinfo_x86 *c = tscan->c; 221 222 /* 223 * Adjust the core_id relative to the node when there is more than 224 * one node. 225 */ 226 if (tscan->c->x86 < 0x17 && tscan->amd_nodes_per_pkg > 1) 227 c->topo.core_id %= tscan->dom_ncpus[TOPO_CORE_DOMAIN] / tscan->amd_nodes_per_pkg; 228 } 229