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