]>
Commit | Line | Data |
---|---|---|
91447636 A |
1 | /* |
2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. | |
3 | * | |
2d21ac55 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
91447636 | 5 | * |
2d21ac55 A |
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. | |
8f6c56a5 | 14 | * |
2d21ac55 A |
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 | |
8f6c56a5 A |
20 | * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, |
21 | * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, | |
2d21ac55 A |
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. | |
8f6c56a5 | 25 | * |
2d21ac55 | 26 | * @APPLE_OSREFERENCE_LICENSE_HEADER_END@ |
91447636 A |
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 | ||
49 | static inline boolean_t | |
50 | pmc_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) | |
2d21ac55 A |
67 | typedef union { |
68 | struct { | |
91447636 A |
69 | uint64_t counter : 40; |
70 | uint64_t reserved : 24; | |
2d21ac55 A |
71 | } fld; |
72 | uint64_t u64; | |
91447636 | 73 | } pmc_counter_t; |
2d21ac55 | 74 | #define PMC_COUNTER_ZERO { .u64 = 0 } |
91447636 A |
75 | |
76 | ||
77 | /* | |
2d21ac55 | 78 | * There are 2 basic flavors of PMCs: P6 (or Core) and P4/Xeon: |
91447636 A |
79 | */ |
80 | typedef enum { | |
2d21ac55 | 81 | pmc_none = 0, |
91447636 A |
82 | pmc_P6, |
83 | pmc_P4_Xeon, | |
2d21ac55 | 84 | pmc_Core, |
91447636 A |
85 | pmc_unknown |
86 | } pmc_machine_t; | |
87 | ||
2d21ac55 A |
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) | |
94 | typedef 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) | |
110 | typedef 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) | |
126 | typedef 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) | |
139 | typedef 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 | ||
91447636 A |
154 | /* |
155 | * P6 MSRs... | |
156 | */ | |
157 | #define MSR_P6_COUNTER_ADDR(n) (0x0c1 + (n)) | |
158 | #define MSR_P6_PES_ADDR(n) (0x186 + (n)) | |
2d21ac55 A |
159 | #define MSR_IA32_PMC(n) (0x0c1 + (n)) |
160 | #define MSR_IA32_PERFEVTSEL(n) (0x186 + (n)) | |
91447636 | 161 | |
2d21ac55 A |
162 | typedef union { |
163 | struct { | |
91447636 A |
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; | |
2d21ac55 A |
175 | } fld; |
176 | uint64_t u64; | |
91447636 | 177 | } pmc_evtsel_t; |
2d21ac55 A |
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 } | |
91447636 A |
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 | ||
224 | typedef 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 | ||
290 | typedef 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) | |
308 | typedef 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; | |
318 | typedef 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; | |
329 | typedef 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) | |
356 | typedef 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; | |
372 | typedef 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; | |
389 | typedef 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 | ||
396 | typedef void (pmc_ovf_func_t)(pmc_id_t id, void *state); | |
397 | ||
398 | /* | |
399 | * In-kernel PMC access primitives: | |
400 | */ | |
401 | /* Generic: */ | |
0c530ab8 | 402 | extern void *pmc_alloc(void); |
91447636 A |
403 | extern int pmc_machine_type(pmc_machine_t *type); |
404 | extern boolean_t pmc_is_reserved(pmc_id_t id); | |
405 | extern int pmc_reserve(pmc_id_t id); | |
406 | extern int pmc_free(pmc_id_t id); | |
407 | extern int pmc_counter_read(pmc_id_t id, pmc_counter_t *val); | |
408 | extern int pmc_counter_write(pmc_id_t id, pmc_counter_t *val); | |
409 | ||
410 | /* P6-specific: */ | |
411 | extern int pmc_evtsel_read(pmc_id_t id, pmc_evtsel_t *evtsel); | |
412 | extern int pmc_evtsel_write(pmc_id_t id, pmc_evtsel_t *evtsel); | |
413 | ||
414 | /* P4/Xeon-specific: */ | |
415 | extern int pmc_cccr_read(pmc_id_t id, pmc_cccr_t *cccr); | |
416 | extern int pmc_cccr_write(pmc_id_t id, pmc_cccr_t *cccr); | |
417 | extern int pmc_escr_read(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); | |
418 | extern int pmc_escr_write(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); | |
419 | extern int pmc_set_ovf_func(pmc_id_t id, pmc_ovf_func_t *func); | |
420 | ||
0c530ab8 A |
421 | extern int pmc_acquire(task_t); |
422 | extern int pmc_release(task_t); | |
423 | ||
91447636 | 424 | #endif /* _I386_PERFMON_H_ */ |