Home | History | Annotate | Download | only in sys
      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 2009 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
     38 extern "C" {
     39 #endif
     40 
     41 typedef 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 
     60 #define	KCPC_REQ_ALL_FLAGS	(CPC_OVF_NOTIFY_EMT | CPC_COUNT_USER | \
     61 		CPC_COUNT_SYSTEM | CPC_COUNT_HV)
     62 #define	KCPC_REQ_VALID_FLAGS(flags) \
     63 		(((flags) | KCPC_REQ_ALL_FLAGS) == KCPC_REQ_ALL_FLAGS)
     64 
     65 /*
     66  * CPC Capabilities
     67  */
     68 #define	CPC_CAP_OVERFLOW_INTERRUPT	0x1
     69 #define	CPC_CAP_OVERFLOW_PRECISE	0x2
     70 
     71 /*
     72  * The only valid per-set flag is CPC_BIND_LWP_INHERIT, which must remain in
     73  * cpc_event.h for backwards compatibility.
     74  */
     75 #define	CPC_SET_ALL_FLAGS	0x1
     76 #define	CPC_SET_VALID_FLAGS(flags) \
     77 		(((flags) | CPC_SET_ALL_FLAGS) == CPC_SET_ALL_FLAGS)
     78 
     79 /*
     80  * These system call subcodes and ioctls allow the implementation of the
     81  * libcpc library to store and retrieve performance counter data.  Subject
     82  * to arbitrary change without notice at any time.  Do not invoke them
     83  * directly!
     84  */
     85 #define	CPC_BIND		0
     86 #define	CPC_SAMPLE		1
     87 #define	CPC_INVALIDATE		2
     88 #define	CPC_RELE		3
     89 #define	CPC_EVLIST_SIZE		4
     90 #define	CPC_LIST_EVENTS		5
     91 #define	CPC_ATTRLIST_SIZE	6
     92 #define	CPC_LIST_ATTRS		7
     93 #define	CPC_IMPL_NAME		8
     94 #define	CPC_CPUREF		9
     95 #define	CPC_USR_EVENTS		10
     96 #define	CPC_SYS_EVENTS		11
     97 #define	CPC_NPIC		12
     98 #define	CPC_CAPS		13
     99 #define	CPC_ENABLE		14
    100 #define	CPC_DISABLE		15
    101 #define	CPC_PRESET		16
    102 #define	CPC_RESTART		17
    103 
    104 #define	_CPCIO_IOC	((((('c'<<8)|'p')<<8)|'c')<<8)
    105 
    106 #define	CPCIO_BIND			(_CPCIO_IOC | 0x1)
    107 #define	CPCIO_SAMPLE			(_CPCIO_IOC | 0x2)
    108 #define	CPCIO_RELE			(_CPCIO_IOC | 0x3)
    109 
    110 /*
    111  * Forward declarations.
    112  */
    113 struct _kthread;
    114 struct _kcpc_set;
    115 
    116 #define	CPC_MAX_EVENT_LEN	512
    117 #define	CPC_MAX_ATTR_LEN	32
    118 
    119 typedef struct _kcpc_attr {
    120 	char		ka_name[CPC_MAX_ATTR_LEN];
    121 	uint64_t	ka_val;
    122 } kcpc_attr_t;
    123 
    124 typedef struct _kcpc_pic {
    125 	uint_t			kp_flags;
    126 	struct _kcpc_request	*kp_req;   /* request this PIC counts for */
    127 } kcpc_pic_t;
    128 
    129 typedef struct _kcpc_ctx kcpc_ctx_t;
    130 
    131 struct _kcpc_ctx {
    132 	struct _kcpc_set *kc_set;	/* linked list of all bound sets */
    133 	uint32_t	kc_flags;
    134 	kcpc_pic_t	*kc_pics;	/* pointer to array of per-pic data */
    135 	hrtime_t	kc_hrtime;	/* gethrtime() at last sample */
    136 	uint64_t	kc_vtick;	/* virtualized %tick */
    137 	uint64_t	kc_rawtick;	/* last snapshot of tick/tsc */
    138 	struct _kthread	*kc_thread;	/* thread this context is measuring */
    139 	int		kc_cpuid;	/* CPU this context is measuring */
    140 	kcpc_ctx_t	*kc_next;	/* Global list of all contexts */
    141 	kmutex_t	kc_lock;	/* protects kc_flags */
    142 	kcondvar_t	kc_condv;	/* wait for kcpc_restore completion */
    143 };
    144 
    145 typedef struct __cpc_args {
    146 	void *udata1;
    147 	void *udata2;
    148 	void *udata3;
    149 } __cpc_args_t;
    150 
    151 #ifdef _KERNEL
    152 
    153 #ifdef _MULTI_DATAMODEL
    154 typedef struct __cpc_args32 {
    155 	caddr32_t udata1;
    156 	caddr32_t udata2;
    157 	caddr32_t udata3;
    158 } __cpc_args32_t;
    159 #endif /* _MULTI_DATAMODEL */
    160 
    161 #define	KCPC_LOG2_HASH_BUCKETS	6	/* => 64 buckets for now */
    162 #define	CPC_HASH_BUCKETS		(1l << KCPC_LOG2_HASH_BUCKETS)
    163 #define	CPC_HASH_CTX(ctx)		((((long)(ctx)) >> 7) &		       \
    164 						(CPC_HASH_BUCKETS - 1))
    165 
    166 /*
    167  * Context flags.
    168  */
    169 #define	KCPC_CTX_FREEZE		0x1	/* => no sampling */
    170 #define	KCPC_CTX_SIGOVF		0x2	/* => send signal on overflow */
    171 #define	KCPC_CTX_NONPRIV	0x4	/* => non-priv access to counters */
    172 #define	KCPC_CTX_LWPINHERIT	0x8	/* => lwp_create inherits ctx */
    173 #define	KCPC_CTX_INVALID	0x100	/* => context stolen; discard */
    174 #define	KCPC_CTX_INVALID_STOPPED 0x200	/* => invalid ctx has been stopped */
    175 #define	KCPC_CTX_RESTORE	0x400	/* => kcpc_restore in progress */
    176 
    177 /*
    178  * PIC flags.
    179  */
    180 #define	KCPC_PIC_OVERFLOWED	0x1	/* pic overflowed & requested notify */
    181 
    182 /*
    183  * The following flags are used by the DTrace CPU performance counter provider
    184  * and the overflow handler. The 'DCPC_INTR_*' flags are used to synchronize
    185  * performance counter configuration events performed by the cpc provider and
    186  * interrupt processing carried out by the overflow handler.  The 'DCPC_?MASK'
    187  * flags are used by the dcpc provider to indicate which type of mask attribute
    188  * a platform supports.
    189  */
    190 
    191 /* No configuration events or overflow interrupts are currently in process. */
    192 #define	DCPC_INTR_FREE 0
    193 
    194 /* An overflow interrupt is currently being processed. */
    195 #define	DCPC_INTR_PROCESSING 1
    196 
    197 /* The cpc subsystem is currently being configured by the dcpc provider. */
    198 #define	DCPC_INTR_CONFIG 2
    199 
    200 #define	DCPC_UMASK 1	/* The platform supports a "umask" attribute. */
    201 #define	DCPC_EMASK 2	/* The platform supports an "emask" attribute. */
    202 
    203 #ifdef __sparc
    204 extern uint64_t ultra_gettick(void);
    205 #define	KCPC_GET_TICK ultra_gettick
    206 #else
    207 extern hrtime_t tsc_read(void);
    208 #define	KCPC_GET_TICK tsc_read
    209 #endif /* __sparc */
    210 
    211 #define	PCBE_NAMELEN 30 /* Enough room for "pcbe." plus full PCBE name spec */
    212 
    213 struct cpu;
    214 
    215 extern uint_t cpc_ncounters;
    216 extern kmutex_t	kcpc_ctx_llock[];	/* protects ctx_list */
    217 extern kcpc_ctx_t *kcpc_ctx_list[];	/* head of list */
    218 extern krwlock_t kcpc_cpuctx_lock;	/* lock for 'kcpc_cpuctx' below */
    219 extern int	kcpc_cpuctx;		/* number of cpu-specific contexts */
    220 
    221 extern void kcpc_invalidate_all(void);
    222 
    223 extern void kcpc_passivate(void);
    224 extern void kcpc_remote_stop(struct cpu *cp);
    225 extern int kcpc_pcbe_tryload(const char *, uint_t, uint_t, uint_t);
    226 extern void kcpc_remote_program(struct cpu *cp);
    227 extern void kcpc_register_dcpc(void (*func)(uint64_t));
    228 extern void kcpc_unregister_dcpc(void);
    229 extern kcpc_ctx_t *kcpc_ctx_alloc(void);
    230 extern int kcpc_assign_reqs(struct _kcpc_set *, kcpc_ctx_t *);
    231 extern void kcpc_ctx_free(kcpc_ctx_t *);
    232 extern int kcpc_configure_reqs(kcpc_ctx_t *, struct _kcpc_set *, int *);
    233 extern void kcpc_free_configs(struct _kcpc_set *);
    234 
    235 #endif /* _KERNEL */
    236 
    237 /*
    238  * Error subcodes.
    239  */
    240 #define	CPC_INVALID_EVENT		1	/* Unknown event */
    241 #define	CPC_INVALID_PICNUM		2	/* Requested PIC out of range */
    242 #define	CPC_INVALID_ATTRIBUTE		3	/* Unknown attribute */
    243 #define	CPC_ATTRIBUTE_OUT_OF_RANGE	4	/* Attribute val out of range */
    244 #define	CPC_RESOURCE_UNAVAIL		5	/* Can't get needed resource */
    245 #define	CPC_PIC_NOT_CAPABLE		6	/* PIC can't count this event */
    246 #define	CPC_REQ_INVALID_FLAGS		7	/* Invalid flags in req(s) */
    247 #define	CPC_CONFLICTING_REQS		8	/* Reqs in the set conflict */
    248 #define	CPC_ATTR_REQUIRES_PRIVILEGE	9	/* Insufficient privs for atr */
    249 #define	CPC_PBIND_FAILED		10	/* Couldn't bind to processor */
    250 #define	CPC_HV_NO_ACCESS		11	/* No perm for HV events */
    251 
    252 #ifdef	__cplusplus
    253 }
    254 #endif
    255 
    256 #endif	/* _SYS_CPC_IMPL_H */
    257