4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <sys/types.h>
31 #include <sys/syscall.h>
42 #include <sys/cpc_impl.h>
45 #include "libcpc_impl.h"
48 * CPC library handle for use by CPCv1 implementation.
51 mutex_t __cpc_lock
; /* protects __cpc handle */
52 int __cpc_v1_cpuver
; /* CPU version in use by CPCv1 client */
55 uint64_t __cpc_v1_pcr
; /* last bound %pcr value */
57 uint32_t __cpc_v1_pes
[2]; /* last bound %pes values */
63 const char *fn
= "__cpc_init";
64 extern cpc_t
*__cpc
; /* CPC handle for obsolete clients to share */
66 (void) mutex_lock(&__cpc_lock
);
67 if (__cpc
== NULL
&& (__cpc
= cpc_open(CPC_VER_CURRENT
)) == NULL
) {
68 __cpc_error(fn
, dgettext(TEXT_DOMAIN
,
69 "Couldn't open CPC library handle\n"));
70 (void) mutex_unlock(&__cpc_lock
);
73 (void) mutex_unlock(&__cpc_lock
);
79 cpc_bind_event(cpc_event_t
*this, int flags
)
90 if (__cpc_init() != 0) {
96 * The cpuver and control fields of the cpc_event_t must be saved off
97 * for later. The user may call cpc_take_sample(), expecting these to
98 * be copied into a different cpc_event_t struct by the kernel. We have
99 * to fake that behavior for CPCv1 clients.
101 __cpc_v1_cpuver
= this->ce_cpuver
;
103 __cpc_v1_pcr
= this->ce_pcr
;
105 __cpc_v1_pes
[0] = this->ce_pes
[0];
106 __cpc_v1_pes
[1] = this->ce_pes
[1];
109 if ((set
= __cpc_eventtoset(__cpc
, this, flags
)) == NULL
) {
115 * Convert flags to CPC2.
117 if (flags
& CPC_BIND_EMT_OVF
) {
118 for (rp
= set
->cs_request
; rp
!= NULL
; rp
= rp
->cr_next
)
119 rp
->cr_flags
|= CPC_OVF_NOTIFY_EMT
;
120 flags
&= ~CPC_BIND_EMT_OVF
;
123 ret
= cpc_bind_curlwp(__cpc
, set
, flags
);
125 (void) cpc_set_destroy(__cpc
, set
);
131 cpc_take_sample(cpc_event_t
*this)
133 this->ce_cpuver
= __cpc_v1_cpuver
;
135 this->ce_pcr
= __cpc_v1_pcr
;
137 this->ce_pes
[0] = __cpc_v1_pes
[0];
138 this->ce_pes
[1] = __cpc_v1_pes
[1];
141 return (syscall(SYS_cpc
, CPC_SAMPLE
, -1, this->ce_pic
, &this->ce_hrt
,
142 &CPC_TICKREG(this), 0));
146 cpc_count_usr_events(int enable
)
148 return (syscall(SYS_cpc
, CPC_USR_EVENTS
, -1, enable
, 0));
152 cpc_count_sys_events(int enable
)
154 return (syscall(SYS_cpc
, CPC_SYS_EVENTS
, -1, enable
, 0));
160 return (syscall(SYS_cpc
, CPC_RELE
, -1, NULL
, 0));
164 * See if the system call is working and installed.
166 * We invoke the system call with nonsense arguments - if it's
167 * there and working correctly, it will return EINVAL.
169 * (This avoids the user getting a SIGSYS core dump when they attempt
170 * to bind on older hardware)
175 void (*handler
)(int);
177 const char fn
[] = "access";
179 handler
= signal(SIGSYS
, SIG_IGN
);
180 if (syscall(SYS_cpc
, -1, -1, NULL
, 0) == -1 &&
183 (void) signal(SIGSYS
, handler
);
187 __cpc_error(fn
, dgettext(TEXT_DOMAIN
, "Another process may be "
188 "sampling system-wide CPU statistics\n"));
192 dgettext(TEXT_DOMAIN
, "CPU performance counters "
193 "are inaccessible on this machine\n"));
196 __cpc_error(fn
, "%s\n", strerror(errno
));
207 * To look at the system-wide counters, we have to open the
208 * 'shared' device. Once that device is open, no further contexts
209 * can be installed (though one open is needed per CPU)
212 cpc_shared_open(void)
214 const char driver
[] = CPUDRV_SHARED
;
216 return (open(driver
, O_RDWR
));
220 cpc_shared_close(int fd
)
222 (void) cpc_shared_rele(fd
);
227 cpc_shared_bind_event(int fd
, cpc_event_t
*this, int flags
)
235 __cpc_args_t cpc_args
;
238 (void) cpc_shared_rele(fd
);
240 } else if (flags
!= 0) {
245 if (__cpc_init() != 0) {
250 if ((set
= __cpc_eventtoset(__cpc
, this, flags
)) == NULL
) {
255 __cpc_v1_cpuver
= this->ce_cpuver
;
257 if ((packed_set
= __cpc_pack_set(set
, flags
, &packsize
)) == NULL
) {
262 cpc_args
.udata1
= packed_set
;
263 cpc_args
.udata2
= (void *)packsize
;
264 cpc_args
.udata3
= (void *)&subcode
;
266 ret
= ioctl(fd
, CPCIO_BIND
, &cpc_args
);
269 (void) cpc_set_destroy(__cpc
, set
);
275 cpc_shared_take_sample(int fd
, cpc_event_t
*this)
279 args
.udata1
= this->ce_pic
;
280 args
.udata2
= &this->ce_hrt
;
281 args
.udata3
= &CPC_TICKREG(this);
283 this->ce_cpuver
= __cpc_v1_cpuver
;
285 return (ioctl(fd
, CPCIO_SAMPLE
, &args
));
289 cpc_shared_rele(int fd
)
291 return (ioctl(fd
, CPCIO_RELE
, 0));
295 cpc_pctx_bind_event(pctx_t
*pctx
, id_t lwpid
, cpc_event_t
*event
, int flags
)
301 return (cpc_pctx_rele(pctx
, lwpid
));
303 if (__cpc_init() != 0) {
308 else if (flags
!= 0) {
313 if ((set
= __cpc_eventtoset(__cpc
, event
, flags
)) == NULL
) {
319 * The cpuver and control fields of the cpc_event_t must be saved off
320 * for later. The user may call cpc_take_sample(), expecting these to
321 * be copied into a different cpc_event_t struct by the kernel. We have
322 * to fake that behavior for CPCv1 clients.
324 __cpc_v1_cpuver
= event
->ce_cpuver
;
326 ret
= cpc_bind_pctx(__cpc
, pctx
, lwpid
, set
, 0);
328 (void) cpc_set_destroy(__cpc
, set
);
334 cpc_pctx_take_sample(pctx_t
*pctx
, id_t lwpid
, cpc_event_t
*event
)
336 event
->ce_cpuver
= __cpc_v1_cpuver
;
338 return (__pctx_cpc(pctx
, __cpc
, CPC_SAMPLE
, lwpid
, event
->ce_pic
,
339 &event
->ce_hrt
, &CPC_TICKREG(event
), CPC1_BUFSIZE
));
343 * Given a process context and an lwpid, mark the CPU performance
344 * counter context as invalid.
347 cpc_pctx_invalidate(pctx_t
*pctx
, id_t lwpid
)
349 return (__pctx_cpc(pctx
, __cpc
, CPC_INVALIDATE
, lwpid
, 0, 0, 0, 0));
353 * Given a process context and an lwpid, remove all our
354 * hardware context from it.
357 cpc_pctx_rele(pctx_t
*pctx
, id_t lwpid
)
359 return (__pctx_cpc(pctx
, __cpc
, CPC_RELE
, lwpid
, 0, 0, 0, 0));
362 static cpc_errfn_t
*__cpc_uerrfn
;
366 __cpc_error(const char *fn
, const char *fmt
, ...)
372 __cpc_uerrfn(fn
, fmt
, ap
);
374 (void) fprintf(stderr
, "libcpc: %s: ", fn
);
375 (void) vfprintf(stderr
, fmt
, ap
);
381 cpc_seterrfn(cpc_errfn_t
*errfn
)
383 __cpc_uerrfn
= errfn
;
387 * cpc_version() is only for CPC1 clients.
389 uint_t __cpc_workver
= CPC_VER_1
;
392 cpc_version(uint_t ver
)
394 __cpc_workver
= CPC_VER_1
;
398 case CPC_VER_CURRENT
:
399 return (CPC_VER_CURRENT
);
402 * As long as the client is using cpc_version() at all, it is
403 * a CPCv1 client. We still allow CPCv1 clients to compile on
409 return (CPC_VER_NONE
);