1184802Sjkoshy/*- 2184802Sjkoshy * Copyright (c) 2008 Joseph Koshy 3184802Sjkoshy * All rights reserved. 4184802Sjkoshy * 5184802Sjkoshy * Redistribution and use in source and binary forms, with or without 6184802Sjkoshy * modification, are permitted provided that the following conditions 7184802Sjkoshy * are met: 8184802Sjkoshy * 1. Redistributions of source code must retain the above copyright 9184802Sjkoshy * notice, this list of conditions and the following disclaimer. 10184802Sjkoshy * 2. Redistributions in binary form must reproduce the above copyright 11184802Sjkoshy * notice, this list of conditions and the following disclaimer in the 12184802Sjkoshy * documentation and/or other materials provided with the distribution. 13184802Sjkoshy * 14184802Sjkoshy * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 15184802Sjkoshy * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 16184802Sjkoshy * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 17184802Sjkoshy * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 18184802Sjkoshy * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 19184802Sjkoshy * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 20184802Sjkoshy * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 21184802Sjkoshy * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 22184802Sjkoshy * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 23184802Sjkoshy * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 24184802Sjkoshy * SUCH DAMAGE. 25184802Sjkoshy */ 26184802Sjkoshy 27184802Sjkoshy/* 28184802Sjkoshy * Common code for handling Intel CPUs. 29184802Sjkoshy */ 30184802Sjkoshy 31184802Sjkoshy#include <sys/cdefs.h> 32184802Sjkoshy__FBSDID("$FreeBSD$"); 33184802Sjkoshy 34184802Sjkoshy#include <sys/param.h> 35184802Sjkoshy#include <sys/pmc.h> 36184802Sjkoshy#include <sys/pmckern.h> 37184802Sjkoshy#include <sys/systm.h> 38184802Sjkoshy 39184802Sjkoshy#include <machine/cpu.h> 40185341Sjkim#include <machine/cputypes.h> 41184802Sjkoshy#include <machine/md_var.h> 42184802Sjkoshy#include <machine/specialreg.h> 43184802Sjkoshy 44184802Sjkoshystatic int 45184802Sjkoshyintel_switch_in(struct pmc_cpu *pc, struct pmc_process *pp) 46184802Sjkoshy{ 47184802Sjkoshy (void) pc; 48184802Sjkoshy 49184802Sjkoshy PMCDBG(MDP,SWI,1, "pc=%p pp=%p enable-msr=%d", pc, pp, 50184802Sjkoshy pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS); 51184802Sjkoshy 52184802Sjkoshy /* allow the RDPMC instruction if needed */ 53184802Sjkoshy if (pp->pp_flags & PMC_PP_ENABLE_MSR_ACCESS) 54184802Sjkoshy load_cr4(rcr4() | CR4_PCE); 55184802Sjkoshy 56184802Sjkoshy PMCDBG(MDP,SWI,1, "cr4=0x%jx", (uintmax_t) rcr4()); 57184802Sjkoshy 58184802Sjkoshy return 0; 59184802Sjkoshy} 60184802Sjkoshy 61184802Sjkoshystatic int 62184802Sjkoshyintel_switch_out(struct pmc_cpu *pc, struct pmc_process *pp) 63184802Sjkoshy{ 64184802Sjkoshy (void) pc; 65184802Sjkoshy (void) pp; /* can be NULL */ 66184802Sjkoshy 67184802Sjkoshy PMCDBG(MDP,SWO,1, "pc=%p pp=%p cr4=0x%jx", pc, pp, 68184802Sjkoshy (uintmax_t) rcr4()); 69184802Sjkoshy 70184802Sjkoshy /* always turn off the RDPMC instruction */ 71249069Ssbruno load_cr4(rcr4() & ~CR4_PCE); 72184802Sjkoshy 73184802Sjkoshy return 0; 74184802Sjkoshy} 75184802Sjkoshy 76184802Sjkoshystruct pmc_mdep * 77184802Sjkoshypmc_intel_initialize(void) 78184802Sjkoshy{ 79184802Sjkoshy struct pmc_mdep *pmc_mdep; 80184802Sjkoshy enum pmc_cputype cputype; 81184802Sjkoshy int error, model, nclasses, ncpus; 82184802Sjkoshy 83185341Sjkim KASSERT(cpu_vendor_id == CPU_VENDOR_INTEL, 84184802Sjkoshy ("[intel,%d] Initializing non-intel processor", __LINE__)); 85184802Sjkoshy 86184802Sjkoshy PMCDBG(MDP,INI,0, "intel-initialize cpuid=0x%x", cpu_id); 87184802Sjkoshy 88184802Sjkoshy cputype = -1; 89184802Sjkoshy nclasses = 2; 90250097Sdavide error = 0; 91185363Sjkoshy model = ((cpu_id & 0xF0000) >> 12) | ((cpu_id & 0xF0) >> 4); 92185363Sjkoshy 93184802Sjkoshy switch (cpu_id & 0xF00) { 94184802Sjkoshy#if defined(__i386__) 95184802Sjkoshy case 0x500: /* Pentium family processors */ 96184802Sjkoshy cputype = PMC_CPU_INTEL_P5; 97184802Sjkoshy break; 98185363Sjkoshy#endif 99184802Sjkoshy case 0x600: /* Pentium Pro, Celeron, Pentium II & III */ 100185363Sjkoshy switch (model) { 101185363Sjkoshy#if defined(__i386__) 102184802Sjkoshy case 0x1: 103184802Sjkoshy cputype = PMC_CPU_INTEL_P6; 104184802Sjkoshy break; 105184802Sjkoshy case 0x3: case 0x5: 106184802Sjkoshy cputype = PMC_CPU_INTEL_PII; 107184802Sjkoshy break; 108185363Sjkoshy case 0x6: case 0x16: 109184802Sjkoshy cputype = PMC_CPU_INTEL_CL; 110184802Sjkoshy break; 111184802Sjkoshy case 0x7: case 0x8: case 0xA: case 0xB: 112184802Sjkoshy cputype = PMC_CPU_INTEL_PIII; 113184802Sjkoshy break; 114184802Sjkoshy case 0x9: case 0xD: 115184802Sjkoshy cputype = PMC_CPU_INTEL_PM; 116184802Sjkoshy break; 117185363Sjkoshy#endif 118185363Sjkoshy case 0xE: 119185363Sjkoshy cputype = PMC_CPU_INTEL_CORE; 120185363Sjkoshy break; 121185363Sjkoshy case 0xF: 122185363Sjkoshy cputype = PMC_CPU_INTEL_CORE2; 123185363Sjkoshy nclasses = 3; 124185363Sjkoshy break; 125185363Sjkoshy case 0x17: 126185363Sjkoshy cputype = PMC_CPU_INTEL_CORE2EXTREME; 127185363Sjkoshy nclasses = 3; 128185363Sjkoshy break; 129185363Sjkoshy case 0x1C: /* Per Intel document 320047-002. */ 130185363Sjkoshy cputype = PMC_CPU_INTEL_ATOM; 131185363Sjkoshy nclasses = 3; 132185363Sjkoshy break; 133187761Sjeff case 0x1A: 134249069Ssbruno case 0x1E: /* 135249069Ssbruno * Per Intel document 253669-032 9/2009, 136249069Ssbruno * pages A-2 and A-57 137249069Ssbruno */ 138249069Ssbruno case 0x1F: /* 139249069Ssbruno * Per Intel document 253669-032 9/2009, 140249069Ssbruno * pages A-2 and A-57 141249069Ssbruno */ 142187761Sjeff cputype = PMC_CPU_INTEL_COREI7; 143206089Sfabient nclasses = 5; 144187761Sjeff break; 145267602Skib case 0x2E: 146267602Skib cputype = PMC_CPU_INTEL_NEHALEM_EX; 147267602Skib nclasses = 3; 148267602Skib break; 149206089Sfabient case 0x25: /* Per Intel document 253669-033US 12/2009. */ 150206089Sfabient case 0x2C: /* Per Intel document 253669-033US 12/2009. */ 151206089Sfabient cputype = PMC_CPU_INTEL_WESTMERE; 152206089Sfabient nclasses = 5; 153206089Sfabient break; 154267602Skib case 0x2F: /* Westmere-EX, seen in wild */ 155267602Skib cputype = PMC_CPU_INTEL_WESTMERE_EX; 156267602Skib nclasses = 3; 157267602Skib break; 158232366Sdavide case 0x2A: /* Per Intel document 253669-039US 05/2011. */ 159232366Sdavide cputype = PMC_CPU_INTEL_SANDYBRIDGE; 160232366Sdavide nclasses = 5; 161232366Sdavide break; 162241738Ssbruno case 0x2D: /* Per Intel document 253669-044US 08/2012. */ 163241738Ssbruno cputype = PMC_CPU_INTEL_SANDYBRIDGE_XEON; 164241738Ssbruno nclasses = 3; 165241738Ssbruno break; 166240164Sfabient case 0x3A: /* Per Intel document 253669-043US 05/2012. */ 167240164Sfabient cputype = PMC_CPU_INTEL_IVYBRIDGE; 168240164Sfabient nclasses = 3; 169240164Sfabient break; 170246166Ssbruno case 0x3E: /* Per Intel document 325462-045US 01/2013. */ 171246166Ssbruno cputype = PMC_CPU_INTEL_IVYBRIDGE_XEON; 172246166Ssbruno nclasses = 3; 173246166Ssbruno break; 174248842Ssbruno case 0x3C: /* Per Intel document 325462-045US 01/2013. */ 175248842Ssbruno cputype = PMC_CPU_INTEL_HASWELL; 176248842Ssbruno nclasses = 5; 177248842Ssbruno break; 178266911Shiren case 0x4D: /* Per Intel document 330061-001 01/2014. */ 179266911Shiren cputype = PMC_CPU_INTEL_ATOM_SILVERMONT; 180266911Shiren nclasses = 3; 181266911Shiren break; 182184802Sjkoshy } 183184802Sjkoshy break; 184184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 185184802Sjkoshy case 0xF00: /* P4 */ 186184802Sjkoshy if (model >= 0 && model <= 6) /* known models */ 187184802Sjkoshy cputype = PMC_CPU_INTEL_PIV; 188184802Sjkoshy break; 189184802Sjkoshy } 190184802Sjkoshy#endif 191184802Sjkoshy 192184802Sjkoshy if ((int) cputype == -1) { 193184802Sjkoshy printf("pmc: Unknown Intel CPU.\n"); 194184802Sjkoshy return (NULL); 195184802Sjkoshy } 196184802Sjkoshy 197233628Sfabient /* Allocate base class and initialize machine dependent struct */ 198233628Sfabient pmc_mdep = pmc_mdep_alloc(nclasses); 199184802Sjkoshy 200249069Ssbruno pmc_mdep->pmd_cputype = cputype; 201184802Sjkoshy pmc_mdep->pmd_switch_in = intel_switch_in; 202184802Sjkoshy pmc_mdep->pmd_switch_out = intel_switch_out; 203184802Sjkoshy 204184802Sjkoshy ncpus = pmc_cpu_max(); 205250101Sdavide error = pmc_tsc_initialize(pmc_mdep, ncpus); 206250101Sdavide if (error) 207250101Sdavide goto error; 208184802Sjkoshy switch (cputype) { 209184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 210185363Sjkoshy /* 211185363Sjkoshy * Intel Core, Core 2 and Atom processors. 212185363Sjkoshy */ 213185363Sjkoshy case PMC_CPU_INTEL_ATOM: 214266911Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 215185363Sjkoshy case PMC_CPU_INTEL_CORE: 216185363Sjkoshy case PMC_CPU_INTEL_CORE2: 217185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 218187761Sjeff case PMC_CPU_INTEL_COREI7: 219267602Skib case PMC_CPU_INTEL_NEHALEM_EX: 220240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 221232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 222206089Sfabient case PMC_CPU_INTEL_WESTMERE: 223267602Skib case PMC_CPU_INTEL_WESTMERE_EX: 224241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 225246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 226248842Ssbruno case PMC_CPU_INTEL_HASWELL: 227185363Sjkoshy error = pmc_core_initialize(pmc_mdep, ncpus); 228185363Sjkoshy break; 229184802Sjkoshy 230184802Sjkoshy /* 231184802Sjkoshy * Intel Pentium 4 Processors, and P4/EMT64 processors. 232184802Sjkoshy */ 233184802Sjkoshy 234184802Sjkoshy case PMC_CPU_INTEL_PIV: 235184802Sjkoshy error = pmc_p4_initialize(pmc_mdep, ncpus); 236184802Sjkoshy break; 237184802Sjkoshy#endif 238184802Sjkoshy 239184802Sjkoshy#if defined(__i386__) 240184802Sjkoshy /* 241184802Sjkoshy * P6 Family Processors 242184802Sjkoshy */ 243184802Sjkoshy 244184802Sjkoshy case PMC_CPU_INTEL_P6: 245184802Sjkoshy case PMC_CPU_INTEL_CL: 246184802Sjkoshy case PMC_CPU_INTEL_PII: 247184802Sjkoshy case PMC_CPU_INTEL_PIII: 248184802Sjkoshy case PMC_CPU_INTEL_PM: 249184802Sjkoshy error = pmc_p6_initialize(pmc_mdep, ncpus); 250184802Sjkoshy break; 251184802Sjkoshy 252184802Sjkoshy /* 253184802Sjkoshy * Intel Pentium PMCs. 254184802Sjkoshy */ 255184802Sjkoshy 256184802Sjkoshy case PMC_CPU_INTEL_P5: 257184802Sjkoshy error = pmc_p5_initialize(pmc_mdep, ncpus); 258184802Sjkoshy break; 259184802Sjkoshy#endif 260184802Sjkoshy 261184802Sjkoshy default: 262184802Sjkoshy KASSERT(0, ("[intel,%d] Unknown CPU type", __LINE__)); 263184802Sjkoshy } 264184802Sjkoshy 265250101Sdavide if (error) { 266250101Sdavide pmc_tsc_finalize(pmc_mdep); 267233569Sgonzo goto error; 268250101Sdavide } 269233569Sgonzo 270206089Sfabient /* 271206089Sfabient * Init the uncore class. 272206089Sfabient */ 273206089Sfabient#if defined(__i386__) || defined(__amd64__) 274206089Sfabient switch (cputype) { 275206089Sfabient /* 276206089Sfabient * Intel Corei7 and Westmere processors. 277206089Sfabient */ 278206089Sfabient case PMC_CPU_INTEL_COREI7: 279248842Ssbruno case PMC_CPU_INTEL_HASWELL: 280232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 281206089Sfabient case PMC_CPU_INTEL_WESTMERE: 282206089Sfabient error = pmc_uncore_initialize(pmc_mdep, ncpus); 283206089Sfabient break; 284206089Sfabient default: 285206089Sfabient break; 286206089Sfabient } 287206089Sfabient#endif 288184802Sjkoshy error: 289184802Sjkoshy if (error) { 290250097Sdavide pmc_mdep_free(pmc_mdep); 291184802Sjkoshy pmc_mdep = NULL; 292184802Sjkoshy } 293184802Sjkoshy 294184802Sjkoshy return (pmc_mdep); 295184802Sjkoshy} 296184802Sjkoshy 297184802Sjkoshyvoid 298184802Sjkoshypmc_intel_finalize(struct pmc_mdep *md) 299184802Sjkoshy{ 300184802Sjkoshy pmc_tsc_finalize(md); 301184802Sjkoshy 302184802Sjkoshy switch (md->pmd_cputype) { 303184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 304185363Sjkoshy case PMC_CPU_INTEL_ATOM: 305266911Shiren case PMC_CPU_INTEL_ATOM_SILVERMONT: 306185363Sjkoshy case PMC_CPU_INTEL_CORE: 307185363Sjkoshy case PMC_CPU_INTEL_CORE2: 308185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 309206089Sfabient case PMC_CPU_INTEL_COREI7: 310267602Skib case PMC_CPU_INTEL_NEHALEM_EX: 311248842Ssbruno case PMC_CPU_INTEL_HASWELL: 312240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 313232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 314206089Sfabient case PMC_CPU_INTEL_WESTMERE: 315267602Skib case PMC_CPU_INTEL_WESTMERE_EX: 316241738Ssbruno case PMC_CPU_INTEL_SANDYBRIDGE_XEON: 317246166Ssbruno case PMC_CPU_INTEL_IVYBRIDGE_XEON: 318185363Sjkoshy pmc_core_finalize(md); 319185363Sjkoshy break; 320185363Sjkoshy 321184802Sjkoshy case PMC_CPU_INTEL_PIV: 322184802Sjkoshy pmc_p4_finalize(md); 323184802Sjkoshy break; 324184802Sjkoshy#endif 325184802Sjkoshy#if defined(__i386__) 326184802Sjkoshy case PMC_CPU_INTEL_P6: 327184802Sjkoshy case PMC_CPU_INTEL_CL: 328184802Sjkoshy case PMC_CPU_INTEL_PII: 329184802Sjkoshy case PMC_CPU_INTEL_PIII: 330184802Sjkoshy case PMC_CPU_INTEL_PM: 331184802Sjkoshy pmc_p6_finalize(md); 332184802Sjkoshy break; 333184802Sjkoshy case PMC_CPU_INTEL_P5: 334184802Sjkoshy pmc_p5_finalize(md); 335184802Sjkoshy break; 336184802Sjkoshy#endif 337184802Sjkoshy default: 338184802Sjkoshy KASSERT(0, ("[intel,%d] unknown CPU type", __LINE__)); 339184802Sjkoshy } 340206089Sfabient 341206089Sfabient /* 342206089Sfabient * Uncore. 343206089Sfabient */ 344206089Sfabient#if defined(__i386__) || defined(__amd64__) 345206089Sfabient switch (md->pmd_cputype) { 346206089Sfabient case PMC_CPU_INTEL_COREI7: 347248842Ssbruno case PMC_CPU_INTEL_HASWELL: 348232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 349206089Sfabient case PMC_CPU_INTEL_WESTMERE: 350206089Sfabient pmc_uncore_finalize(md); 351206089Sfabient break; 352206089Sfabient default: 353206089Sfabient break; 354206089Sfabient } 355206089Sfabient#endif 356184802Sjkoshy} 357