6811333 Remove prom_printf() message in emlxs driver
[opensolaris.git] / usr / src / uts / common / dtrace / dcpc.c
blob05f304fdd7da6124861aab311bd7dc06910ada6a
1 /*
2 * CDDL HEADER START
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.
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.
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]
19 * CDDL HEADER END
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/errno.h>
28 #include <sys/cpuvar.h>
29 #include <sys/stat.h>
30 #include <sys/modctl.h>
31 #include <sys/cmn_err.h>
32 #include <sys/ddi.h>
33 #include <sys/sunddi.h>
34 #include <sys/ksynch.h>
35 #include <sys/conf.h>
36 #include <sys/kmem.h>
37 #include <sys/kcpc.h>
38 #include <sys/cpc_pcbe.h>
39 #include <sys/cpc_impl.h>
40 #include <sys/dtrace_impl.h>
43 * DTrace CPU Performance Counter Provider
44 * ---------------------------------------
46 * The DTrace cpc provider allows DTrace consumers to access the CPU
47 * performance counter overflow mechanism of a CPU. The configuration
48 * presented in a probe specification is programmed into the performance
49 * counter hardware of all available CPUs on a system. Programming the
50 * hardware causes a counter on each CPU to begin counting events of the
51 * given type. When the specified number of events have occurred, an overflow
52 * interrupt will be generated and the probe is fired.
54 * The required configuration for the performance counter is encoded into
55 * the probe specification and this includes the performance counter event
56 * name, processor mode, overflow rate and an optional unit mask.
58 * Most processors provide several counters (PICs) which can count all or a
59 * subset of the events available for a given CPU. However, when overflow
60 * profiling is being used, not all CPUs can detect which counter generated the
61 * overflow interrupt. In this case we cannot reliably determine which counter
62 * overflowed and we therefore only allow such CPUs to configure one event at
63 * a time. Processors that can determine the counter which overflowed are
64 * allowed to program as many events at one time as possible (in theory up to
65 * the number of instrumentation counters supported by that platform).
66 * Therefore, multiple consumers can enable multiple probes at the same time
67 * on such platforms. Platforms which cannot determine the source of an
68 * overflow interrupt are only allowed to program a single event at one time.
70 * The performance counter hardware is made available to consumers on a
71 * first-come, first-served basis. Only a finite amount of hardware resource
72 * is available and, while we make every attempt to accomodate requests from
73 * consumers, we must deny requests when hardware resources have been exhausted.
74 * A consumer will fail to enable probes when resources are currently in use.
76 * The cpc provider contends for shared hardware resources along with other
77 * consumers of the kernel CPU performance counter subsystem (e.g. cpustat(1M)).
78 * Only one such consumer can use the performance counters at any one time and
79 * counters are made available on a first-come, first-served basis. As with
80 * cpustat, the cpc provider has priority over per-LWP libcpc usage (e.g.
81 * cputrack(1)). Invoking the cpc provider will cause all existing per-LWP
82 * counter contexts to be invalidated.
85 typedef struct dcpc_probe {
86 char dcpc_event_name[CPC_MAX_EVENT_LEN];
87 int dcpc_flag; /* flags (USER/SYS) */
88 uint32_t dcpc_ovfval; /* overflow value */
89 int64_t dcpc_umask; /* umask/emask for this event */
90 int dcpc_picno; /* pic this event is programmed in */
91 int dcpc_enabled; /* probe is actually enabled? */
92 int dcpc_disabling; /* probe is currently being disabled */
93 dtrace_id_t dcpc_id; /* probeid this request is enabling */
94 int dcpc_actv_req_idx; /* idx into dcpc_actv_reqs[] */
95 } dcpc_probe_t;
97 static dev_info_t *dcpc_devi;
98 static dtrace_provider_id_t dcpc_pid;
99 static dcpc_probe_t **dcpc_actv_reqs;
100 static uint32_t dcpc_enablings = 0;
101 static int dcpc_ovf_mask = 0;
102 static int dcpc_mult_ovf_cap = 0;
103 static int dcpc_mask_type = 0;
106 * When the dcpc provider is loaded, dcpc_min_overflow is set to either
107 * DCPC_MIN_OVF_DEFAULT or the value that dcpc-min-overflow is set to in
108 * the dcpc.conf file. Decrease this value to set probes with smaller
109 * overflow values. Remember that very small values could render a system
110 * unusable with frequently occurring events.
112 #define DCPC_MIN_OVF_DEFAULT 5000
113 static uint32_t dcpc_min_overflow;
115 static int dcpc_aframes = 0; /* override for artificial frame setting */
116 #if defined(__x86)
117 #define DCPC_ARTIFICIAL_FRAMES 8
118 #elif defined(__sparc)
119 #define DCPC_ARTIFICIAL_FRAMES 2
120 #endif
123 * Called from the platform overflow interrupt handler. 'bitmap' is a mask
124 * which contains the pic(s) that have overflowed.
126 static void
127 dcpc_fire(uint64_t bitmap)
129 int i;
132 * No counter was marked as overflowing. Shout about it and get out.
134 if ((bitmap & dcpc_ovf_mask) == 0) {
135 cmn_err(CE_NOTE, "dcpc_fire: no counter overflow found\n");
136 return;
140 * This is the common case of a processor that doesn't support
141 * multiple overflow events. Such systems are only allowed a single
142 * enabling and therefore we just look for the first entry in
143 * the active request array.
145 if (!dcpc_mult_ovf_cap) {
146 for (i = 0; i < cpc_ncounters; i++) {
147 if (dcpc_actv_reqs[i] != NULL) {
148 dtrace_probe(dcpc_actv_reqs[i]->dcpc_id,
149 CPU->cpu_cpcprofile_pc,
150 CPU->cpu_cpcprofile_upc, 0, 0, 0);
151 return;
154 return;
158 * This is a processor capable of handling multiple overflow events.
159 * Iterate over the array of active requests and locate the counters
160 * that overflowed (note: it is possible for more than one counter to
161 * have overflowed at the same time).
163 for (i = 0; i < cpc_ncounters; i++) {
164 if (dcpc_actv_reqs[i] != NULL &&
165 (bitmap & (1ULL << dcpc_actv_reqs[i]->dcpc_picno))) {
166 dtrace_probe(dcpc_actv_reqs[i]->dcpc_id,
167 CPU->cpu_cpcprofile_pc,
168 CPU->cpu_cpcprofile_upc, 0, 0, 0);
173 static void
174 dcpc_create_probe(dtrace_provider_id_t id, const char *probename,
175 char *eventname, int64_t umask, uint32_t ovfval, char flag)
177 dcpc_probe_t *pp;
178 int nr_frames = DCPC_ARTIFICIAL_FRAMES + dtrace_mach_aframes();
180 if (dcpc_aframes)
181 nr_frames = dcpc_aframes;
183 if (dtrace_probe_lookup(id, NULL, NULL, probename) != 0)
184 return;
186 pp = kmem_zalloc(sizeof (dcpc_probe_t), KM_SLEEP);
187 (void) strncpy(pp->dcpc_event_name, eventname,
188 sizeof (pp->dcpc_event_name) - 1);
189 pp->dcpc_event_name[sizeof (pp->dcpc_event_name) - 1] = '\0';
190 pp->dcpc_flag = flag | CPC_OVF_NOTIFY_EMT;
191 pp->dcpc_ovfval = ovfval;
192 pp->dcpc_umask = umask;
193 pp->dcpc_actv_req_idx = pp->dcpc_picno = pp->dcpc_disabling = -1;
195 pp->dcpc_id = dtrace_probe_create(id, NULL, NULL, probename,
196 nr_frames, pp);
199 /*ARGSUSED*/
200 static void
201 dcpc_provide(void *arg, const dtrace_probedesc_t *desc)
204 * The format of a probe is:
206 * event_name-mode-{optional_umask}-overflow_rate
207 * e.g.
208 * DC_refill_from_system-user-0x1e-50000, or,
209 * DC_refill_from_system-all-10000
212 char *str, *end, *p;
213 int i, flag = 0;
214 char event[CPC_MAX_EVENT_LEN];
215 long umask = -1, val = 0;
216 size_t evlen, len;
219 * The 'cpc' provider offers no probes by default.
221 if (desc == NULL)
222 return;
224 len = strlen(desc->dtpd_name);
225 p = str = kmem_alloc(len + 1, KM_SLEEP);
226 (void) strcpy(str, desc->dtpd_name);
229 * We have a poor man's strtok() going on here. Replace any hyphens
230 * in the the probe name with NULL characters in order to make it
231 * easy to parse the string with regular string functions.
233 for (i = 0; i < len; i++) {
234 if (str[i] == '-')
235 str[i] = '\0';
239 * The first part of the string must be either a platform event
240 * name or a generic event name.
242 evlen = strlen(p);
243 (void) strncpy(event, p, CPC_MAX_EVENT_LEN - 1);
244 event[CPC_MAX_EVENT_LEN - 1] = '\0';
247 * The next part of the name is the mode specification. Valid
248 * settings are "user", "kernel" or "all".
250 p += evlen + 1;
252 if (strcmp(p, "user") == 0)
253 flag |= CPC_COUNT_USER;
254 else if (strcmp(p, "kernel") == 0)
255 flag |= CPC_COUNT_SYSTEM;
256 else if (strcmp(p, "all") == 0)
257 flag |= CPC_COUNT_USER | CPC_COUNT_SYSTEM;
258 else
259 goto err;
262 * Next we either have a mask specification followed by an overflow
263 * rate or just an overflow rate on its own.
265 p += strlen(p) + 1;
266 if (p[0] == '0' && (p[1] == 'x' || p[1] == 'X')) {
268 * A unit mask can only be specified if:
269 * 1) this performance counter back end supports masks.
270 * 2) the specified event is platform specific.
271 * 3) a valid hex number is converted.
272 * 4) no extraneous characters follow the mask specification.
274 if (dcpc_mask_type != 0 && strncmp(event, "PAPI", 4) != 0 &&
275 ddi_strtol(p, &end, 16, &umask) == 0 &&
276 end == p + strlen(p)) {
277 p += strlen(p) + 1;
278 } else {
279 goto err;
284 * This final part must be an overflow value which has to be greater
285 * than the minimum permissible overflow rate.
287 if ((ddi_strtol(p, &end, 10, &val) != 0) || end != p + strlen(p) ||
288 val < dcpc_min_overflow)
289 goto err;
292 * Validate the event and create the probe.
294 for (i = 0; i < cpc_ncounters; i++) {
295 if (strstr(kcpc_list_events(i), event) != NULL)
296 dcpc_create_probe(dcpc_pid, desc->dtpd_name, event,
297 umask, (uint32_t)val, flag);
300 err:
301 kmem_free(str, len + 1);
304 /*ARGSUSED*/
305 static void
306 dcpc_destroy(void *arg, dtrace_id_t id, void *parg)
308 dcpc_probe_t *pp = parg;
310 ASSERT(pp->dcpc_enabled == 0);
311 kmem_free(pp, sizeof (dcpc_probe_t));
314 /*ARGSUSED*/
315 static int
316 dcpc_usermode(void *arg, dtrace_id_t id, void *parg)
318 return (CPU->cpu_cpcprofile_pc == 0);
321 static void
322 dcpc_populate_set(cpu_t *c, dcpc_probe_t *pp, kcpc_set_t *set, int reqno)
324 kcpc_set_t *oset;
325 int i;
327 (void) strncpy(set->ks_req[reqno].kr_event, pp->dcpc_event_name,
328 CPC_MAX_EVENT_LEN);
329 set->ks_req[reqno].kr_config = NULL;
330 set->ks_req[reqno].kr_index = reqno;
331 set->ks_req[reqno].kr_picnum = -1;
332 set->ks_req[reqno].kr_flags = pp->dcpc_flag;
335 * If a unit mask has been specified then detect which attribute
336 * the platform needs. For now, it's either "umask" or "emask".
338 if (pp->dcpc_umask >= 0) {
339 set->ks_req[reqno].kr_attr =
340 kmem_zalloc(sizeof (kcpc_attr_t), KM_SLEEP);
341 set->ks_req[reqno].kr_nattrs = 1;
342 if (dcpc_mask_type & DCPC_UMASK)
343 (void) strncpy(set->ks_req[reqno].kr_attr->ka_name,
344 "umask", 5);
345 else
346 (void) strncpy(set->ks_req[reqno].kr_attr->ka_name,
347 "emask", 5);
348 set->ks_req[reqno].kr_attr->ka_val = pp->dcpc_umask;
349 } else {
350 set->ks_req[reqno].kr_attr = NULL;
351 set->ks_req[reqno].kr_nattrs = 0;
355 * If this probe is enabled, obtain its current countdown value
356 * and use that. The CPUs cpc context might not exist yet if we
357 * are dealing with a CPU that is just coming online.
359 if (pp->dcpc_enabled && (c->cpu_cpc_ctx != NULL)) {
360 oset = c->cpu_cpc_ctx->kc_set;
362 for (i = 0; i < oset->ks_nreqs; i++) {
363 if (strcmp(oset->ks_req[i].kr_event,
364 set->ks_req[reqno].kr_event) == 0) {
365 set->ks_req[reqno].kr_preset =
366 *(oset->ks_req[i].kr_data);
369 } else {
370 set->ks_req[reqno].kr_preset = UINT64_MAX - pp->dcpc_ovfval;
373 set->ks_nreqs++;
378 * Create a fresh request set for the enablings represented in the
379 * 'dcpc_actv_reqs' array which contains the probes we want to be
380 * in the set. This can be called for several reasons:
382 * 1) We are on a single or multi overflow platform and we have no
383 * current events so we can just create the set and initialize it.
384 * 2) We are on a multi-overflow platform and we already have one or
385 * more existing events and we are adding a new enabling. Create a
386 * new set and copy old requests in and then add the new request.
387 * 3) We are on a multi-overflow platform and we have just removed an
388 * enabling but we still have enablings whch are valid. Create a new
389 * set and copy in still valid requests.
391 static kcpc_set_t *
392 dcpc_create_set(cpu_t *c)
394 int i, reqno = 0;
395 int active_requests = 0;
396 kcpc_set_t *set;
399 * First get a count of the number of currently active requests.
400 * Note that dcpc_actv_reqs[] should always reflect which requests
401 * we want to be in the set that is to be created. It is the
402 * responsibility of the caller of dcpc_create_set() to adjust that
403 * array accordingly beforehand.
405 for (i = 0; i < cpc_ncounters; i++) {
406 if (dcpc_actv_reqs[i] != NULL)
407 active_requests++;
410 set = kmem_zalloc(sizeof (kcpc_set_t), KM_SLEEP);
412 set->ks_req =
413 kmem_zalloc(sizeof (kcpc_request_t) * active_requests, KM_SLEEP);
415 set->ks_data =
416 kmem_zalloc(active_requests * sizeof (uint64_t), KM_SLEEP);
419 * Look for valid entries in the active requests array and populate
420 * the request set for any entries found.
422 for (i = 0; i < cpc_ncounters; i++) {
423 if (dcpc_actv_reqs[i] != NULL) {
424 dcpc_populate_set(c, dcpc_actv_reqs[i], set, reqno);
425 reqno++;
429 return (set);
432 static int
433 dcpc_program_cpu_event(cpu_t *c)
435 int i, j, subcode;
436 kcpc_ctx_t *ctx, *octx;
437 kcpc_set_t *set;
439 set = dcpc_create_set(c);
441 octx = NULL;
442 set->ks_ctx = ctx = kcpc_ctx_alloc();
443 ctx->kc_set = set;
444 ctx->kc_cpuid = c->cpu_id;
446 if (kcpc_assign_reqs(set, ctx) != 0)
447 goto err;
449 if (kcpc_configure_reqs(ctx, set, &subcode) != 0)
450 goto err;
452 for (i = 0; i < set->ks_nreqs; i++) {
453 for (j = 0; j < cpc_ncounters; j++) {
454 if (dcpc_actv_reqs[j] != NULL &&
455 strcmp(set->ks_req[i].kr_event,
456 dcpc_actv_reqs[j]->dcpc_event_name) == 0) {
457 dcpc_actv_reqs[j]->dcpc_picno =
458 set->ks_req[i].kr_picnum;
464 * If we already have an active enabling then save the current cpc
465 * context away.
467 if (c->cpu_cpc_ctx != NULL)
468 octx = c->cpu_cpc_ctx;
470 c->cpu_cpc_ctx = ctx;
471 kcpc_remote_program(c);
473 if (octx != NULL) {
474 kcpc_set_t *oset = octx->kc_set;
475 kmem_free(oset->ks_data, oset->ks_nreqs * sizeof (uint64_t));
476 kcpc_free_set(oset);
477 kcpc_ctx_free(octx);
480 return (0);
482 err:
484 * We failed to configure this request up so free things up and
485 * get out.
487 kmem_free(set->ks_data, set->ks_nreqs * sizeof (uint64_t));
488 kcpc_free_set(set);
489 kcpc_ctx_free(ctx);
491 return (-1);
494 static void
495 dcpc_disable_cpu(cpu_t *c)
497 kcpc_ctx_t *ctx;
498 kcpc_set_t *set;
501 * Leave this CPU alone if it's already offline.
503 if (c->cpu_flags & CPU_OFFLINE)
504 return;
506 kcpc_remote_stop(c);
508 ctx = c->cpu_cpc_ctx;
509 set = ctx->kc_set;
511 kcpc_free_configs(set);
513 kmem_free(set->ks_data, set->ks_nreqs * sizeof (uint64_t));
514 kcpc_free_set(set);
515 kcpc_ctx_free(ctx);
516 c->cpu_cpc_ctx = NULL;
520 * Stop overflow interrupts being actively processed so that per-CPU
521 * configuration state can be changed safely and correctly. Each CPU has a
522 * dcpc interrupt state byte which is transitioned from DCPC_INTR_FREE (the
523 * "free" state) to DCPC_INTR_CONFIG (the "configuration in process" state)
524 * before any configuration state is changed on any CPUs. The hardware overflow
525 * handler, kcpc_hw_overflow_intr(), will only process an interrupt when a
526 * configuration is not in process (i.e. the state is marked as free). During
527 * interrupt processing the state is set to DCPC_INTR_PROCESSING by the
528 * overflow handler.
530 static void
531 dcpc_block_interrupts(void)
533 cpu_t *c;
534 uint8_t *state;
536 c = cpu_list;
538 do {
539 state = &cpu_core[c->cpu_id].cpuc_dcpc_intr_state;
541 while (atomic_cas_8(state, DCPC_INTR_FREE,
542 DCPC_INTR_CONFIG) != DCPC_INTR_FREE)
543 continue;
545 } while ((c = c->cpu_next) != cpu_list);
549 * Set all CPUs dcpc interrupt state to DCPC_INTR_FREE to indicate that
550 * overflow interrupts can be processed safely.
552 static void
553 dcpc_release_interrupts(void)
555 cpu_t *c = cpu_list;
557 do {
558 cpu_core[c->cpu_id].cpuc_dcpc_intr_state = DCPC_INTR_FREE;
559 membar_producer();
560 } while ((c = c->cpu_next) != cpu_list);
564 * dcpc_program_event() can be called owing to a new enabling or if a multi
565 * overflow platform has disabled a request but needs to program the requests
566 * that are still valid.
568 * Every invocation of dcpc_program_event() will create a new kcpc_ctx_t
569 * and a new request set which contains the new enabling and any old enablings
570 * which are still valid (possible with multi-overflow platforms).
572 static int
573 dcpc_program_event(dcpc_probe_t *pp)
575 cpu_t *c;
576 int ret = 0;
578 ASSERT(MUTEX_HELD(&cpu_lock));
580 kpreempt_disable();
582 dcpc_block_interrupts();
584 c = cpu_list;
586 do {
588 * Skip CPUs that are currently offline.
590 if (c->cpu_flags & CPU_OFFLINE)
591 continue;
593 if (c->cpu_cpc_ctx != NULL)
594 kcpc_remote_stop(c);
595 } while ((c = c->cpu_next) != cpu_list);
597 dcpc_release_interrupts();
600 * If this enabling is being removed (in the case of a multi event
601 * capable system with more than one active enabling), we can now
602 * update the active request array to reflect the enablings that need
603 * to be reprogrammed.
605 if (pp->dcpc_disabling == 1)
606 dcpc_actv_reqs[pp->dcpc_actv_req_idx] = NULL;
608 do {
610 * Skip CPUs that are currently offline.
612 if (c->cpu_flags & CPU_OFFLINE)
613 continue;
615 ret = dcpc_program_cpu_event(c);
616 } while ((c = c->cpu_next) != cpu_list && ret == 0);
619 * If dcpc_program_cpu_event() fails then it is because we couldn't
620 * configure the requests in the set for the CPU and not because of
621 * an error programming the hardware. If we have a failure here then
622 * we assume no CPUs have been programmed in the above step as they
623 * are all configured identically.
625 if (ret != 0) {
626 pp->dcpc_enabled = 0;
627 kpreempt_enable();
628 return (-1);
631 if (pp->dcpc_disabling != 1)
632 pp->dcpc_enabled = 1;
634 kpreempt_enable();
636 return (0);
639 /*ARGSUSED*/
640 static int
641 dcpc_enable(void *arg, dtrace_id_t id, void *parg)
643 dcpc_probe_t *pp = parg;
644 int i, found = 0;
645 cpu_t *c;
647 ASSERT(MUTEX_HELD(&cpu_lock));
650 * Bail out if the counters are being used by a libcpc consumer.
652 rw_enter(&kcpc_cpuctx_lock, RW_READER);
653 if (kcpc_cpuctx > 0) {
654 rw_exit(&kcpc_cpuctx_lock);
655 return (-1);
658 dtrace_cpc_in_use++;
659 rw_exit(&kcpc_cpuctx_lock);
662 * Locate this enabling in the first free entry of the active
663 * request array.
665 for (i = 0; i < cpc_ncounters; i++) {
666 if (dcpc_actv_reqs[i] == NULL) {
667 dcpc_actv_reqs[i] = pp;
668 pp->dcpc_actv_req_idx = i;
669 found = 1;
670 break;
675 * If we couldn't find a slot for this probe then there is no
676 * room at the inn.
678 if (!found) {
679 dtrace_cpc_in_use--;
680 return (-1);
683 ASSERT(pp->dcpc_actv_req_idx >= 0);
686 * The following must hold true if we are to (attempt to) enable
687 * this request:
689 * 1) No enablings currently exist. We allow all platforms to
690 * proceed if this is true.
692 * OR
694 * 2) If the platform is multi overflow capable and there are
695 * less valid enablings than there are counters. There is no
696 * guarantee that a platform can accommodate as many events as
697 * it has counters for but we will at least try to program
698 * up to that many requests.
700 * The 'dcpc_enablings' variable is implictly protected by locking
701 * provided by the DTrace framework and the cpu management framework.
703 if (dcpc_enablings == 0 || (dcpc_mult_ovf_cap &&
704 dcpc_enablings < cpc_ncounters)) {
706 * Before attempting to program the first enabling we need to
707 * invalidate any lwp-based contexts.
709 if (dcpc_enablings == 0)
710 kcpc_invalidate_all();
712 if (dcpc_program_event(pp) == 0) {
713 dcpc_enablings++;
714 return (0);
719 * If active enablings existed before we failed to enable this probe
720 * on a multi event capable platform then we need to restart counters
721 * as they will have been stopped in the attempted configuration. The
722 * context should now just contain the request prior to this failed
723 * enabling.
725 if (dcpc_enablings > 0 && dcpc_mult_ovf_cap) {
726 c = cpu_list;
728 ASSERT(dcpc_mult_ovf_cap == 1);
729 do {
731 * Skip CPUs that are currently offline.
733 if (c->cpu_flags & CPU_OFFLINE)
734 continue;
736 kcpc_remote_program(c);
737 } while ((c = c->cpu_next) != cpu_list);
740 dtrace_cpc_in_use--;
741 dcpc_actv_reqs[pp->dcpc_actv_req_idx] = NULL;
742 pp->dcpc_actv_req_idx = pp->dcpc_picno = -1;
744 return (-1);
748 * If only one enabling is active then remove the context and free
749 * everything up. If there are multiple enablings active then remove this
750 * one, its associated meta-data and re-program the hardware.
752 /*ARGSUSED*/
753 static void
754 dcpc_disable(void *arg, dtrace_id_t id, void *parg)
756 cpu_t *c;
757 dcpc_probe_t *pp = parg;
759 ASSERT(MUTEX_HELD(&cpu_lock));
761 kpreempt_disable();
764 * This probe didn't actually make it as far as being fully enabled
765 * so we needn't do anything with it.
767 if (pp->dcpc_enabled == 0) {
769 * If we actually allocated this request a slot in the
770 * request array but failed to enabled it then remove the
771 * entry in the array.
773 if (pp->dcpc_actv_req_idx >= 0) {
774 dcpc_actv_reqs[pp->dcpc_actv_req_idx] = NULL;
775 pp->dcpc_actv_req_idx = pp->dcpc_picno =
776 pp->dcpc_disabling = -1;
779 kpreempt_enable();
780 return;
784 * If this is the only enabling then stop all the counters and
785 * free up the meta-data.
787 if (dcpc_enablings == 1) {
788 ASSERT(dtrace_cpc_in_use == 1);
790 dcpc_block_interrupts();
792 c = cpu_list;
794 do {
795 dcpc_disable_cpu(c);
796 } while ((c = c->cpu_next) != cpu_list);
798 dcpc_actv_reqs[pp->dcpc_actv_req_idx] = NULL;
799 dcpc_release_interrupts();
800 } else {
802 * This platform can support multiple overflow events and
803 * the enabling being disabled is not the last one. Remove this
804 * enabling and re-program the hardware with the new config.
806 ASSERT(dcpc_mult_ovf_cap);
807 ASSERT(dcpc_enablings > 1);
809 pp->dcpc_disabling = 1;
810 (void) dcpc_program_event(pp);
813 kpreempt_enable();
815 dcpc_enablings--;
816 dtrace_cpc_in_use--;
817 pp->dcpc_enabled = 0;
818 pp->dcpc_actv_req_idx = pp->dcpc_picno = pp->dcpc_disabling = -1;
821 /*ARGSUSED*/
822 static int
823 dcpc_cpu_setup(cpu_setup_t what, processorid_t cpu, void *arg)
825 cpu_t *c;
826 uint8_t *state;
828 ASSERT(MUTEX_HELD(&cpu_lock));
830 switch (what) {
831 case CPU_OFF:
833 * Offline CPUs are not allowed to take part so remove this
834 * CPU if we are actively tracing.
836 if (dtrace_cpc_in_use) {
837 c = cpu_get(cpu);
838 state = &cpu_core[c->cpu_id].cpuc_dcpc_intr_state;
841 * Indicate that a configuration is in process in
842 * order to stop overflow interrupts being processed
843 * on this CPU while we disable it.
845 while (atomic_cas_8(state, DCPC_INTR_FREE,
846 DCPC_INTR_CONFIG) != DCPC_INTR_FREE)
847 continue;
849 dcpc_disable_cpu(c);
852 * Reset this CPUs interrupt state as the configuration
853 * has ended.
855 cpu_core[c->cpu_id].cpuc_dcpc_intr_state =
856 DCPC_INTR_FREE;
857 membar_producer();
859 break;
861 case CPU_ON:
862 case CPU_SETUP:
864 * This CPU is being initialized or brought online so program
865 * it with the current request set if we are actively tracing.
867 if (dtrace_cpc_in_use) {
868 c = cpu_get(cpu);
870 (void) dcpc_program_cpu_event(c);
872 break;
874 default:
875 break;
878 return (0);
881 static dtrace_pattr_t dcpc_attr = {
882 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
883 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
884 { DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
885 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_CPU },
886 { DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
889 static dtrace_pops_t dcpc_pops = {
890 dcpc_provide,
891 NULL,
892 dcpc_enable,
893 dcpc_disable,
894 NULL,
895 NULL,
896 NULL,
897 NULL,
898 dcpc_usermode,
899 dcpc_destroy
902 /*ARGSUSED*/
903 static int
904 dcpc_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
906 return (0);
909 /*ARGSUSED*/
910 static int
911 dcpc_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
913 int error;
915 switch (infocmd) {
916 case DDI_INFO_DEVT2DEVINFO:
917 *result = (void *)dcpc_devi;
918 error = DDI_SUCCESS;
919 break;
920 case DDI_INFO_DEVT2INSTANCE:
921 *result = (void *)0;
922 error = DDI_SUCCESS;
923 break;
924 default:
925 error = DDI_FAILURE;
927 return (error);
930 static int
931 dcpc_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
933 switch (cmd) {
934 case DDI_DETACH:
935 break;
936 case DDI_SUSPEND:
937 return (DDI_SUCCESS);
938 default:
939 return (DDI_FAILURE);
942 if (dtrace_unregister(dcpc_pid) != 0)
943 return (DDI_FAILURE);
945 ddi_remove_minor_node(devi, NULL);
947 mutex_enter(&cpu_lock);
948 unregister_cpu_setup_func(dcpc_cpu_setup, NULL);
949 mutex_exit(&cpu_lock);
951 kmem_free(dcpc_actv_reqs, cpc_ncounters * sizeof (dcpc_probe_t *));
953 kcpc_unregister_dcpc();
955 return (DDI_SUCCESS);
958 static int
959 dcpc_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
961 uint_t caps;
962 char *attrs;
964 switch (cmd) {
965 case DDI_ATTACH:
966 break;
967 case DDI_RESUME:
968 return (DDI_SUCCESS);
969 default:
970 return (DDI_FAILURE);
973 if (kcpc_pcbe_loaded() == -1)
974 return (DDI_FAILURE);
976 caps = kcpc_pcbe_capabilities();
978 if (!(caps & CPC_CAP_OVERFLOW_INTERRUPT)) {
979 cmn_err(CE_WARN, "dcpc: Counter Overflow not supported"\
980 " on this processor\n");
981 return (DDI_FAILURE);
984 if (ddi_create_minor_node(devi, "dcpc", S_IFCHR, 0,
985 DDI_PSEUDO, NULL) == DDI_FAILURE ||
986 dtrace_register("cpc", &dcpc_attr, DTRACE_PRIV_KERNEL,
987 NULL, &dcpc_pops, NULL, &dcpc_pid) != 0) {
988 ddi_remove_minor_node(devi, NULL);
989 return (DDI_FAILURE);
992 mutex_enter(&cpu_lock);
993 register_cpu_setup_func(dcpc_cpu_setup, NULL);
994 mutex_exit(&cpu_lock);
996 dcpc_ovf_mask = (1 << cpc_ncounters) - 1;
997 ASSERT(dcpc_ovf_mask != 0);
999 if (caps & CPC_CAP_OVERFLOW_PRECISE)
1000 dcpc_mult_ovf_cap = 1;
1003 * Determine which, if any, mask attribute the back-end can use.
1005 attrs = kcpc_list_attrs();
1006 if (strstr(attrs, "umask") != NULL)
1007 dcpc_mask_type |= DCPC_UMASK;
1008 else if (strstr(attrs, "emask") != NULL)
1009 dcpc_mask_type |= DCPC_EMASK;
1012 * The dcpc_actv_reqs array is used to store the requests that
1013 * we currently have programmed. The order of requests in this
1014 * array is not necessarily the order that the event appears in
1015 * the kcpc_request_t array. Once entered into a slot in the array
1016 * the entry is not moved until it's removed.
1018 dcpc_actv_reqs =
1019 kmem_zalloc(cpc_ncounters * sizeof (dcpc_probe_t *), KM_SLEEP);
1021 dcpc_min_overflow = ddi_prop_get_int(DDI_DEV_T_ANY, devi,
1022 DDI_PROP_DONTPASS, "dcpc-min-overflow", DCPC_MIN_OVF_DEFAULT);
1024 kcpc_register_dcpc(dcpc_fire);
1026 ddi_report_dev(devi);
1027 dcpc_devi = devi;
1029 return (DDI_SUCCESS);
1032 static struct cb_ops dcpc_cb_ops = {
1033 dcpc_open, /* open */
1034 nodev, /* close */
1035 nulldev, /* strategy */
1036 nulldev, /* print */
1037 nodev, /* dump */
1038 nodev, /* read */
1039 nodev, /* write */
1040 nodev, /* ioctl */
1041 nodev, /* devmap */
1042 nodev, /* mmap */
1043 nodev, /* segmap */
1044 nochpoll, /* poll */
1045 ddi_prop_op, /* cb_prop_op */
1046 0, /* streamtab */
1047 D_NEW | D_MP /* Driver compatibility flag */
1050 static struct dev_ops dcpc_ops = {
1051 DEVO_REV, /* devo_rev, */
1052 0, /* refcnt */
1053 dcpc_info, /* get_dev_info */
1054 nulldev, /* identify */
1055 nulldev, /* probe */
1056 dcpc_attach, /* attach */
1057 dcpc_detach, /* detach */
1058 nodev, /* reset */
1059 &dcpc_cb_ops, /* driver operations */
1060 NULL, /* bus operations */
1061 nodev, /* dev power */
1062 ddi_quiesce_not_needed /* quiesce */
1066 * Module linkage information for the kernel.
1068 static struct modldrv modldrv = {
1069 &mod_driverops, /* module type */
1070 "DTrace CPC Module", /* name of module */
1071 &dcpc_ops, /* driver ops */
1074 static struct modlinkage modlinkage = {
1075 MODREV_1,
1076 (void *)&modldrv,
1077 NULL
1081 _init(void)
1083 return (mod_install(&modlinkage));
1087 _info(struct modinfo *modinfop)
1089 return (mod_info(&modlinkage, modinfop));
1093 _fini(void)
1095 return (mod_remove(&modlinkage));