hwpmc_intel.c revision 240164
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: head/sys/dev/hwpmc/hwpmc_intel.c 240164 2012-09-06 13:54:01Z fabient $"); 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 */ 71184802Sjkoshy 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; 90184802Sjkoshy 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: 134200669Sjkoshy case 0x1E: /* Per Intel document 253669-032 9/2009, pages A-2 and A-57 */ 135200669Sjkoshy case 0x1F: /* Per Intel document 253669-032 9/2009, pages A-2 and A-57 */ 136206089Sfabient case 0x2E: 137187761Sjeff cputype = PMC_CPU_INTEL_COREI7; 138206089Sfabient nclasses = 5; 139187761Sjeff break; 140206089Sfabient case 0x25: /* Per Intel document 253669-033US 12/2009. */ 141206089Sfabient case 0x2C: /* Per Intel document 253669-033US 12/2009. */ 142206089Sfabient cputype = PMC_CPU_INTEL_WESTMERE; 143206089Sfabient nclasses = 5; 144206089Sfabient break; 145232366Sdavide case 0x2A: /* Per Intel document 253669-039US 05/2011. */ 146232366Sdavide cputype = PMC_CPU_INTEL_SANDYBRIDGE; 147232366Sdavide nclasses = 5; 148232366Sdavide break; 149240164Sfabient case 0x3A: /* Per Intel document 253669-043US 05/2012. */ 150240164Sfabient cputype = PMC_CPU_INTEL_IVYBRIDGE; 151240164Sfabient nclasses = 3; 152240164Sfabient break; 153184802Sjkoshy } 154184802Sjkoshy break; 155184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 156184802Sjkoshy case 0xF00: /* P4 */ 157184802Sjkoshy if (model >= 0 && model <= 6) /* known models */ 158184802Sjkoshy cputype = PMC_CPU_INTEL_PIV; 159184802Sjkoshy break; 160184802Sjkoshy } 161184802Sjkoshy#endif 162184802Sjkoshy 163184802Sjkoshy if ((int) cputype == -1) { 164184802Sjkoshy printf("pmc: Unknown Intel CPU.\n"); 165184802Sjkoshy return (NULL); 166184802Sjkoshy } 167184802Sjkoshy 168233628Sfabient /* Allocate base class and initialize machine dependent struct */ 169233628Sfabient pmc_mdep = pmc_mdep_alloc(nclasses); 170184802Sjkoshy 171184802Sjkoshy pmc_mdep->pmd_cputype = cputype; 172184802Sjkoshy pmc_mdep->pmd_switch_in = intel_switch_in; 173184802Sjkoshy pmc_mdep->pmd_switch_out = intel_switch_out; 174184802Sjkoshy 175184802Sjkoshy ncpus = pmc_cpu_max(); 176184802Sjkoshy 177184802Sjkoshy error = pmc_tsc_initialize(pmc_mdep, ncpus); 178184802Sjkoshy if (error) 179184802Sjkoshy goto error; 180184802Sjkoshy 181184802Sjkoshy switch (cputype) { 182184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 183185363Sjkoshy /* 184185363Sjkoshy * Intel Core, Core 2 and Atom processors. 185185363Sjkoshy */ 186185363Sjkoshy case PMC_CPU_INTEL_ATOM: 187185363Sjkoshy case PMC_CPU_INTEL_CORE: 188185363Sjkoshy case PMC_CPU_INTEL_CORE2: 189185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 190187761Sjeff case PMC_CPU_INTEL_COREI7: 191240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 192232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 193206089Sfabient case PMC_CPU_INTEL_WESTMERE: 194185363Sjkoshy error = pmc_core_initialize(pmc_mdep, ncpus); 195185363Sjkoshy break; 196184802Sjkoshy 197184802Sjkoshy /* 198184802Sjkoshy * Intel Pentium 4 Processors, and P4/EMT64 processors. 199184802Sjkoshy */ 200184802Sjkoshy 201184802Sjkoshy case PMC_CPU_INTEL_PIV: 202184802Sjkoshy error = pmc_p4_initialize(pmc_mdep, ncpus); 203184802Sjkoshy break; 204184802Sjkoshy#endif 205184802Sjkoshy 206184802Sjkoshy#if defined(__i386__) 207184802Sjkoshy /* 208184802Sjkoshy * P6 Family Processors 209184802Sjkoshy */ 210184802Sjkoshy 211184802Sjkoshy case PMC_CPU_INTEL_P6: 212184802Sjkoshy case PMC_CPU_INTEL_CL: 213184802Sjkoshy case PMC_CPU_INTEL_PII: 214184802Sjkoshy case PMC_CPU_INTEL_PIII: 215184802Sjkoshy case PMC_CPU_INTEL_PM: 216184802Sjkoshy error = pmc_p6_initialize(pmc_mdep, ncpus); 217184802Sjkoshy break; 218184802Sjkoshy 219184802Sjkoshy /* 220184802Sjkoshy * Intel Pentium PMCs. 221184802Sjkoshy */ 222184802Sjkoshy 223184802Sjkoshy case PMC_CPU_INTEL_P5: 224184802Sjkoshy error = pmc_p5_initialize(pmc_mdep, ncpus); 225184802Sjkoshy break; 226184802Sjkoshy#endif 227184802Sjkoshy 228184802Sjkoshy default: 229184802Sjkoshy KASSERT(0, ("[intel,%d] Unknown CPU type", __LINE__)); 230184802Sjkoshy } 231184802Sjkoshy 232233569Sgonzo if (error) 233233569Sgonzo goto error; 234233569Sgonzo 235206089Sfabient /* 236206089Sfabient * Init the uncore class. 237206089Sfabient */ 238206089Sfabient#if defined(__i386__) || defined(__amd64__) 239206089Sfabient switch (cputype) { 240206089Sfabient /* 241206089Sfabient * Intel Corei7 and Westmere processors. 242206089Sfabient */ 243206089Sfabient case PMC_CPU_INTEL_COREI7: 244232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 245206089Sfabient case PMC_CPU_INTEL_WESTMERE: 246206089Sfabient error = pmc_uncore_initialize(pmc_mdep, ncpus); 247206089Sfabient break; 248206089Sfabient default: 249206089Sfabient break; 250206089Sfabient } 251206089Sfabient#endif 252184802Sjkoshy 253184802Sjkoshy error: 254184802Sjkoshy if (error) { 255184802Sjkoshy free(pmc_mdep, M_PMC); 256184802Sjkoshy pmc_mdep = NULL; 257184802Sjkoshy } 258184802Sjkoshy 259184802Sjkoshy return (pmc_mdep); 260184802Sjkoshy} 261184802Sjkoshy 262184802Sjkoshyvoid 263184802Sjkoshypmc_intel_finalize(struct pmc_mdep *md) 264184802Sjkoshy{ 265184802Sjkoshy pmc_tsc_finalize(md); 266184802Sjkoshy 267184802Sjkoshy switch (md->pmd_cputype) { 268184802Sjkoshy#if defined(__i386__) || defined(__amd64__) 269185363Sjkoshy case PMC_CPU_INTEL_ATOM: 270185363Sjkoshy case PMC_CPU_INTEL_CORE: 271185363Sjkoshy case PMC_CPU_INTEL_CORE2: 272185585Sjkoshy case PMC_CPU_INTEL_CORE2EXTREME: 273206089Sfabient case PMC_CPU_INTEL_COREI7: 274240164Sfabient case PMC_CPU_INTEL_IVYBRIDGE: 275232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 276206089Sfabient case PMC_CPU_INTEL_WESTMERE: 277185363Sjkoshy pmc_core_finalize(md); 278185363Sjkoshy break; 279185363Sjkoshy 280184802Sjkoshy case PMC_CPU_INTEL_PIV: 281184802Sjkoshy pmc_p4_finalize(md); 282184802Sjkoshy break; 283184802Sjkoshy#endif 284184802Sjkoshy#if defined(__i386__) 285184802Sjkoshy case PMC_CPU_INTEL_P6: 286184802Sjkoshy case PMC_CPU_INTEL_CL: 287184802Sjkoshy case PMC_CPU_INTEL_PII: 288184802Sjkoshy case PMC_CPU_INTEL_PIII: 289184802Sjkoshy case PMC_CPU_INTEL_PM: 290184802Sjkoshy pmc_p6_finalize(md); 291184802Sjkoshy break; 292184802Sjkoshy case PMC_CPU_INTEL_P5: 293184802Sjkoshy pmc_p5_finalize(md); 294184802Sjkoshy break; 295184802Sjkoshy#endif 296184802Sjkoshy default: 297184802Sjkoshy KASSERT(0, ("[intel,%d] unknown CPU type", __LINE__)); 298184802Sjkoshy } 299206089Sfabient 300206089Sfabient /* 301206089Sfabient * Uncore. 302206089Sfabient */ 303206089Sfabient#if defined(__i386__) || defined(__amd64__) 304206089Sfabient switch (md->pmd_cputype) { 305206089Sfabient case PMC_CPU_INTEL_COREI7: 306232366Sdavide case PMC_CPU_INTEL_SANDYBRIDGE: 307206089Sfabient case PMC_CPU_INTEL_WESTMERE: 308206089Sfabient pmc_uncore_finalize(md); 309206089Sfabient break; 310206089Sfabient default: 311206089Sfabient break; 312206089Sfabient } 313206089Sfabient#endif 314184802Sjkoshy} 315