]>
Commit | Line | Data |
---|---|---|
91447636 A |
1 | /* |
2 | * Copyright (c) 2003 Apple Computer, Inc. All rights reserved. | |
3 | * | |
8f6c56a5 | 4 | * @APPLE_OSREFERENCE_LICENSE_HEADER_START@ |
91447636 | 5 | * |
8f6c56a5 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. | |
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 | |
8ad349bb | 24 | * limitations under the License. |
8f6c56a5 A |
25 | * |
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) | |
67 | typedef struct { | |
68 | uint64_t counter : 40; | |
69 | uint64_t reserved : 24; | |
70 | } pmc_counter_t; | |
71 | #define PMC_COUNTER_ZERO { 0, 0 } | |
72 | ||
73 | ||
74 | /* | |
75 | * There are 2 basic flavors of PMCsL: P6 and P4/Xeon: | |
76 | */ | |
77 | typedef enum { | |
78 | pmc_none, | |
79 | pmc_P6, | |
80 | pmc_P4_Xeon, | |
81 | pmc_unknown | |
82 | } pmc_machine_t; | |
83 | ||
84 | /* | |
85 | * P6 MSRs... | |
86 | */ | |
87 | #define MSR_P6_COUNTER_ADDR(n) (0x0c1 + (n)) | |
88 | #define MSR_P6_PES_ADDR(n) (0x186 + (n)) | |
89 | ||
90 | typedef struct { | |
91 | uint64_t event_select : 8; | |
92 | uint64_t umask : 8; | |
93 | uint64_t usr : 1; | |
94 | uint64_t os : 1; | |
95 | uint64_t e : 1; | |
96 | uint64_t pc : 1; | |
97 | uint64_t apic_int : 1; | |
98 | uint64_t reserved1 : 1; | |
99 | uint64_t en : 1; | |
100 | uint64_t inv : 1; | |
101 | uint64_t cmask : 8; | |
102 | } pmc_evtsel_t; | |
103 | #define PMC_EVTSEL_ZERO ((pmc_evtsel_t){ 0,0,0,0,0,0,0,0,0,0,0 }) | |
104 | ||
105 | #define MSR_P6_PERFCTR0 0 | |
106 | #define MSR_P6_PERFCTR1 1 | |
107 | ||
108 | /* | |
109 | * P4/Xeon MSRs... | |
110 | */ | |
111 | #define MSR_COUNTER_ADDR(n) (0x300 + (n)) | |
112 | #define MSR_CCCR_ADDR(n) (0x360 + (n)) | |
113 | ||
114 | typedef enum { | |
115 | MSR_BPU_COUNTER0 = 0, | |
116 | MSR_BPU_COUNTER1 = 1, | |
117 | #define MSR_BSU_ESCR0 7 | |
118 | #define MSR_FSB_ESCR0 6 | |
119 | #define MSR_MOB_ESCR0 2 | |
120 | #define MSR_PMH_ESCR0 4 | |
121 | #define MSR_BPU_ESCR0 0 | |
122 | #define MSR_IS_ESCR0 1 | |
123 | #define MSR_ITLB_ESCR0 3 | |
124 | #define MSR_IX_ESCR0 5 | |
125 | MSR_BPU_COUNTER2 = 2, | |
126 | MSR_BPU_COUNTER3 = 3, | |
127 | #define MSR_BSU_ESCR1 7 | |
128 | #define MSR_FSB_ESCR1 6 | |
129 | #define MSR_MOB_ESCR1 2 | |
130 | #define MSR_PMH_ESCR1 4 | |
131 | #define MSR_BPU_ESCR1 0 | |
132 | #define MSR_IS_ESCR1 1 | |
133 | #define MSR_ITLB_ESCR1 3 | |
134 | #define MSR_IX_ESCR1 5 | |
135 | MSR_MS_COUNTER0 = 4, | |
136 | MSR_MS_COUNTER1 = 5, | |
137 | #define MSR_MS_ESCR0 0 | |
138 | #define MSR_TBPU_ESCR0 2 | |
139 | #define MSR_TC_ESCR0 1 | |
140 | MSR_MS_COUNTER2 = 6, | |
141 | MSR_MS_COUNTER3 = 7, | |
142 | #define MSR_MS_ESCR1 0 | |
143 | #define MSR_TBPU_ESCR1 2 | |
144 | #define MSR_TC_ESCR1 1 | |
145 | MSR_FLAME_COUNTER0 = 8, | |
146 | MSR_FLAME_COUNTER1 = 9, | |
147 | #define MSR_FIRM_ESCR0 1 | |
148 | #define MSR_FLAME_ESCR0 0 | |
149 | #define MSR_DAC_ESCR0 5 | |
150 | #define MSR_SAT_ESCR0 2 | |
151 | #define MSR_U2L_ESCR0 3 | |
152 | MSR_FLAME_COUNTER2 = 10, | |
153 | MSR_FLAME_COUNTER3 = 11, | |
154 | #define MSR_FIRM_ESCR1 1 | |
155 | #define MSR_FLAME_ESCR1 0 | |
156 | #define MSR_DAC_ESCR1 5 | |
157 | #define MSR_SAT_ESCR1 2 | |
158 | #define MSR_U2L_ESCR1 3 | |
159 | MSR_IQ_COUNTER0 = 12, | |
160 | MSR_IQ_COUNTER1 = 13, | |
161 | MSR_IQ_COUNTER4 = 16, | |
162 | #define MSR_CRU_ESCR0 4 | |
163 | #define MSR_CRU_ESCR2 5 | |
164 | #define MSR_CRU_ESCR4 6 | |
165 | #define MSR_IQ_ESCR0 0 | |
166 | #define MSR_RAT_ESCR0 2 | |
167 | #define MSR_SSU_ESCR0 3 | |
168 | #define MSR_AFL_ESCR0 1 | |
169 | MSR_IQ_COUNTER2 = 14, | |
170 | MSR_IQ_COUNTER3 = 15, | |
171 | MSR_IQ_COUNTER5 = 17, | |
172 | #define MSR_CRU_ESCR1 4 | |
173 | #define MSR_CRU_ESCR3 5 | |
174 | #define MSR_CRU_ESCR5 6 | |
175 | #define MSR_IQ_ESCR1 0 | |
176 | #define MSR_RAT_ESCR1 2 | |
177 | #define MSR_AFL_ESCR1 1 | |
178 | } pmc_id_t; | |
179 | ||
180 | typedef int pmc_escr_id_t; | |
181 | #define PMC_ESID_MAX 7 | |
182 | ||
183 | /* | |
184 | * ESCR MSR layout: | |
185 | */ | |
186 | #define PMC_ECSR_NOHTT_RESERVED field(0,1) | |
187 | #define PMC_ECSR_T0_USR bit(0) | |
188 | #define PMC_ECSR_T0_OS bit(1) | |
189 | #define PMC_ECSR_T1_USR bit(2) | |
190 | #define PMC_ECSR_T1_OS bit(3) | |
191 | #define PMC_ECSR_USR bit(2) | |
192 | #define PMC_ECSR_OS bit(3) | |
193 | #define PMC_ECSR_TAG_ENABLE bit(4) | |
194 | #define PMC_ECSR_TAG_VALUE field(5,8) | |
195 | #define PMC_ECSR_EVENT_MASK field(9,24) | |
196 | #define PMC_ECSR_EVENT_SELECT field(25,30) | |
197 | #define PMC_ECSR_RESERVED2 field(30,64) | |
198 | typedef struct { | |
199 | uint64_t reserved1 : 2; | |
200 | uint64_t usr : 1; | |
201 | uint64_t os : 1; | |
202 | uint64_t tag_enable : 1; | |
203 | uint64_t tag_value : 4; | |
204 | uint64_t event_mask : 16; | |
205 | uint64_t event_select : 6; | |
206 | uint64_t reserved2 : 33; | |
207 | } pmc_escr_nohtt_t; | |
208 | typedef struct { | |
209 | uint64_t t0_usr : 1; | |
210 | uint64_t t0_os : 1; | |
211 | uint64_t t1_usr : 1; | |
212 | uint64_t t1_os : 1; | |
213 | uint64_t tag_enable : 1; | |
214 | uint64_t tag_value : 4; | |
215 | uint64_t event_mask : 16; | |
216 | uint64_t event_select : 6; | |
217 | uint64_t reserved2 : 33; | |
218 | } pmc_escr_htt_t; | |
219 | typedef union { | |
220 | pmc_escr_nohtt_t u_nohtt; | |
221 | pmc_escr_htt_t u_htt; | |
222 | uint64_t u_u64; | |
223 | } pmc_escr_t; | |
224 | #define PMC_ESCR_ZERO { .u_u64 = 0ULL } | |
225 | ||
226 | /* | |
227 | * CCCR MSR layout: | |
228 | */ | |
229 | #define PMC_CCCR_RESERVED1 field(1,11) | |
230 | #define PMC_CCCR_ENABLE bit(12) | |
231 | #define PMC_CCCR_ECSR_SELECT field(13,15) | |
232 | #define PMC_CCCR_RESERVED2 field(16,17) | |
233 | #define PMC_CCCR_HTT_ACTIVE field(16,17) | |
234 | #define PMC_CCCR_COMPARE bit(18) | |
235 | #define PMC_CCCR_COMPLEMENT bit(19) | |
236 | #define PMC_CCCR_THRESHOLD field(20,23) | |
237 | #define PMC_CCCR_EDGE bit(24) | |
238 | #define PMC_CCCR_FORCE_OVF bit(25) | |
239 | #define PMC_CCCR_OVF_PMI bit(26) | |
240 | #define PMC_CCCR_NOHTT_RESERVED2 field(27,29) | |
241 | #define PMC_CCCR_OVF_PMI_T0 bit(26) | |
242 | #define PMC_CCCR_OVF_PMI_T1 bit(27) | |
243 | #define PMC_CCCR_HTT_RESERVED2 field(28,29) | |
244 | #define PMC_CCCR_CASCADE bit(30) | |
245 | #define PMC_CCCR_OVF bit(31) | |
246 | typedef struct { | |
247 | uint64_t reserved1 : 12; | |
248 | uint64_t enable : 1; | |
249 | uint64_t escr_select : 3; | |
250 | uint64_t reserved2 : 2; | |
251 | uint64_t compare : 1; | |
252 | uint64_t complement : 1; | |
253 | uint64_t threshold : 4; | |
254 | uint64_t edge : 1; | |
255 | uint64_t force_ovf : 1; | |
256 | uint64_t ovf_pmi : 1; | |
257 | uint64_t reserved3 : 3; | |
258 | uint64_t cascade : 1; | |
259 | uint64_t ovf : 1; | |
260 | uint64_t reserved4 : 32; | |
261 | } pmc_cccr_nohtt_t; | |
262 | typedef struct { | |
263 | uint64_t reserved1 : 12; | |
264 | uint64_t enable : 1; | |
265 | uint64_t escr_select : 3; | |
266 | uint64_t active_thread : 2; | |
267 | uint64_t compare : 1; | |
268 | uint64_t complement : 1; | |
269 | uint64_t threshold : 4; | |
270 | uint64_t edge : 1; | |
271 | uint64_t force_OVF : 1; | |
272 | uint64_t ovf_pmi_t0 : 1; | |
273 | uint64_t ovf_pmi_t1 : 1; | |
274 | uint64_t reserved3 : 2; | |
275 | uint64_t cascade : 1; | |
276 | uint64_t ovf : 1; | |
277 | uint64_t reserved4 : 32; | |
278 | } pmc_cccr_htt_t; | |
279 | typedef union { | |
280 | pmc_cccr_nohtt_t u_nohtt; | |
281 | pmc_cccr_htt_t u_htt; | |
282 | uint64_t u_u64; | |
283 | } pmc_cccr_t; | |
284 | #define PMC_CCCR_ZERO { .u_u64 = 0ULL } | |
285 | ||
286 | typedef void (pmc_ovf_func_t)(pmc_id_t id, void *state); | |
287 | ||
288 | /* | |
289 | * In-kernel PMC access primitives: | |
290 | */ | |
291 | /* Generic: */ | |
8f6c56a5 | 292 | extern int pmc_init(void); |
91447636 A |
293 | extern int pmc_machine_type(pmc_machine_t *type); |
294 | extern boolean_t pmc_is_reserved(pmc_id_t id); | |
295 | extern int pmc_reserve(pmc_id_t id); | |
296 | extern int pmc_free(pmc_id_t id); | |
297 | extern int pmc_counter_read(pmc_id_t id, pmc_counter_t *val); | |
298 | extern int pmc_counter_write(pmc_id_t id, pmc_counter_t *val); | |
299 | ||
300 | /* P6-specific: */ | |
301 | extern int pmc_evtsel_read(pmc_id_t id, pmc_evtsel_t *evtsel); | |
302 | extern int pmc_evtsel_write(pmc_id_t id, pmc_evtsel_t *evtsel); | |
303 | ||
304 | /* P4/Xeon-specific: */ | |
305 | extern int pmc_cccr_read(pmc_id_t id, pmc_cccr_t *cccr); | |
306 | extern int pmc_cccr_write(pmc_id_t id, pmc_cccr_t *cccr); | |
307 | extern int pmc_escr_read(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); | |
308 | extern int pmc_escr_write(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr); | |
309 | extern int pmc_set_ovf_func(pmc_id_t id, pmc_ovf_func_t *func); | |
310 | ||
311 | #endif /* _I386_PERFMON_H_ */ |