1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21/*
22 * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
23 * Use is subject to license terms.
24 */
25
26#ifndef	_SYS_CPC_IMPL_H
27#define	_SYS_CPC_IMPL_H
28
29#include <sys/types.h>
30#include <sys/time.h>
31#include <sys/ksynch.h>
32
33#if defined(_KERNEL) && defined(_MULTI_DATAMODEL)
34#include <sys/types32.h>
35#endif
36
37#ifdef	__cplusplus
38extern "C" {
39#endif
40
41typedef struct {
42	char		*ca_name;
43	uint64_t	ca_val;
44} cpc_attr_t;
45
46/*
47 * Flag arguments to cpc_bind_event and cpc_ctx_bind_event
48 */
49#define	CPC_BIND_LWP_INHERIT	(0x1)
50#define	CPC_BIND_EMT_OVF	(0x2)
51
52#define	CPC_MAX_IMPL_NAME	512	/* Max len of PCBE's description str */
53#define	CPC_MAX_CPUREF		1024	/* Max len of PCBE's CPU ref string */
54
55#define	CPC_OVF_NOTIFY_EMT	0x1
56#define	CPC_COUNT_USER		0x2
57#define	CPC_COUNT_SYSTEM	0x4
58#define	CPC_COUNT_HV		0x8
59#define	CPC_COUNT_SAMPLE_MODE	0x10
60
61#define	KCPC_REQ_ALL_FLAGS	(CPC_OVF_NOTIFY_EMT | CPC_COUNT_USER | \
62		CPC_COUNT_SYSTEM | CPC_COUNT_HV | CPC_COUNT_SAMPLE_MODE)
63#define	KCPC_REQ_VALID_FLAGS(flags) \
64		(((flags) | KCPC_REQ_ALL_FLAGS) == KCPC_REQ_ALL_FLAGS)
65
66/*
67 * CPC Capabilities
68 */
69#define	CPC_CAP_OVERFLOW_INTERRUPT	0x1
70#define	CPC_CAP_OVERFLOW_PRECISE	0x2
71
72/*
73 * The only valid per-set flag is CPC_BIND_LWP_INHERIT, which must remain in
74 * cpc_event.h for backwards compatibility.
75 */
76#define	CPC_SET_ALL_FLAGS	0x1
77#define	CPC_SET_VALID_FLAGS(flags) \
78		(((flags) | CPC_SET_ALL_FLAGS) == CPC_SET_ALL_FLAGS)
79
80/*
81 * These system call subcodes and ioctls allow the implementation of the
82 * libcpc library to store and retrieve performance counter data.  Subject
83 * to arbitrary change without notice at any time.  Do not invoke them
84 * directly!
85 */
86#define	CPC_BIND		0
87#define	CPC_SAMPLE		1
88#define	CPC_INVALIDATE		2
89#define	CPC_RELE		3
90#define	CPC_EVLIST_SIZE		4
91#define	CPC_LIST_EVENTS		5
92#define	CPC_ATTRLIST_SIZE	6
93#define	CPC_LIST_ATTRS		7
94#define	CPC_IMPL_NAME		8
95#define	CPC_CPUREF		9
96#define	CPC_USR_EVENTS		10
97#define	CPC_SYS_EVENTS		11
98#define	CPC_NPIC		12
99#define	CPC_CAPS		13
100#define	CPC_ENABLE		14
101#define	CPC_DISABLE		15
102#define	CPC_PRESET		16
103#define	CPC_RESTART		17
104
105#define	_CPCIO_IOC	((((('c'<<8)|'p')<<8)|'c')<<8)
106
107#define	CPCIO_BIND			(_CPCIO_IOC | 0x1)
108#define	CPCIO_SAMPLE			(_CPCIO_IOC | 0x2)
109#define	CPCIO_RELE			(_CPCIO_IOC | 0x3)
110
111/*
112 * Forward declarations.
113 */
114struct _kthread;
115struct _kcpc_set;
116
117#define	CPC_MAX_EVENT_LEN	512
118#define	CPC_MAX_ATTR_LEN	32
119
120typedef struct _kcpc_attr {
121	char		ka_name[CPC_MAX_ATTR_LEN];
122	uint64_t	ka_val;
123} kcpc_attr_t;
124
125typedef struct _kcpc_pic {
126	uint_t			kp_flags;
127	struct _kcpc_request	*kp_req;   /* request this PIC counts for */
128} kcpc_pic_t;
129
130typedef struct _kcpc_ctx kcpc_ctx_t;
131
132struct _kcpc_ctx {
133	struct _kcpc_set *kc_set;	/* linked list of all bound sets */
134	volatile uint_t	kc_flags;
135	kcpc_pic_t	*kc_pics;	/* pointer to array of per-pic data */
136	hrtime_t	kc_hrtime;	/* gethrtime() at last sample */
137	uint64_t	kc_vtick;	/* virtualized %tick */
138	uint64_t	kc_rawtick;	/* last snapshot of tick/tsc */
139	struct _kthread	*kc_thread;	/* thread this context is measuring */
140	int		kc_cpuid;	/* CPU this context is measuring */
141	kcpc_ctx_t	*kc_next;	/* Global list of all contexts */
142	kmutex_t	kc_lock;	/* protects kc_flags */
143	kcondvar_t	kc_condv;	/* wait for kcpc_restore completion */
144};
145
146typedef struct __cpc_args {
147	void *udata1;
148	void *udata2;
149	void *udata3;
150} __cpc_args_t;
151
152#ifdef _KERNEL
153
154#ifdef _MULTI_DATAMODEL
155typedef struct __cpc_args32 {
156	caddr32_t udata1;
157	caddr32_t udata2;
158	caddr32_t udata3;
159} __cpc_args32_t;
160#endif /* _MULTI_DATAMODEL */
161
162#define	KCPC_LOG2_HASH_BUCKETS	6	/* => 64 buckets for now */
163#define	CPC_HASH_BUCKETS		(1l << KCPC_LOG2_HASH_BUCKETS)
164#define	CPC_HASH_CTX(ctx)		((((long)(ctx)) >> 7) &		       \
165						(CPC_HASH_BUCKETS - 1))
166
167/*
168 * Context flags.
169 */
170#define	KCPC_CTX_FREEZE		0x1	/* => no sampling */
171#define	KCPC_CTX_SIGOVF		0x2	/* => send signal on overflow */
172#define	KCPC_CTX_NONPRIV	0x4	/* => non-priv access to counters */
173#define	KCPC_CTX_LWPINHERIT	0x8	/* => lwp_create inherits ctx */
174#define	KCPC_CTX_INVALID	0x100	/* => context stolen; discard */
175#define	KCPC_CTX_INVALID_STOPPED 0x200	/* => invalid ctx has been stopped */
176#define	KCPC_CTX_RESTORE	0x400	/* => kcpc_restore in progress */
177
178/*
179 * PIC flags.
180 */
181#define	KCPC_PIC_OVERFLOWED	0x1	/* pic overflowed & requested notify */
182
183/*
184 * The following flags are used by the DTrace CPU performance counter provider
185 * and the overflow handler. The 'DCPC_INTR_*' flags are used to synchronize
186 * performance counter configuration events performed by the cpc provider and
187 * interrupt processing carried out by the overflow handler.  The 'DCPC_?MASK'
188 * flags are used by the dcpc provider to indicate which type of mask attribute
189 * a platform supports.
190 */
191
192enum dcpc_intr_state {
193	DCPC_INTR_INACTIVE,	/* The dcpc provider is currently not in use */
194	DCPC_INTR_FREE,		/* No config events or ovf ints in progress */
195	DCPC_INTR_PROCESSING,	/* An overflow interrupt is being processed */
196	DCPC_INTR_CONFIG	/* cpc subsystem being configured by dcpc */
197};
198
199enum dcpc_mask_attr {
200	DCPC_UMASK = 0x1,	/* The platform supports a "umask" attribute */
201	DCPC_EMASK = 0x2	/* The platform supports an "emask" attribute */
202};
203
204#ifdef __sparc
205extern uint64_t ultra_gettick(void);
206#define	KCPC_GET_TICK ultra_gettick
207#else
208extern hrtime_t tsc_read(void);
209#define	KCPC_GET_TICK tsc_read
210#endif /* __sparc */
211
212#define	PCBE_NAMELEN 30 /* Enough room for "pcbe." plus full PCBE name spec */
213
214struct cpu;
215
216extern uint_t cpc_ncounters;
217extern krwlock_t kcpc_cpuctx_lock;	/* lock for 'kcpc_cpuctx' below */
218extern int	kcpc_cpuctx;		/* number of cpu-specific contexts */
219
220extern void kcpc_invalidate_all(void);
221
222extern void kcpc_passivate(void);
223extern void kcpc_cpu_stop(struct cpu *, boolean_t);
224extern int kcpc_pcbe_tryload(const char *, uint_t, uint_t, uint_t);
225extern void kcpc_cpu_program(struct cpu *, kcpc_ctx_t *);
226extern void kcpc_register_dcpc(void (*func)(uint64_t));
227extern void kcpc_unregister_dcpc(void);
228extern kcpc_ctx_t *kcpc_ctx_alloc(int);
229extern int kcpc_assign_reqs(struct _kcpc_set *, kcpc_ctx_t *);
230extern void kcpc_ctx_free(kcpc_ctx_t *);
231extern int kcpc_configure_reqs(kcpc_ctx_t *, struct _kcpc_set *, int *);
232extern void kcpc_free_configs(struct _kcpc_set *);
233
234#endif /* _KERNEL */
235
236/*
237 * Error subcodes.
238 */
239#define	CPC_INVALID_EVENT		1	/* Unknown event */
240#define	CPC_INVALID_PICNUM		2	/* Requested PIC out of range */
241#define	CPC_INVALID_ATTRIBUTE		3	/* Unknown attribute */
242#define	CPC_ATTRIBUTE_OUT_OF_RANGE	4	/* Attribute val out of range */
243#define	CPC_RESOURCE_UNAVAIL		5	/* Can't get needed resource */
244#define	CPC_PIC_NOT_CAPABLE		6	/* PIC can't count this event */
245#define	CPC_REQ_INVALID_FLAGS		7	/* Invalid flags in req(s) */
246#define	CPC_CONFLICTING_REQS		8	/* Reqs in the set conflict */
247#define	CPC_ATTR_REQUIRES_PRIVILEGE	9	/* Insufficient privs for atr */
248#define	CPC_PBIND_FAILED		10	/* Couldn't bind to processor */
249#define	CPC_HV_NO_ACCESS		11	/* No perm for HV events */
250
251#ifdef	__cplusplus
252}
253#endif
254
255#endif	/* _SYS_CPC_IMPL_H */
256