1 /*- 2 * SPDX-License-Identifier: BSD-2-Clause 3 * 4 * Copyright (c) 2008 Joseph Koshy 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 1. Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * 2. Redistributions in binary form must reproduce the above copyright 13 * notice, this list of conditions and the following disclaimer in the 14 * documentation and/or other materials provided with the distribution. 15 * 16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 17 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 18 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 19 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 20 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 21 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 22 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 24 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 25 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 26 * SUCH DAMAGE. 27 */ 28 29 /* 30 * Common code for handling Intel CPUs. 31 */ 32 33 #include <sys/param.h> 34 #include <sys/pmc.h> 35 #include <sys/pmckern.h> 36 #include <sys/systm.h> 37 38 #include <machine/cpu.h> 39 #include <machine/cputypes.h> 40 #include <machine/md_var.h> 41 #include <machine/specialreg.h> 42 43 static int 44 intel_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) 45 { 46 (void) pc; 47 48 PMCDBG3(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp, 49 pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS); 50 51 /* allow the RDPMC instruction if needed */ 52 if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) 53 load_cr4(rcr4() | CR4_PCE); 54 55 PMCDBG1(MDP,SWI,1, "cr4=0x%jx", (uintmax_t) rcr4()); 56 57 return 0; 58 } 59 60 static int 61 intel_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) 62 { 63 (void) pc; 64 (void) pp; /* can be NULL */ 65 66 PMCDBG3(MDP,SWO,1, "pc=%p pp=%p cr4=0x%jx", pc, pp, 67 (uintmax_t) rcr4()); 68 69 /* always turn off the RDPMC instruction */ 70 load_cr4(rcr4() & ~CR4_PCE); 71 72 return 0; 73 } 74 75 struct pmc_mdep * 76 pmc_intel_initialize(void) 77 { 78 struct pmc_mdep *pmc_mdep; 79 enum pmc_cputype cputype; 80 int error, family, model, nclasses, ncpus, stepping, verov; 81 82 KASSERT(cpu_vendor_id == CPU_VENDOR_INTEL, 83 ("[intel,%d] Initializing non-intel processor", __LINE__)); 84 85 PMCDBG1(MDP,INI,0, "intel-initialize cpuid=0x%x", cpu_id); 86 87 cputype = -1; 88 nclasses = 2; 89 error = 0; 90 verov = 0; 91 family = CPUID_TO_FAMILY(cpu_id); 92 model = CPUID_TO_MODEL(cpu_id); 93 stepping = CPUID_TO_STEPPING(cpu_id); 94 95 snprintf(pmc_cpuid, sizeof(pmc_cpuid), "GenuineIntel-%d-%02X-%X", 96 family, model, stepping); 97 98 switch (cpu_id & 0xF00) { 99 case 0x600: 100 switch (model) { 101 case 0xE: 102 cputype = PMC_CPU_INTEL_CORE; 103 break; 104 case 0xF: 105 /* Per Intel document 315338-020. */ 106 if (stepping == 0x7) { 107 cputype = PMC_CPU_INTEL_CORE; 108 verov = 1; 109 } else { 110 cputype = PMC_CPU_INTEL_CORE2; 111 nclasses = 3; 112 } 113 break; 114 case 0x17: 115 cputype = PMC_CPU_INTEL_CORE2EXTREME; 116 nclasses = 3; 117 break; 118 case 0x1A: 119 case 0x1E: /* 120 * Per Intel document 253669-032 9/2009, 121 * pages A-2 and A-57 122 */ 123 case 0x1F: /* 124 * Per Intel document 253669-032 9/2009, 125 * pages A-2 and A-57 126 */ 127 cputype = PMC_CPU_INTEL_COREI7; 128 nclasses = 5; 129 break; 130 case 0x2E: 131 cputype = PMC_CPU_INTEL_NEHALEM_EX; 132 nclasses = 3; 133 break; 134 case 0x25: /* Per Intel document 253669-033US 12/2009. */ 135 case 0x2C: /* Per Intel document 253669-033US 12/2009. */ 136 cputype = PMC_CPU_INTEL_WESTMERE; 137 nclasses = 5; 138 break; 139 case 0x2F: /* Westmere-EX, seen in wild */ 140 cputype = PMC_CPU_INTEL_WESTMERE_EX; 141 nclasses = 3; 142 break; 143 case 0x2A: /* Per Intel document 253669-039US 05/2011. */ 144 cputype = PMC_CPU_INTEL_SANDYBRIDGE; 145 nclasses = 3; 146 break; 147 case 0x2D: /* Per Intel document 253669-044US 08/2012. */ 148 cputype = PMC_CPU_INTEL_SANDYBRIDGE_XEON; 149 nclasses = 3; 150 break; 151 case 0x3A: /* Per Intel document 253669-043US 05/2012. */ 152 cputype = PMC_CPU_INTEL_IVYBRIDGE; 153 nclasses = 3; 154 break; 155 case 0x3E: /* Per Intel document 325462-045US 01/2013. */ 156 cputype = PMC_CPU_INTEL_IVYBRIDGE_XEON; 157 nclasses = 3; 158 break; 159 case 0x3D: 160 case 0x47: 161 cputype = PMC_CPU_INTEL_BROADWELL; 162 nclasses = 3; 163 break; 164 case 0x4f: 165 case 0x56: 166 cputype = PMC_CPU_INTEL_BROADWELL_XEON; 167 nclasses = 3; 168 break; 169 case 0x3C: /* Per Intel document 325462-045US 01/2013. */ 170 case 0x45: /* Per Intel document 325462-045US 09/2014. */ 171 cputype = PMC_CPU_INTEL_HASWELL; 172 nclasses = 3; 173 break; 174 case 0x3F: /* Per Intel document 325462-045US 09/2014. */ 175 case 0x46: /* Per Intel document 325462-045US 09/2014. */ 176 /* Should 46 be XEON. probably its own? */ 177 cputype = PMC_CPU_INTEL_HASWELL_XEON; 178 nclasses = 3; 179 break; 180 /* Skylake */ 181 case 0x4e: 182 case 0x5e: 183 /* Kabylake */ 184 case 0x8E: /* Per Intel document 325462-063US July 2017. */ 185 case 0x9E: /* Per Intel document 325462-063US July 2017. */ 186 /* Cometlake */ 187 case 0xA5: 188 case 0xA6: 189 cputype = PMC_CPU_INTEL_SKYLAKE; 190 nclasses = 3; 191 break; 192 case 0x55: /* SDM rev 63 */ 193 cputype = PMC_CPU_INTEL_SKYLAKE_XEON; 194 nclasses = 3; 195 break; 196 /* Icelake */ 197 case 0x7D: 198 case 0x7E: 199 /* Tigerlake */ 200 case 0x8C: 201 case 0x8D: 202 /* Rocketlake */ 203 case 0xA7: 204 cputype = PMC_CPU_INTEL_ICELAKE; 205 nclasses = 3; 206 break; 207 case 0x6A: 208 case 0x6C: 209 cputype = PMC_CPU_INTEL_ICELAKE_XEON; 210 nclasses = 3; 211 break; 212 case 0x97: 213 case 0x9A: 214 case 0xB7: 215 case 0xBA: 216 case 0xBF: 217 cputype = PMC_CPU_INTEL_ALDERLAKE; 218 nclasses = 3; 219 break; 220 case 0x1C: /* Per Intel document 320047-002. */ 221 case 0x26: 222 case 0x27: 223 case 0x35: 224 case 0x36: 225 cputype = PMC_CPU_INTEL_ATOM; 226 nclasses = 3; 227 break; 228 case 0x37: 229 case 0x4A: 230 case 0x4D: /* Per Intel document 330061-001 01/2014. */ 231 case 0x5A: 232 case 0x5D: 233 cputype = PMC_CPU_INTEL_ATOM_SILVERMONT; 234 nclasses = 3; 235 break; 236 case 0x5C: /* Per Intel document 325462-071US 10/2019. */ 237 case 0x5F: 238 cputype = PMC_CPU_INTEL_ATOM_GOLDMONT; 239 nclasses = 3; 240 break; 241 case 0x7A: 242 cputype = PMC_CPU_INTEL_ATOM_GOLDMONT_P; 243 nclasses = 3; 244 break; 245 case 0x86: 246 case 0x96: 247 cputype = PMC_CPU_INTEL_ATOM_TREMONT; 248 nclasses = 3; 249 break; 250 case 0xAA: 251 case 0xAC: 252 case 0xB5: 253 cputype = PMC_CPU_INTEL_METEOR_LAKE; 254 nclasses = 3; 255 break; 256 case 0xAD: 257 case 0xAE: 258 cputype = PMC_CPU_INTEL_GRANITE_RAPIDS; 259 nclasses = 3; 260 break; 261 case 0xBE: 262 cputype = PMC_CPU_INTEL_ALDERLAKEN; 263 nclasses = 3; 264 break; 265 case 0xCF: 266 cputype = PMC_CPU_INTEL_EMERALD_RAPIDS; 267 nclasses = 3; 268 break; 269 case 0x8F: 270 cputype = PMC_CPU_INTEL_SAPPHIRE_RAPIDS; 271 nclasses = 3; 272 break; 273 } 274 break; 275 } 276 277 278 if ((int) cputype == -1) { 279 printf("pmc: Unknown Intel CPU.\n"); 280 return (NULL); 281 } 282 283 /* 284 * Detect support for MPERF and APERF MSRs. tsc_perf_stat is set by the 285 * kernel's generic TSC initialization (start_TSC(), called at boot via 286 * cpu_startup() -> startrtclock()), not by hwpmc's TSC PMC class. It is 287 * set only after confirming both MSRs actually increment (some emulators 288 * expose the CPUID bit without real MSR support). 289 */ 290 if ((cpu_power_ecx & CPUID_PERF_STAT) && (tsc_perf_stat == 1)) { 291 nclasses++; 292 } 293 294 /* Reserve one extra class slot for the optional RAPL counters. */ 295 nclasses++; 296 297 /* Allocate base class and initialize machine dependent struct */ 298 pmc_mdep = pmc_mdep_alloc(nclasses); 299 300 pmc_mdep->pmd_cputype = cputype; 301 pmc_mdep->pmd_switch_in = intel_switch_in; 302 pmc_mdep->pmd_switch_out = intel_switch_out; 303 304 ncpus = pmc_cpu_max(); 305 error = pmc_tsc_initialize(pmc_mdep, ncpus); 306 if (error) 307 goto error; 308 309 MPASS(nclasses >= PMC_MDEP_CLASS_INDEX_IAF); 310 error = pmc_core_initialize(pmc_mdep, ncpus, verov); 311 if (error) { 312 pmc_tsc_finalize(pmc_mdep); 313 goto error; 314 } 315 316 /* 317 * Init the uncore class. 318 */ 319 switch (cputype) { 320 /* 321 * Intel Corei7 and Westmere processors. 322 */ 323 case PMC_CPU_INTEL_COREI7: 324 case PMC_CPU_INTEL_WESTMERE: 325 #ifdef notyet 326 /* 327 * TODO: re-enable uncore class on these processors. 328 * 329 * The uncore unit was reworked beginning with Sandy Bridge, including 330 * the MSRs required to program it. In particular, we need to: 331 * - Parse the MSR_UNC_CBO_CONFIG MSR for number of C-box units in the 332 * system 333 * - Support reading and writing to ARB and C-box units, depending on 334 * the requested event 335 * - Create some kind of mapping between C-box <--> CPU 336 * 337 * Also TODO: support other later changes to these interfaces, to 338 * enable the uncore class on generations newer than Broadwell. 339 * Skylake+ appears to use newer addresses for the uncore MSRs. 340 */ 341 case PMC_CPU_INTEL_HASWELL: 342 case PMC_CPU_INTEL_BROADWELL: 343 case PMC_CPU_INTEL_SANDYBRIDGE: 344 #endif 345 MPASS(nclasses >= PMC_MDEP_CLASS_INDEX_UCF); 346 error = pmc_uncore_initialize(pmc_mdep, ncpus); 347 break; 348 default: 349 break; 350 } 351 352 if (error == 0) { 353 /* Initialize PERF class. */ 354 pmc_perf_initialize(pmc_mdep, ncpus, nclasses - 1); 355 } 356 357 if (error == 0 && 358 pmc_rapl_initialize(pmc_mdep, ncpus, pmc_mdep->pmd_nclass - 1) != 0) 359 pmc_mdep->pmd_nclass--; 360 error: 361 if (error) { 362 pmc_mdep_free(pmc_mdep); 363 pmc_mdep = NULL; 364 } 365 366 return (pmc_mdep); 367 } 368 369 void 370 pmc_intel_finalize(struct pmc_mdep *md) 371 { 372 pmc_rapl_finalize(md); 373 374 pmc_tsc_finalize(md); 375 376 pmc_core_finalize(md); 377 378 pmc_perf_finalize(md); 379 380 /* 381 * Uncore. 382 */ 383 switch (md->pmd_cputype) { 384 case PMC_CPU_INTEL_COREI7: 385 case PMC_CPU_INTEL_WESTMERE: 386 #ifdef notyet 387 case PMC_CPU_INTEL_HASWELL: 388 case PMC_CPU_INTEL_BROADWELL: 389 case PMC_CPU_INTEL_SANDYBRIDGE: 390 #endif 391 pmc_uncore_finalize(md); 392 break; 393 default: 394 break; 395 } 396 } 397