]> git.saurik.com Git - apple/xnu.git/blob - osfmk/i386/perfmon.h
xnu-792.25.20.tar.gz
[apple/xnu.git] / osfmk / i386 / perfmon.h
1 /*
2 * Copyright (c) 2003 Apple Computer, Inc. All rights reserved.
3 *
4 * @APPLE_LICENSE_HEADER_START@
5 *
6 * The contents of this file constitute Original Code as defined in and
7 * are subject to the Apple Public Source License Version 1.1 (the
8 * "License"). You may not use this file except in compliance with the
9 * License. Please obtain a copy of the License at
10 * http://www.apple.com/publicsource and read it before using this file.
11 *
12 * This Original Code and all software distributed under the License are
13 * distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, EITHER
14 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
15 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE OR NON-INFRINGEMENT. Please see the
17 * License for the specific language governing rights and limitations
18 * under the License.
19 *
20 * @APPLE_LICENSE_HEADER_END@
21 */
22 #ifndef _I386_PERFMON_H_
23 #define _I386_PERFMON_H_
24
25 #include <i386/proc_reg.h>
26
27 /*
28 * Handy macros for bit/bitfield definition and manipulations:
29 */
30 #define bit(n) (1ULL << (n))
31 #define field(n,m) ((bit((m)+1)-1) & ~(bit(n)-1))
32 #define field_nbit(fld) (ffs(fld)-1)
33 #define field_select(fld,x) ((x) & (fld))
34 #define field_clear(fld,x) ((x) & ~(fld))
35 #define field_unshift(fld,x) ((x) >> field_nbit(fld))
36 #define field_shift(fld,x) ((x) << field_nbit(fld))
37 #define field_get(fld,x) (field_unshift(fld,field_select(fld,x)))
38 #define field_set(fld,x,val) (field_clear(fld,x) | field_shift(fld,val))
39
40 #define PERFMON_AVAILABLE bit(7)
41 #define BTS_UNAVAILABLE bit(11)
42
43 static inline boolean_t
44 pmc_is_available(void)
45 {
46 uint32_t lo;
47 uint32_t hi;
48 int ret;
49
50 ret = rdmsr_carefully(MSR_IA32_MISC_ENABLE, &lo, &hi);
51
52 return (ret == 0) && ((lo & PERFMON_AVAILABLE) != 0);
53 }
54
55 /*
56 * Counter layout:
57 */
58 #define PMC_COUNTER_COUNTER field(0,39)
59 #define PMC_COUNTER_RESERVED field(40,64)
60 #define PMC_COUNTER_MAX ((uint64_t) PMC_COUNTER_COUNTER)
61 typedef struct {
62 uint64_t counter : 40;
63 uint64_t reserved : 24;
64 } pmc_counter_t;
65 #define PMC_COUNTER_ZERO { 0, 0 }
66
67
68 /*
69 * There are 2 basic flavors of PMCsL: P6 and P4/Xeon:
70 */
71 typedef enum {
72 pmc_none,
73 pmc_P6,
74 pmc_P4_Xeon,
75 pmc_unknown
76 } pmc_machine_t;
77
78 /*
79 * P6 MSRs...
80 */
81 #define MSR_P6_COUNTER_ADDR(n) (0x0c1 + (n))
82 #define MSR_P6_PES_ADDR(n) (0x186 + (n))
83
84 typedef struct {
85 uint64_t event_select : 8;
86 uint64_t umask : 8;
87 uint64_t usr : 1;
88 uint64_t os : 1;
89 uint64_t e : 1;
90 uint64_t pc : 1;
91 uint64_t apic_int : 1;
92 uint64_t reserved1 : 1;
93 uint64_t en : 1;
94 uint64_t inv : 1;
95 uint64_t cmask : 8;
96 } pmc_evtsel_t;
97 #define PMC_EVTSEL_ZERO ((pmc_evtsel_t){ 0,0,0,0,0,0,0,0,0,0,0 })
98
99 #define MSR_P6_PERFCTR0 0
100 #define MSR_P6_PERFCTR1 1
101
102 /*
103 * P4/Xeon MSRs...
104 */
105 #define MSR_COUNTER_ADDR(n) (0x300 + (n))
106 #define MSR_CCCR_ADDR(n) (0x360 + (n))
107
108 typedef enum {
109 MSR_BPU_COUNTER0 = 0,
110 MSR_BPU_COUNTER1 = 1,
111 #define MSR_BSU_ESCR0 7
112 #define MSR_FSB_ESCR0 6
113 #define MSR_MOB_ESCR0 2
114 #define MSR_PMH_ESCR0 4
115 #define MSR_BPU_ESCR0 0
116 #define MSR_IS_ESCR0 1
117 #define MSR_ITLB_ESCR0 3
118 #define MSR_IX_ESCR0 5
119 MSR_BPU_COUNTER2 = 2,
120 MSR_BPU_COUNTER3 = 3,
121 #define MSR_BSU_ESCR1 7
122 #define MSR_FSB_ESCR1 6
123 #define MSR_MOB_ESCR1 2
124 #define MSR_PMH_ESCR1 4
125 #define MSR_BPU_ESCR1 0
126 #define MSR_IS_ESCR1 1
127 #define MSR_ITLB_ESCR1 3
128 #define MSR_IX_ESCR1 5
129 MSR_MS_COUNTER0 = 4,
130 MSR_MS_COUNTER1 = 5,
131 #define MSR_MS_ESCR0 0
132 #define MSR_TBPU_ESCR0 2
133 #define MSR_TC_ESCR0 1
134 MSR_MS_COUNTER2 = 6,
135 MSR_MS_COUNTER3 = 7,
136 #define MSR_MS_ESCR1 0
137 #define MSR_TBPU_ESCR1 2
138 #define MSR_TC_ESCR1 1
139 MSR_FLAME_COUNTER0 = 8,
140 MSR_FLAME_COUNTER1 = 9,
141 #define MSR_FIRM_ESCR0 1
142 #define MSR_FLAME_ESCR0 0
143 #define MSR_DAC_ESCR0 5
144 #define MSR_SAT_ESCR0 2
145 #define MSR_U2L_ESCR0 3
146 MSR_FLAME_COUNTER2 = 10,
147 MSR_FLAME_COUNTER3 = 11,
148 #define MSR_FIRM_ESCR1 1
149 #define MSR_FLAME_ESCR1 0
150 #define MSR_DAC_ESCR1 5
151 #define MSR_SAT_ESCR1 2
152 #define MSR_U2L_ESCR1 3
153 MSR_IQ_COUNTER0 = 12,
154 MSR_IQ_COUNTER1 = 13,
155 MSR_IQ_COUNTER4 = 16,
156 #define MSR_CRU_ESCR0 4
157 #define MSR_CRU_ESCR2 5
158 #define MSR_CRU_ESCR4 6
159 #define MSR_IQ_ESCR0 0
160 #define MSR_RAT_ESCR0 2
161 #define MSR_SSU_ESCR0 3
162 #define MSR_AFL_ESCR0 1
163 MSR_IQ_COUNTER2 = 14,
164 MSR_IQ_COUNTER3 = 15,
165 MSR_IQ_COUNTER5 = 17,
166 #define MSR_CRU_ESCR1 4
167 #define MSR_CRU_ESCR3 5
168 #define MSR_CRU_ESCR5 6
169 #define MSR_IQ_ESCR1 0
170 #define MSR_RAT_ESCR1 2
171 #define MSR_AFL_ESCR1 1
172 } pmc_id_t;
173
174 typedef int pmc_escr_id_t;
175 #define PMC_ESID_MAX 7
176
177 /*
178 * ESCR MSR layout:
179 */
180 #define PMC_ECSR_NOHTT_RESERVED field(0,1)
181 #define PMC_ECSR_T0_USR bit(0)
182 #define PMC_ECSR_T0_OS bit(1)
183 #define PMC_ECSR_T1_USR bit(2)
184 #define PMC_ECSR_T1_OS bit(3)
185 #define PMC_ECSR_USR bit(2)
186 #define PMC_ECSR_OS bit(3)
187 #define PMC_ECSR_TAG_ENABLE bit(4)
188 #define PMC_ECSR_TAG_VALUE field(5,8)
189 #define PMC_ECSR_EVENT_MASK field(9,24)
190 #define PMC_ECSR_EVENT_SELECT field(25,30)
191 #define PMC_ECSR_RESERVED2 field(30,64)
192 typedef struct {
193 uint64_t reserved1 : 2;
194 uint64_t usr : 1;
195 uint64_t os : 1;
196 uint64_t tag_enable : 1;
197 uint64_t tag_value : 4;
198 uint64_t event_mask : 16;
199 uint64_t event_select : 6;
200 uint64_t reserved2 : 33;
201 } pmc_escr_nohtt_t;
202 typedef struct {
203 uint64_t t0_usr : 1;
204 uint64_t t0_os : 1;
205 uint64_t t1_usr : 1;
206 uint64_t t1_os : 1;
207 uint64_t tag_enable : 1;
208 uint64_t tag_value : 4;
209 uint64_t event_mask : 16;
210 uint64_t event_select : 6;
211 uint64_t reserved2 : 33;
212 } pmc_escr_htt_t;
213 typedef union {
214 pmc_escr_nohtt_t u_nohtt;
215 pmc_escr_htt_t u_htt;
216 uint64_t u_u64;
217 } pmc_escr_t;
218 #define PMC_ESCR_ZERO { .u_u64 = 0ULL }
219
220 /*
221 * CCCR MSR layout:
222 */
223 #define PMC_CCCR_RESERVED1 field(1,11)
224 #define PMC_CCCR_ENABLE bit(12)
225 #define PMC_CCCR_ECSR_SELECT field(13,15)
226 #define PMC_CCCR_RESERVED2 field(16,17)
227 #define PMC_CCCR_HTT_ACTIVE field(16,17)
228 #define PMC_CCCR_COMPARE bit(18)
229 #define PMC_CCCR_COMPLEMENT bit(19)
230 #define PMC_CCCR_THRESHOLD field(20,23)
231 #define PMC_CCCR_EDGE bit(24)
232 #define PMC_CCCR_FORCE_OVF bit(25)
233 #define PMC_CCCR_OVF_PMI bit(26)
234 #define PMC_CCCR_NOHTT_RESERVED2 field(27,29)
235 #define PMC_CCCR_OVF_PMI_T0 bit(26)
236 #define PMC_CCCR_OVF_PMI_T1 bit(27)
237 #define PMC_CCCR_HTT_RESERVED2 field(28,29)
238 #define PMC_CCCR_CASCADE bit(30)
239 #define PMC_CCCR_OVF bit(31)
240 typedef struct {
241 uint64_t reserved1 : 12;
242 uint64_t enable : 1;
243 uint64_t escr_select : 3;
244 uint64_t reserved2 : 2;
245 uint64_t compare : 1;
246 uint64_t complement : 1;
247 uint64_t threshold : 4;
248 uint64_t edge : 1;
249 uint64_t force_ovf : 1;
250 uint64_t ovf_pmi : 1;
251 uint64_t reserved3 : 3;
252 uint64_t cascade : 1;
253 uint64_t ovf : 1;
254 uint64_t reserved4 : 32;
255 } pmc_cccr_nohtt_t;
256 typedef struct {
257 uint64_t reserved1 : 12;
258 uint64_t enable : 1;
259 uint64_t escr_select : 3;
260 uint64_t active_thread : 2;
261 uint64_t compare : 1;
262 uint64_t complement : 1;
263 uint64_t threshold : 4;
264 uint64_t edge : 1;
265 uint64_t force_OVF : 1;
266 uint64_t ovf_pmi_t0 : 1;
267 uint64_t ovf_pmi_t1 : 1;
268 uint64_t reserved3 : 2;
269 uint64_t cascade : 1;
270 uint64_t ovf : 1;
271 uint64_t reserved4 : 32;
272 } pmc_cccr_htt_t;
273 typedef union {
274 pmc_cccr_nohtt_t u_nohtt;
275 pmc_cccr_htt_t u_htt;
276 uint64_t u_u64;
277 } pmc_cccr_t;
278 #define PMC_CCCR_ZERO { .u_u64 = 0ULL }
279
280 typedef void (pmc_ovf_func_t)(pmc_id_t id, void *state);
281
282 /*
283 * In-kernel PMC access primitives:
284 */
285 /* Generic: */
286 extern void *pmc_alloc(void);
287 extern int pmc_machine_type(pmc_machine_t *type);
288 extern boolean_t pmc_is_reserved(pmc_id_t id);
289 extern int pmc_reserve(pmc_id_t id);
290 extern int pmc_free(pmc_id_t id);
291 extern int pmc_counter_read(pmc_id_t id, pmc_counter_t *val);
292 extern int pmc_counter_write(pmc_id_t id, pmc_counter_t *val);
293
294 /* P6-specific: */
295 extern int pmc_evtsel_read(pmc_id_t id, pmc_evtsel_t *evtsel);
296 extern int pmc_evtsel_write(pmc_id_t id, pmc_evtsel_t *evtsel);
297
298 /* P4/Xeon-specific: */
299 extern int pmc_cccr_read(pmc_id_t id, pmc_cccr_t *cccr);
300 extern int pmc_cccr_write(pmc_id_t id, pmc_cccr_t *cccr);
301 extern int pmc_escr_read(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr);
302 extern int pmc_escr_write(pmc_id_t id, pmc_escr_id_t esid, pmc_escr_t *escr);
303 extern int pmc_set_ovf_func(pmc_id_t id, pmc_ovf_func_t *func);
304
305 extern int pmc_acquire(task_t);
306 extern int pmc_release(task_t);
307
308 #endif /* _I386_PERFMON_H_ */