1/* 2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. 3 * 4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ 5 * 6 * This file contains Original Code and/or Modifications of Original Code 7 * as defined in and that are subject to the Apple Public Source License 8 * Version 2.0 (the 'License'). You may not use this file except in 9 * compliance with the License. The rights granted to you under the License 10 * may not be used to create, or enable the creation or redistribution of, 11 * unlawful or unlicensed copies of an Apple operating system, or to 12 * circumvent, violate, or enable the circumvention or violation of, any 13 * terms of an Apple operating system software license agreement. 14 * 15 * Please obtain a copy of the License at 16 * http://www.opensource.apple.com/apsl/ and read it before using this file. 17 * 18 * The Original Code and all software distributed under the License are 19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER 20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, 21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, 22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. 23 * Please see the License for the specific language governing rights and 24 * limitations under the License. 25 * 26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ 27 */ 28#ifndef _I386_PERFMON_H_ 29#define _I386_PERFMON_H_ 30 31#include <i386/proc_reg.h> 32 33/* 34 * Handy macros for bit/bitfield definition and manipulations: 35 */ 36#define bit(n) (1ULL << (n)) 37#define field(n,m) ((bit((m)+1)-1) & ~(bit(n)-1)) 38#define field_nbit(fld) (ffs(fld)-1) 39#define field_select(fld,x) ((x) & (fld)) 40#define field_clear(fld,x) ((x) & ~(fld)) 41#define field_unshift(fld,x) ((x) >> field_nbit(fld)) 42#define field_shift(fld,x) ((x) << field_nbit(fld)) 43#define field_get(fld,x) (field_unshift(fld,field_select(fld,x))) 44#define field_set(fld,x,val) (field_clear(fld,x) | field_shift(fld,val)) 45 46#define PERFMON_AVAILABLE bit(7) 47#define BTS_UNAVAILABLE bit(11) 48 49static inline boolean_t 50pmc_is_available(void) 51{ 52 uint32_t lo; 53 uint32_t hi; 54 int ret; 55 56 ret = rdmsr_carefully(MSR_IA32_MISC_ENABLE, &lo, &hi); 57 58 return (ret == 0) && ((lo & PERFMON_AVAILABLE) != 0); 59} 60 61/* 62 * Counter layout: 63 */ 64#define PMC_COUNTER_COUNTER field(0,39) 65#define PMC_COUNTER_RESERVED field(40,64) 66#define PMC_COUNTER_MAX ((uint64_t) PMC_COUNTER_COUNTER) 67typedef union { 68 struct { 69 uint64_t counter : 40; 70 uint64_t reserved : 24; 71 } fld; 72 uint64_t u64; 73} pmc_counter_t; 74#define PMC_COUNTER_ZERO { .u64 = 0 } 75 76 77/* 78 * There are 2 basic flavors of PMCs: P6 (or Core) and P4/Xeon: 79 */ 80typedef enum { 81 pmc_none = 0, 82 pmc_P6, 83 pmc_P4_Xeon, 84 pmc_Core, 85 pmc_unknown 86} pmc_machine_t; 87 88#define MSR_PERF_FIXED_CTR(n) (0x309 + (n)) 89#define MSR_PERF_INST_RETIRED MSR_PERF_FIXED_CTR(0) 90#define MSR_PERF_CPU_CLK_UNHALTED_CORE MSR_PERF_FIXED_CTR(1) 91#define MSR_PERF_CPU_CLK_UNHALTED_REF MSR_PERF_FIXED_CTR(2) 92 93#define MSR_PERF_FIXED_CTR_CTRL (0x38d) 94typedef union { 95 struct { 96 uint64_t FIXED_CTR0_enable :2; 97 uint64_t reserved0 :1; 98 uint64_t FIXED_CTR0_pmi :1; 99 uint64_t FIXED_CTR1_enable :2; 100 uint64_t reserved1 :1; 101 uint64_t FIXED_CTR1_pmi :1; 102 uint64_t FIXED_CTR2_enable :2; 103 uint64_t reserved2 :1; 104 uint64_t FIXED_CTR2_pmi :1; 105 } fld; 106 uint64_t u64; 107} pmc_fixed_ctr_ctrl_t; 108 109#define MSR_PERF_GLOBAL_STATUS (0x38e) 110typedef union { 111 struct { 112 uint64_t PMC0_overflow : 1; 113 uint64_t PMC1_overflow : 1; 114 uint64_t reserved1 : 30; 115 uint64_t FIXED_CTR0_overflow : 1; 116 uint64_t FIXED_CTR1_overflow : 1; 117 uint64_t FIXED_CTR2_overflow : 1; 118 uint64_t reserved2 : 27; 119 uint64_t ovf_buffer : 1; 120 uint64_t cond_changed : 1; 121 } fld; 122 uint64_t u64; 123} pmc_global_status_t; 124 125#define MSR_PERF_GLOBAL_CTRL (0x38f) 126typedef union { 127 struct { 128 uint64_t PMC0_enable : 1; 129 uint64_t PMC1_enable : 1; 130 uint64_t reserved1 : 30; 131 uint64_t FIXED_CTR0_enable : 1; 132 uint64_t FIXED_CTR1_enable : 1; 133 uint64_t FIXED_CTR2_enable : 1; 134 } fld; 135 uint64_t u64; 136} pmc_global_ctrl_t; 137 138#define MSR_PERF_GLOBAL_OVF_CTRL (0x390) 139typedef union { 140 struct { 141 uint64_t PMC0_clr_overflow : 1; 142 uint64_t PMC1_clr_overflow : 1; 143 uint64_t reserved1 : 30; 144 uint64_t FIXED_CTR0_clr_overflow : 1; 145 uint64_t FIXED_CTR1_clr_overflow : 1; 146 uint64_t FIXED_CTR2_clr_overflow : 1; 147 uint64_t reserved2 : 27; 148 uint64_t clr_ovf_buffer : 1; 149 uint64_t clr_cond_changed : 1; 150 } fld; 151 uint64_t u64; 152} pmc_global_ovf_ctrl; 153 154/* 155 * P6 MSRs... 156 */ 157#define MSR_P6_COUNTER_ADDR(n) (0x0c1 + (n)) 158#define MSR_P6_PES_ADDR(n) (0x186 + (n)) 159#define MSR_IA32_PMC(n) (0x0c1 + (n)) 160#define MSR_IA32_PERFEVTSEL(n) (0x186 + (n)) 161 162typedef union { 163 struct { 164 uint64_t event_select : 8; 165 uint64_t umask : 8; 166 uint64_t usr : 1; 167 uint64_t os : 1; 168 uint64_t e : 1; 169 uint64_t pc : 1; 170 uint64_t apic_int : 1; 171 uint64_t reserved1 : 1; 172 uint64_t en : 1; 173 uint64_t inv : 1; 174 uint64_t cmask : 8; 175 } fld; 176 uint64_t u64; 177} pmc_evtsel_t; 178#define PMC_EVTSEL_ZERO { .u64 = 0ULL } 179 180 181/* 182 * Non-architectural event selectors. See Vol 3b, section 18.13: 183 */ 184#define PMC_EVTSEL_ALLCORES (bit(15)|bit(14)) 185#define PMC_EVTSEL_THISCORE (bit(14)) 186#define PMC_EVTSEL_ALLAGENTS (bit(14)) 187#define PMC_EVTSEL_THISAGENT (0ULL) } 188#define PMC_EVTSEL_PREFETCH_ALL (bit(13)|bit(12)) 189#define PMC_EVTSEL_PREFETCH_HW (bit(12)) 190#define PMC_EVTSEL_PREFETCH_NOHW (0ULL) 191#define PMC_EVTSEL_MESI_MOD (bit(11)) 192#define PMC_EVTSEL_MESI_EXCL (bit(10)) 193#define PMC_EVTSEL_MESI_SHRD (bit(9)) 194#define PMC_EVTSEL_MESI_INVAL (bit(8)) 195 196#define PMC_EVTSEL_SNOOP_HITM (bit(11)) 197#define PMC_EVTSEL_SNOOP_HIT (bit(9)) 198#define PMC_EVTSEL_SNOOP_CLEAN (bit(8)) 199#define PMC_EVTSEL_SNOOP_CMP2I (bit(9)) 200#define PMC_EVTSEL_SNOOP_CMP2S (bit(8)) 201 202#define PMC_CORE_ITLB_MISS_RETIRED \ 203 { .fld.event_select = 0xc9, .fld.umask = 0 } 204#define PMC_CORE_MEM_LOAD_RETIRED_L1D_MISS \ 205 { .fld.event_select = 0xcb, .fld.umask = 1 } 206#define PMC_CORE_MEM_LOAD_RETIRED_L1D_LINE_MISS \ 207 { .fld.event_select = 0xcb, .fld.umask = 2 } 208#define PMC_CORE_MEM_LOAD_RETIRED_L2_MISS \ 209 { .fld.event_select = 0xcb, .fld.umask = 4 } 210#define PMC_CORE_MEM_LOAD_RETIRED_L2_LINE_MISS \ 211 { .fld.event_select = 0xcb, .fld.umask = 8 } 212#define PMC_CORE_MEM_LOAD_RETIRED_DTLB_MISS \ 213 { .fld.event_select = 0xcb, .fld.umask = 0x10 } 214 215#define MSR_P6_PERFCTR0 0 216#define MSR_P6_PERFCTR1 1 217 218/* 219 * P4/Xeon MSRs... 220 */ 221#define MSR_COUNTER_ADDR(n) (0x300 + (n)) 222#define MSR_CCCR_ADDR(n) (0x360 + (n)) 223 224typedef enum { 225 MSR_BPU_COUNTER0 = 0, 226 MSR_BPU_COUNTER1 = 1, 227 #define MSR_BSU_ESCR0 7 228 #define MSR_FSB_ESCR0 6 229 #define MSR_MOB_ESCR0 2 230 #define MSR_PMH_ESCR0 4 231 #define MSR_BPU_ESCR0 0 232 #define MSR_IS_ESCR0 1 233 #define MSR_ITLB_ESCR0 3 234 #define MSR_IX_ESCR0 5 235 MSR_BPU_COUNTER2 = 2, 236 MSR_BPU_COUNTER3 = 3, 237 #define MSR_BSU_ESCR1 7 238 #define MSR_FSB_ESCR1 6 239 #define MSR_MOB_ESCR1 2 240 #define MSR_PMH_ESCR1 4 241 #define MSR_BPU_ESCR1 0 242 #define MSR_IS_ESCR1 1 243 #define MSR_ITLB_ESCR1 3 244 #define MSR_IX_ESCR1 5 245 MSR_MS_COUNTER0 = 4, 246 MSR_MS_COUNTER1 = 5, 247 #define MSR_MS_ESCR0 0 248 #define MSR_TBPU_ESCR0 2 249 #define MSR_TC_ESCR0 1 250 MSR_MS_COUNTER2 = 6, 251 MSR_MS_COUNTER3 = 7, 252 #define MSR_MS_ESCR1 0 253 #define MSR_TBPU_ESCR1 2 254 #define MSR_TC_ESCR1 1 255 MSR_FLAME_COUNTER0 = 8, 256 MSR_FLAME_COUNTER1 = 9, 257 #define MSR_FIRM_ESCR0 1 258 #define MSR_FLAME_ESCR0 0 259 #define MSR_DAC_ESCR0 5 260 #define MSR_SAT_ESCR0 2 261 #define MSR_U2L_ESCR0 3 262 MSR_FLAME_COUNTER2 = 10, 263 MSR_FLAME_COUNTER3 = 11, 264 #define MSR_FIRM_ESCR1 1 265 #define MSR_FLAME_ESCR1 0 266 #define MSR_DAC_ESCR1 5 267 #define MSR_SAT_ESCR1 2 268 #define MSR_U2L_ESCR1 3 269 MSR_IQ_COUNTER0 = 12, 270 MSR_IQ_COUNTER1 = 13, 271 MSR_IQ_COUNTER4 = 16, 272 #define MSR_CRU_ESCR0 4 273 #define MSR_CRU_ESCR2 5 274 #define MSR_CRU_ESCR4 6 275 #define MSR_IQ_ESCR0 0 276 #define MSR_RAT_ESCR0 2 277 #define MSR_SSU_ESCR0 3 278 #define MSR_AFL_ESCR0 1 279 MSR_IQ_COUNTER2 = 14, 280 MSR_IQ_COUNTER3 = 15, 281 MSR_IQ_COUNTER5 = 17, 282 #define MSR_CRU_ESCR1 4 283 #define MSR_CRU_ESCR3 5 284 #define MSR_CRU_ESCR5 6 285 #define MSR_IQ_ESCR1 0 286 #define MSR_RAT_ESCR1 2 287 #define MSR_AFL_ESCR1 1 288} pmc_id_t; 289 290typedef int pmc_escr_id_t; 291#define PMC_ESID_MAX 7 292 293/* 294 * ESCR MSR layout: 295 */ 296#define PMC_ECSR_NOHTT_RESERVED field(0,1) 297#define PMC_ECSR_T0_USR bit(0) 298#define PMC_ECSR_T0_OS bit(1) 299#define PMC_ECSR_T1_USR bit(2) 300#define PMC_ECSR_T1_OS bit(3) 301#define PMC_ECSR_USR bit(2) 302#define PMC_ECSR_OS bit(3) 303#define PMC_ECSR_TAG_ENABLE bit(4) 304#define PMC_ECSR_TAG_VALUE field(5,8) 305#define PMC_ECSR_EVENT_MASK field(9,24) 306#define PMC_ECSR_EVENT_SELECT field(25,30) 307#define PMC_ECSR_RESERVED2 field(30,64) 308typedef struct { 309 uint64_t reserved1 : 2; 310 uint64_t usr : 1; 311 uint64_t os : 1; 312 uint64_t tag_enable : 1; 313 uint64_t tag_value : 4; 314 uint64_t event_mask : 16; 315 uint64_t event_select : 6; 316 uint64_t reserved2 : 33; 317} pmc_escr_nohtt_t; 318typedef struct { 319 uint64_t t0_usr : 1; 320 uint64_t t0_os : 1; 321 uint64_t t1_usr : 1; 322 uint64_t t1_os : 1; 323 uint64_t tag_enable : 1; 324 uint64_t tag_value : 4; 325 uint64_t event_mask : 16; 326 uint64_t event_select : 6; 327 uint64_t reserved2 : 33; 328} pmc_escr_htt_t; 329typedef union { 330 pmc_escr_nohtt_t u_nohtt; 331 pmc_escr_htt_t u_htt; 332 uint64_t u_u64; 333} pmc_escr_t; 334#define PMC_ESCR_ZERO { .u_u64 = 0ULL } 335 336/* 337 * CCCR MSR layout: 338 */ 339#define PMC_CCCR_RESERVED1 field(1,11) 340#define PMC_CCCR_ENABLE bit(12) 341#define PMC_CCCR_ECSR_SELECT field(13,15) 342#define PMC_CCCR_RESERVED2 field(16,17) 343#define PMC_CCCR_HTT_ACTIVE field(16,17) 344#define PMC_CCCR_COMPARE bit(18) 345#define PMC_CCCR_COMPLEMENT bit(19) 346#define PMC_CCCR_THRESHOLD field(20,23) 347#define PMC_CCCR_EDGE bit(24) 348#define PMC_CCCR_FORCE_OVF bit(25) 349#define PMC_CCCR_OVF_PMI bit(26) 350#define PMC_CCCR_NOHTT_RESERVED2 field(27,29) 351#define PMC_CCCR_OVF_PMI_T0 bit(26) 352#define PMC_CCCR_OVF_PMI_T1 bit(27) 353#define PMC_CCCR_HTT_RESERVED2 field(28,29) 354#define PMC_CCCR_CASCADE bit(30) 355#define PMC_CCCR_OVF bit(31) 356typedef struct { 357 uint64_t reserved1 : 12; 358 uint64_t enable : 1; 359 uint64_t escr_select : 3; 360 uint64_t reserved2 : 2; 361 uint64_t compare : 1; 362 uint64_t complement : 1; 363 uint64_t threshold : 4; 364 uint64_t edge : 1; 365 uint64_t force_ovf : 1; 366 uint64_t ovf_pmi : 1; 367 uint64_t reserved3 : 3; 368 uint64_t cascade : 1; 369 uint64_t ovf : 1; 370 uint64_t reserved4 : 32; 371} pmc_cccr_nohtt_t; 372typedef struct { 373 uint64_t reserved1 : 12; 374 uint64_t enable : 1; 375 uint64_t escr_select : 3; 376 uint64_t active_thread : 2; 377 uint64_t compare : 1; 378 uint64_t complement : 1; 379 uint64_t threshold : 4; 380 uint64_t edge : 1; 381 uint64_t force_OVF : 1; 382 uint64_t ovf_pmi_t0 : 1; 383 uint64_t ovf_pmi_t1 : 1; 384 uint64_t reserved3 : 2; 385 uint64_t cascade : 1; 386 uint64_t ovf : 1; 387 uint64_t reserved4 : 32; 388} pmc_cccr_htt_t; 389typedef union { 390 pmc_cccr_nohtt_t u_nohtt; 391 pmc_cccr_htt_t u_htt; 392 uint64_t u_u64; 393} pmc_cccr_t; 394#define PMC_CCCR_ZERO { .u_u64 = 0ULL } 395 396typedef void (pmc_ovf_func_t)(pmc_id_t id, void *state); 397 398/* 399 * In-kernel PMC access primitives: 400 */ 401/* Generic: */ 402extern void *pmc_alloc(void); 403extern int pmc_machine_type(pmc_machine_t *type); 404extern boolean_t pmc_is_reserved(pmc_id_t id); 405extern int pmc_reserve(pmc_id_t id); 406extern int pmc_free(pmc_id_t id); 407extern int pmc_counter_read(pmc_id_t id, pmc_counter_t *val); 408extern int pmc_counter_write(pmc_id_t id, pmc_counter_t *val); 409 410/* P6-specific: */ 411extern int pmc_evtsel_read(pmc_id_t id, pmc_evtsel_t *evtsel); 412extern int pmc_evtsel_write(pmc_id_t id, pmc_evtsel_t *evtsel); 413 414/* P4/Xeon-specific: */ 415extern int pmc_cccr_read(pmc_id_t id, pmc_cccr_t *cccr); 416extern int pmc_cccr_write(pmc_id_t id, pmc_cccr_t *cccr); 417extern int pmc_escr_read(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); 418extern int pmc_escr_write(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); 419extern int pmc_set_ovf_func(pmc_id_t id, pmc_ovf_func_t *func); 420 421extern int pmc_acquire(task_t); 422extern int pmc_release(task_t); 423 424#endif /* _I386_PERFMON_H_ */ 425