1 // SPDX-License-Identifier: GPL-2.0 2 #include <linux/cpu.h> 3 4 #include <xen/xen.h> 5 6 #include <asm/intel-family.h> 7 #include <asm/apic.h> 8 #include <asm/processor.h> 9 #include <asm/cpuid/api.h> 10 #include <asm/smp.h> 11 12 #include "cpu.h" 13 14 struct x86_topology_system x86_topo_system __ro_after_init; 15 EXPORT_SYMBOL_GPL(x86_topo_system); 16 17 unsigned int __amd_nodes_per_pkg __ro_after_init; 18 EXPORT_SYMBOL_GPL(__amd_nodes_per_pkg); 19 20 /* CPUs which are the primary SMT threads */ 21 struct cpumask __cpu_primary_thread_mask __read_mostly; 22 23 void topology_set_dom(struct topo_scan *tscan, enum x86_topology_domains dom, 24 unsigned int shift, unsigned int ncpus) 25 { 26 topology_update_dom(tscan, dom, shift, ncpus); 27 28 /* Propagate to the upper levels */ 29 for (dom++; dom < TOPO_MAX_DOMAIN; dom++) { 30 tscan->dom_shifts[dom] = tscan->dom_shifts[dom - 1]; 31 tscan->dom_ncpus[dom] = tscan->dom_ncpus[dom - 1]; 32 } 33 } 34 35 enum x86_topology_cpu_type get_topology_cpu_type(struct cpuinfo_x86 *c) 36 { 37 if (c->x86_vendor == X86_VENDOR_INTEL) { 38 switch (c->topo.intel_type) { 39 case INTEL_CPU_TYPE_ATOM: return TOPO_CPU_TYPE_EFFICIENCY; 40 case INTEL_CPU_TYPE_CORE: return TOPO_CPU_TYPE_PERFORMANCE; 41 } 42 } 43 if (c->x86_vendor == X86_VENDOR_AMD) { 44 switch (c->topo.amd_type) { 45 case AMD_CPU_TYPE_PERFORMANCE: return TOPO_CPU_TYPE_PERFORMANCE; 46 case AMD_CPU_TYPE_EFFICIENCY: return TOPO_CPU_TYPE_EFFICIENCY; 47 case AMD_CPU_TYPE_LOW_POWER: return TOPO_CPU_TYPE_LOW_POWER; 48 } 49 } 50 51 return TOPO_CPU_TYPE_UNKNOWN; 52 } 53 54 const char *get_topology_cpu_type_name(struct cpuinfo_x86 *c) 55 { 56 switch (get_topology_cpu_type(c)) { 57 case TOPO_CPU_TYPE_PERFORMANCE: 58 return "performance"; 59 case TOPO_CPU_TYPE_EFFICIENCY: 60 return "efficiency"; 61 case TOPO_CPU_TYPE_LOW_POWER: 62 return "low_power"; 63 default: 64 return "unknown"; 65 } 66 } 67 68 static unsigned int parse_num_cores_legacy(struct cpuinfo_x86 *c) 69 { 70 struct { 71 u32 cache_type : 5, 72 unused : 21, 73 ncores : 6; 74 } eax; 75 76 if (c->cpuid_level < 4) 77 return 1; 78 79 cpuid_subleaf_reg(4, 0, CPUID_EAX, &eax); 80 if (!eax.cache_type) 81 return 1; 82 83 return eax.ncores + 1; 84 } 85 86 static void parse_legacy(struct topo_scan *tscan) 87 { 88 unsigned int cores, core_shift, smt_shift = 0; 89 struct cpuinfo_x86 *c = tscan->c; 90 91 cores = parse_num_cores_legacy(c); 92 core_shift = get_count_order(cores); 93 94 if (cpu_has(c, X86_FEATURE_HT)) { 95 if (!WARN_ON_ONCE(tscan->ebx1_nproc_shift < core_shift)) 96 smt_shift = tscan->ebx1_nproc_shift - core_shift; 97 /* 98 * The parser expects leaf 0xb/0x1f format, which means 99 * the number of logical processors at core level is 100 * counting threads. 101 */ 102 core_shift += smt_shift; 103 cores <<= smt_shift; 104 } 105 106 topology_set_dom(tscan, TOPO_SMT_DOMAIN, smt_shift, 1U << smt_shift); 107 topology_set_dom(tscan, TOPO_CORE_DOMAIN, core_shift, cores); 108 } 109 110 static bool fake_topology(struct topo_scan *tscan) 111 { 112 /* 113 * Preset the CORE level shift for CPUID less systems and XEN_PV, 114 * which has useless CPUID information. 115 */ 116 topology_set_dom(tscan, TOPO_SMT_DOMAIN, 0, 1); 117 topology_set_dom(tscan, TOPO_CORE_DOMAIN, 0, 1); 118 119 return tscan->c->cpuid_level < 1; 120 } 121 122 static void parse_topology(struct topo_scan *tscan, bool early) 123 { 124 const struct cpuinfo_topology topo_defaults = { 125 .cu_id = 0xff, 126 .llc_id = BAD_APICID, 127 .l2c_id = BAD_APICID, 128 .cpu_type = TOPO_CPU_TYPE_UNKNOWN, 129 }; 130 struct cpuinfo_x86 *c = tscan->c; 131 struct { 132 u32 unused0 : 16, 133 nproc : 8, 134 apicid : 8; 135 } ebx; 136 137 c->topo = topo_defaults; 138 139 if (fake_topology(tscan)) 140 return; 141 142 /* Preset Initial APIC ID from CPUID leaf 1 */ 143 cpuid_leaf_reg(1, CPUID_EBX, &ebx); 144 c->topo.initial_apicid = ebx.apicid; 145 146 /* 147 * The initial invocation from early_identify_cpu() happens before 148 * the APIC is mapped or X2APIC enabled. For establishing the 149 * topology, that's not required. Use the initial APIC ID. 150 */ 151 if (early) 152 c->topo.apicid = c->topo.initial_apicid; 153 else 154 c->topo.apicid = read_apic_id(); 155 156 /* The above is sufficient for UP */ 157 if (!IS_ENABLED(CONFIG_SMP)) 158 return; 159 160 tscan->ebx1_nproc_shift = get_count_order(ebx.nproc); 161 162 switch (c->x86_vendor) { 163 case X86_VENDOR_AMD: 164 case X86_VENDOR_HYGON: 165 cpu_parse_topology_amd(tscan); 166 break; 167 case X86_VENDOR_CENTAUR: 168 case X86_VENDOR_ZHAOXIN: 169 parse_legacy(tscan); 170 break; 171 case X86_VENDOR_INTEL: 172 if (!IS_ENABLED(CONFIG_CPU_SUP_INTEL) || !cpu_parse_topology_ext(tscan)) 173 parse_legacy(tscan); 174 175 if (c->cpuid_level >= 0x1a) { 176 c->topo.hw_cpu_type = cpuid_eax(0x1a); 177 c->topo.cpu_type = get_topology_cpu_type(c); 178 } 179 180 break; 181 } 182 } 183 184 static void topo_set_ids(struct topo_scan *tscan, bool early) 185 { 186 struct cpuinfo_x86 *c = tscan->c; 187 u32 apicid = c->topo.apicid; 188 189 c->topo.pkg_id = topo_shift_apicid(apicid, TOPO_PKG_DOMAIN); 190 c->topo.die_id = topo_shift_apicid(apicid, TOPO_DIE_DOMAIN); 191 192 if (!early) { 193 c->topo.logical_pkg_id = topology_get_logical_id(apicid, TOPO_PKG_DOMAIN); 194 c->topo.logical_die_id = topology_get_logical_id(apicid, TOPO_DIE_DOMAIN); 195 c->topo.logical_core_id = topology_get_logical_id(apicid, TOPO_CORE_DOMAIN); 196 } 197 198 /* Package relative core ID */ 199 c->topo.core_id = (apicid & topo_domain_mask(TOPO_PKG_DOMAIN)) >> 200 x86_topo_system.dom_shifts[TOPO_SMT_DOMAIN]; 201 202 c->topo.amd_node_id = tscan->amd_node_id; 203 204 if (c->x86_vendor == X86_VENDOR_AMD) 205 cpu_topology_fixup_amd(tscan); 206 } 207 208 void cpu_parse_topology(struct cpuinfo_x86 *c) 209 { 210 unsigned int dom, cpu = smp_processor_id(); 211 struct topo_scan tscan = { .c = c, }; 212 213 parse_topology(&tscan, false); 214 215 if (IS_ENABLED(CONFIG_X86_LOCAL_APIC)) { 216 if (c->topo.initial_apicid != c->topo.apicid) { 217 pr_err(FW_BUG "CPU%4u: APIC ID mismatch. CPUID: 0x%04x APIC: 0x%04x\n", 218 cpu, c->topo.initial_apicid, c->topo.apicid); 219 } 220 221 if (c->topo.apicid != cpuid_to_apicid[cpu]) { 222 pr_err(FW_BUG "CPU%4u: APIC ID mismatch. Firmware: 0x%04x APIC: 0x%04x\n", 223 cpu, cpuid_to_apicid[cpu], c->topo.apicid); 224 } 225 } 226 227 for (dom = TOPO_SMT_DOMAIN; dom < TOPO_MAX_DOMAIN; dom++) { 228 if (tscan.dom_shifts[dom] == x86_topo_system.dom_shifts[dom]) 229 continue; 230 pr_err(FW_BUG "CPU%d: Topology domain %u shift %u != %u\n", cpu, dom, 231 tscan.dom_shifts[dom], x86_topo_system.dom_shifts[dom]); 232 } 233 234 topo_set_ids(&tscan, false); 235 } 236 237 void __init cpu_init_topology(struct cpuinfo_x86 *c) 238 { 239 struct topo_scan tscan = { .c = c, }; 240 unsigned int dom, sft; 241 242 parse_topology(&tscan, true); 243 244 /* Copy the shift values and calculate the unit sizes. */ 245 memcpy(x86_topo_system.dom_shifts, tscan.dom_shifts, sizeof(x86_topo_system.dom_shifts)); 246 247 dom = TOPO_SMT_DOMAIN; 248 x86_topo_system.dom_size[dom] = 1U << x86_topo_system.dom_shifts[dom]; 249 250 for (dom++; dom < TOPO_MAX_DOMAIN; dom++) { 251 sft = x86_topo_system.dom_shifts[dom] - x86_topo_system.dom_shifts[dom - 1]; 252 x86_topo_system.dom_size[dom] = 1U << sft; 253 } 254 255 topo_set_ids(&tscan, true); 256 257 /* 258 * AMD systems have Nodes per package which cannot be mapped to 259 * APIC ID. 260 */ 261 __amd_nodes_per_pkg = tscan.amd_nodes_per_pkg; 262 } 263