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]
25 static int dtrace_verbose_ioctl;
26 SYSCTL_INT(_debug_dtrace, OID_AUTO, verbose_ioctl, CTLFLAG_RW, &dtrace_verbose_ioctl, 0, "");
28 #define DTRACE_IOCTL_PRINTF(fmt, ...) if (dtrace_verbose_ioctl) printf(fmt, ## __VA_ARGS__ )
31 dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
35 dof_helper_t *dhp = NULL;
36 dof_hdr_t *dof = NULL;
39 case DTRACEHIOC_ADDDOF:
40 dhp = (dof_helper_t *)addr;
41 /* XXX all because dofhp_dof is 64 bit */
42 addr = (caddr_t)(vm_offset_t)dhp->dofhp_dof;
45 dof = dtrace_dof_copyin((intptr_t)addr, &rval);
50 mutex_enter(&dtrace_lock);
51 if ((rval = dtrace_helper_slurp((dof_hdr_t *)dof, dhp)) != -1) {
54 copyout(dhp, addr, sizeof(*dhp));
60 mutex_exit(&dtrace_lock);
62 case DTRACEHIOC_REMOVE:
63 mutex_enter(&dtrace_lock);
64 rval = dtrace_helper_destroygen((int)*addr);
65 mutex_exit(&dtrace_lock);
77 dtrace_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,
78 int flags __unused, struct thread *td)
80 #if __FreeBSD_version < 800039
81 dtrace_state_t *state = dev->si_drv1;
83 dtrace_state_t *state;
84 devfs_get_cdevpriv((void **) &state);
90 if (state->dts_anon) {
91 ASSERT(dtrace_anon.dta_state == NULL);
92 state = state->dts_anon;
96 case DTRACEIOC_AGGDESC: {
97 dtrace_aggdesc_t **paggdesc = (dtrace_aggdesc_t **) addr;
98 dtrace_aggdesc_t aggdesc;
100 dtrace_aggregation_t *agg;
103 dtrace_recdesc_t *lrec;
108 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_AGGDESC\n",__func__,__LINE__);
110 if (copyin((void *) *paggdesc, &aggdesc, sizeof (aggdesc)) != 0)
113 mutex_enter(&dtrace_lock);
115 if ((agg = dtrace_aggid2agg(state, aggdesc.dtagd_id)) == NULL) {
116 mutex_exit(&dtrace_lock);
120 aggdesc.dtagd_epid = agg->dtag_ecb->dte_epid;
122 nrecs = aggdesc.dtagd_nrecs;
123 aggdesc.dtagd_nrecs = 0;
125 offs = agg->dtag_base;
126 lrec = &agg->dtag_action.dta_rec;
127 aggdesc.dtagd_size = lrec->dtrd_offset + lrec->dtrd_size - offs;
129 for (act = agg->dtag_first; ; act = act->dta_next) {
130 ASSERT(act->dta_intuple ||
131 DTRACEACT_ISAGG(act->dta_kind));
134 * If this action has a record size of zero, it
135 * denotes an argument to the aggregating action.
136 * Because the presence of this record doesn't (or
137 * shouldn't) affect the way the data is interpreted,
138 * we don't copy it out to save user-level the
139 * confusion of dealing with a zero-length record.
141 if (act->dta_rec.dtrd_size == 0) {
142 ASSERT(agg->dtag_hasarg);
146 aggdesc.dtagd_nrecs++;
148 if (act == &agg->dtag_action)
153 * Now that we have the size, we need to allocate a temporary
154 * buffer in which to store the complete description. We need
155 * the temporary buffer to be able to drop dtrace_lock()
156 * across the copyout(), below.
158 size = sizeof (dtrace_aggdesc_t) +
159 (aggdesc.dtagd_nrecs * sizeof (dtrace_recdesc_t));
161 buf = kmem_alloc(size, KM_SLEEP);
162 dest = (uintptr_t)buf;
164 bcopy(&aggdesc, (void *)dest, sizeof (aggdesc));
165 dest += offsetof(dtrace_aggdesc_t, dtagd_rec[0]);
167 for (act = agg->dtag_first; ; act = act->dta_next) {
168 dtrace_recdesc_t rec = act->dta_rec;
171 * See the comment in the above loop for why we pass
172 * over zero-length records.
174 if (rec.dtrd_size == 0) {
175 ASSERT(agg->dtag_hasarg);
182 rec.dtrd_offset -= offs;
183 bcopy(&rec, (void *)dest, sizeof (rec));
184 dest += sizeof (dtrace_recdesc_t);
186 if (act == &agg->dtag_action)
190 mutex_exit(&dtrace_lock);
192 if (copyout(buf, (void *) *paggdesc, dest - (uintptr_t)buf) != 0) {
193 kmem_free(buf, size);
197 kmem_free(buf, size);
200 case DTRACEIOC_AGGSNAP:
201 case DTRACEIOC_BUFSNAP: {
202 dtrace_bufdesc_t **pdesc = (dtrace_bufdesc_t **) addr;
203 dtrace_bufdesc_t desc;
205 dtrace_buffer_t *buf;
207 dtrace_debug_output();
209 if (copyin((void *) *pdesc, &desc, sizeof (desc)) != 0)
212 DTRACE_IOCTL_PRINTF("%s(%d): %s curcpu %d cpu %d\n",
214 cmd == DTRACEIOC_AGGSNAP ?
215 "DTRACEIOC_AGGSNAP":"DTRACEIOC_BUFSNAP",
216 curcpu, desc.dtbd_cpu);
218 if (desc.dtbd_cpu >= NCPU)
220 if (pcpu_find(desc.dtbd_cpu) == NULL)
223 mutex_enter(&dtrace_lock);
225 if (cmd == DTRACEIOC_BUFSNAP) {
226 buf = &state->dts_buffer[desc.dtbd_cpu];
228 buf = &state->dts_aggbuffer[desc.dtbd_cpu];
231 if (buf->dtb_flags & (DTRACEBUF_RING | DTRACEBUF_FILL)) {
232 size_t sz = buf->dtb_offset;
234 if (state->dts_activity != DTRACE_ACTIVITY_STOPPED) {
235 mutex_exit(&dtrace_lock);
240 * If this buffer has already been consumed, we're
241 * going to indicate that there's nothing left here
244 if (buf->dtb_flags & DTRACEBUF_CONSUMED) {
245 mutex_exit(&dtrace_lock);
249 desc.dtbd_errors = 0;
250 desc.dtbd_oldest = 0;
253 if (copyout(&desc, (void *) *pdesc, sz) != 0)
260 * If this is a ring buffer that has wrapped, we want
261 * to copy the whole thing out.
263 if (buf->dtb_flags & DTRACEBUF_WRAPPED) {
264 dtrace_buffer_polish(buf);
268 if (copyout(buf->dtb_tomax, desc.dtbd_data, sz) != 0) {
269 mutex_exit(&dtrace_lock);
274 desc.dtbd_drops = buf->dtb_drops;
275 desc.dtbd_errors = buf->dtb_errors;
276 desc.dtbd_oldest = buf->dtb_xamot_offset;
277 desc.dtbd_timestamp = dtrace_gethrtime();
279 mutex_exit(&dtrace_lock);
281 if (copyout(&desc, (void *) *pdesc, sizeof (desc)) != 0)
284 buf->dtb_flags |= DTRACEBUF_CONSUMED;
289 if (buf->dtb_tomax == NULL) {
290 ASSERT(buf->dtb_xamot == NULL);
291 mutex_exit(&dtrace_lock);
295 cached = buf->dtb_tomax;
296 ASSERT(!(buf->dtb_flags & DTRACEBUF_NOSWITCH));
298 dtrace_xcall(desc.dtbd_cpu,
299 (dtrace_xcall_t)dtrace_buffer_switch, buf);
301 state->dts_errors += buf->dtb_xamot_errors;
304 * If the buffers did not actually switch, then the cross call
305 * did not take place -- presumably because the given CPU is
306 * not in the ready set. If this is the case, we'll return
309 if (buf->dtb_tomax == cached) {
310 ASSERT(buf->dtb_xamot != cached);
311 mutex_exit(&dtrace_lock);
315 ASSERT(cached == buf->dtb_xamot);
317 DTRACE_IOCTL_PRINTF("%s(%d): copyout the buffer snapshot\n",__func__,__LINE__);
320 * We have our snapshot; now copy it out.
322 if (copyout(buf->dtb_xamot, desc.dtbd_data,
323 buf->dtb_xamot_offset) != 0) {
324 mutex_exit(&dtrace_lock);
328 desc.dtbd_size = buf->dtb_xamot_offset;
329 desc.dtbd_drops = buf->dtb_xamot_drops;
330 desc.dtbd_errors = buf->dtb_xamot_errors;
331 desc.dtbd_oldest = 0;
332 desc.dtbd_timestamp = buf->dtb_switched;
334 mutex_exit(&dtrace_lock);
336 DTRACE_IOCTL_PRINTF("%s(%d): copyout buffer desc: size %zd drops %lu errors %lu\n",__func__,__LINE__,(size_t) desc.dtbd_size,(u_long) desc.dtbd_drops,(u_long) desc.dtbd_errors);
339 * Finally, copy out the buffer description.
341 if (copyout(&desc, (void *) *pdesc, sizeof (desc)) != 0)
346 case DTRACEIOC_CONF: {
349 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_CONF\n",__func__,__LINE__);
351 bzero(&conf, sizeof (conf));
352 conf.dtc_difversion = DIF_VERSION;
353 conf.dtc_difintregs = DIF_DIR_NREGS;
354 conf.dtc_diftupregs = DIF_DTR_NREGS;
355 conf.dtc_ctfmodel = CTF_MODEL_NATIVE;
357 *((dtrace_conf_t *) addr) = conf;
361 case DTRACEIOC_DOFGET: {
362 dof_hdr_t **pdof = (dof_hdr_t **) addr;
363 dof_hdr_t hdr, *dof = *pdof;
367 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_DOFGET\n",__func__,__LINE__);
369 if (copyin((void *)dof, &hdr, sizeof (hdr)) != 0)
372 mutex_enter(&dtrace_lock);
373 dof = dtrace_dof_create(state);
374 mutex_exit(&dtrace_lock);
376 len = MIN(hdr.dofh_loadsz, dof->dofh_loadsz);
377 rval = copyout(dof, (void *) *pdof, len);
378 dtrace_dof_destroy(dof);
380 return (rval == 0 ? 0 : EFAULT);
382 case DTRACEIOC_ENABLE: {
383 dof_hdr_t *dof = NULL;
384 dtrace_enabling_t *enab = NULL;
385 dtrace_vstate_t *vstate;
388 dtrace_enable_io_t *p = (dtrace_enable_io_t *) addr;
390 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_ENABLE\n",__func__,__LINE__);
393 * If a NULL argument has been passed, we take this as our
394 * cue to reevaluate our enablings.
396 if (p->dof == NULL) {
397 dtrace_enabling_matchall();
402 if ((dof = dtrace_dof_copyin((uintptr_t) p->dof, &rval)) == NULL)
405 mutex_enter(&cpu_lock);
406 mutex_enter(&dtrace_lock);
407 vstate = &state->dts_vstate;
409 if (state->dts_activity != DTRACE_ACTIVITY_INACTIVE) {
410 mutex_exit(&dtrace_lock);
411 mutex_exit(&cpu_lock);
412 dtrace_dof_destroy(dof);
416 if (dtrace_dof_slurp(dof, vstate, td->td_ucred, &enab, 0, B_TRUE) != 0) {
417 mutex_exit(&dtrace_lock);
418 mutex_exit(&cpu_lock);
419 dtrace_dof_destroy(dof);
423 if ((rval = dtrace_dof_options(dof, state)) != 0) {
424 dtrace_enabling_destroy(enab);
425 mutex_exit(&dtrace_lock);
426 mutex_exit(&cpu_lock);
427 dtrace_dof_destroy(dof);
431 if ((err = dtrace_enabling_match(enab, &p->n_matched)) == 0) {
432 err = dtrace_enabling_retain(enab);
434 dtrace_enabling_destroy(enab);
437 mutex_exit(&cpu_lock);
438 mutex_exit(&dtrace_lock);
439 dtrace_dof_destroy(dof);
443 case DTRACEIOC_EPROBE: {
444 dtrace_eprobedesc_t **pepdesc = (dtrace_eprobedesc_t **) addr;
445 dtrace_eprobedesc_t epdesc;
447 dtrace_action_t *act;
453 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_EPROBE\n",__func__,__LINE__);
455 if (copyin((void *)*pepdesc, &epdesc, sizeof (epdesc)) != 0)
458 mutex_enter(&dtrace_lock);
460 if ((ecb = dtrace_epid2ecb(state, epdesc.dtepd_epid)) == NULL) {
461 mutex_exit(&dtrace_lock);
465 if (ecb->dte_probe == NULL) {
466 mutex_exit(&dtrace_lock);
470 epdesc.dtepd_probeid = ecb->dte_probe->dtpr_id;
471 epdesc.dtepd_uarg = ecb->dte_uarg;
472 epdesc.dtepd_size = ecb->dte_size;
474 nrecs = epdesc.dtepd_nrecs;
475 epdesc.dtepd_nrecs = 0;
476 for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
477 if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
480 epdesc.dtepd_nrecs++;
484 * Now that we have the size, we need to allocate a temporary
485 * buffer in which to store the complete description. We need
486 * the temporary buffer to be able to drop dtrace_lock()
487 * across the copyout(), below.
489 size = sizeof (dtrace_eprobedesc_t) +
490 (epdesc.dtepd_nrecs * sizeof (dtrace_recdesc_t));
492 buf = kmem_alloc(size, KM_SLEEP);
493 dest = (uintptr_t)buf;
495 bcopy(&epdesc, (void *)dest, sizeof (epdesc));
496 dest += offsetof(dtrace_eprobedesc_t, dtepd_rec[0]);
498 for (act = ecb->dte_action; act != NULL; act = act->dta_next) {
499 if (DTRACEACT_ISAGG(act->dta_kind) || act->dta_intuple)
505 bcopy(&act->dta_rec, (void *)dest,
506 sizeof (dtrace_recdesc_t));
507 dest += sizeof (dtrace_recdesc_t);
510 mutex_exit(&dtrace_lock);
512 if (copyout(buf, (void *) *pepdesc, dest - (uintptr_t)buf) != 0) {
513 kmem_free(buf, size);
517 kmem_free(buf, size);
520 case DTRACEIOC_FORMAT: {
521 dtrace_fmtdesc_t *fmt = (dtrace_fmtdesc_t *) addr;
525 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_FORMAT\n",__func__,__LINE__);
527 mutex_enter(&dtrace_lock);
529 if (fmt->dtfd_format == 0 ||
530 fmt->dtfd_format > state->dts_nformats) {
531 mutex_exit(&dtrace_lock);
536 * Format strings are allocated contiguously and they are
537 * never freed; if a format index is less than the number
538 * of formats, we can assert that the format map is non-NULL
539 * and that the format for the specified index is non-NULL.
541 ASSERT(state->dts_formats != NULL);
542 str = state->dts_formats[fmt->dtfd_format - 1];
545 len = strlen(str) + 1;
547 if (len > fmt->dtfd_length) {
548 fmt->dtfd_length = len;
550 if (copyout(str, fmt->dtfd_string, len) != 0) {
551 mutex_exit(&dtrace_lock);
556 mutex_exit(&dtrace_lock);
561 processorid_t *cpuid = (processorid_t *) addr;
563 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_GO\n",__func__,__LINE__);
565 rval = dtrace_state_go(state, cpuid);
569 case DTRACEIOC_PROBEARG: {
570 dtrace_argdesc_t *desc = (dtrace_argdesc_t *) addr;
571 dtrace_probe_t *probe;
572 dtrace_provider_t *prov;
574 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_PROBEARG\n",__func__,__LINE__);
576 if (desc->dtargd_id == DTRACE_IDNONE)
579 if (desc->dtargd_ndx == DTRACE_ARGNONE)
582 mutex_enter(&dtrace_provider_lock);
584 mutex_enter(&mod_lock);
586 mutex_enter(&dtrace_lock);
588 if (desc->dtargd_id > dtrace_nprobes) {
589 mutex_exit(&dtrace_lock);
591 mutex_exit(&mod_lock);
593 mutex_exit(&dtrace_provider_lock);
597 if ((probe = dtrace_probes[desc->dtargd_id - 1]) == NULL) {
598 mutex_exit(&dtrace_lock);
600 mutex_exit(&mod_lock);
602 mutex_exit(&dtrace_provider_lock);
606 mutex_exit(&dtrace_lock);
608 prov = probe->dtpr_provider;
610 if (prov->dtpv_pops.dtps_getargdesc == NULL) {
612 * There isn't any typed information for this probe.
613 * Set the argument number to DTRACE_ARGNONE.
615 desc->dtargd_ndx = DTRACE_ARGNONE;
617 desc->dtargd_native[0] = '\0';
618 desc->dtargd_xlate[0] = '\0';
619 desc->dtargd_mapping = desc->dtargd_ndx;
621 prov->dtpv_pops.dtps_getargdesc(prov->dtpv_arg,
622 probe->dtpr_id, probe->dtpr_arg, desc);
626 mutex_exit(&mod_lock);
628 mutex_exit(&dtrace_provider_lock);
632 case DTRACEIOC_PROBEMATCH:
633 case DTRACEIOC_PROBES: {
634 dtrace_probedesc_t *p_desc = (dtrace_probedesc_t *) addr;
635 dtrace_probe_t *probe = NULL;
636 dtrace_probekey_t pkey;
643 DTRACE_IOCTL_PRINTF("%s(%d): %s\n",__func__,__LINE__,
644 cmd == DTRACEIOC_PROBEMATCH ?
645 "DTRACEIOC_PROBEMATCH":"DTRACEIOC_PROBES");
647 p_desc->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
648 p_desc->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
649 p_desc->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
650 p_desc->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
653 * Before we attempt to match this probe, we want to give
654 * all providers the opportunity to provide it.
656 if (p_desc->dtpd_id == DTRACE_IDNONE) {
657 mutex_enter(&dtrace_provider_lock);
658 dtrace_probe_provide(p_desc, NULL);
659 mutex_exit(&dtrace_provider_lock);
663 if (cmd == DTRACEIOC_PROBEMATCH) {
664 dtrace_probekey(p_desc, &pkey);
665 pkey.dtpk_id = DTRACE_IDNONE;
668 dtrace_cred2priv(td->td_ucred, &priv, &uid, &zoneid);
670 mutex_enter(&dtrace_lock);
672 if (cmd == DTRACEIOC_PROBEMATCH) {
673 for (i = p_desc->dtpd_id; i <= dtrace_nprobes; i++) {
674 if ((probe = dtrace_probes[i - 1]) != NULL &&
675 (m = dtrace_match_probe(probe, &pkey,
676 priv, uid, zoneid)) != 0)
681 mutex_exit(&dtrace_lock);
686 for (i = p_desc->dtpd_id; i <= dtrace_nprobes; i++) {
687 if ((probe = dtrace_probes[i - 1]) != NULL &&
688 dtrace_match_priv(probe, priv, uid, zoneid))
694 mutex_exit(&dtrace_lock);
698 dtrace_probe_description(probe, p_desc);
699 mutex_exit(&dtrace_lock);
703 case DTRACEIOC_PROVIDER: {
704 dtrace_providerdesc_t *pvd = (dtrace_providerdesc_t *) addr;
705 dtrace_provider_t *pvp;
707 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_PROVIDER\n",__func__,__LINE__);
709 pvd->dtvd_name[DTRACE_PROVNAMELEN - 1] = '\0';
710 mutex_enter(&dtrace_provider_lock);
712 for (pvp = dtrace_provider; pvp != NULL; pvp = pvp->dtpv_next) {
713 if (strcmp(pvp->dtpv_name, pvd->dtvd_name) == 0)
717 mutex_exit(&dtrace_provider_lock);
722 bcopy(&pvp->dtpv_priv, &pvd->dtvd_priv, sizeof (dtrace_ppriv_t));
723 bcopy(&pvp->dtpv_attr, &pvd->dtvd_attr, sizeof (dtrace_pattr_t));
727 case DTRACEIOC_REPLICATE: {
728 dtrace_repldesc_t *desc = (dtrace_repldesc_t *) addr;
729 dtrace_probedesc_t *match = &desc->dtrpd_match;
730 dtrace_probedesc_t *create = &desc->dtrpd_create;
733 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_REPLICATE\n",__func__,__LINE__);
735 match->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
736 match->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
737 match->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
738 match->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
740 create->dtpd_provider[DTRACE_PROVNAMELEN - 1] = '\0';
741 create->dtpd_mod[DTRACE_MODNAMELEN - 1] = '\0';
742 create->dtpd_func[DTRACE_FUNCNAMELEN - 1] = '\0';
743 create->dtpd_name[DTRACE_NAMELEN - 1] = '\0';
745 mutex_enter(&dtrace_lock);
746 err = dtrace_enabling_replicate(state, match, create);
747 mutex_exit(&dtrace_lock);
751 case DTRACEIOC_STATUS: {
752 dtrace_status_t *stat = (dtrace_status_t *) addr;
753 dtrace_dstate_t *dstate;
757 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_STATUS\n",__func__,__LINE__);
760 * See the comment in dtrace_state_deadman() for the reason
761 * for setting dts_laststatus to INT64_MAX before setting
762 * it to the correct value.
764 state->dts_laststatus = INT64_MAX;
765 dtrace_membar_producer();
766 state->dts_laststatus = dtrace_gethrtime();
768 bzero(stat, sizeof (*stat));
770 mutex_enter(&dtrace_lock);
772 if (state->dts_activity == DTRACE_ACTIVITY_INACTIVE) {
773 mutex_exit(&dtrace_lock);
777 if (state->dts_activity == DTRACE_ACTIVITY_DRAINING)
778 stat->dtst_exiting = 1;
780 nerrs = state->dts_errors;
781 dstate = &state->dts_vstate.dtvs_dynvars;
783 for (i = 0; i < NCPU; i++) {
785 if (pcpu_find(i) == NULL)
788 dtrace_dstate_percpu_t *dcpu = &dstate->dtds_percpu[i];
790 stat->dtst_dyndrops += dcpu->dtdsc_drops;
791 stat->dtst_dyndrops_dirty += dcpu->dtdsc_dirty_drops;
792 stat->dtst_dyndrops_rinsing += dcpu->dtdsc_rinsing_drops;
794 if (state->dts_buffer[i].dtb_flags & DTRACEBUF_FULL)
797 nerrs += state->dts_buffer[i].dtb_errors;
799 for (j = 0; j < state->dts_nspeculations; j++) {
800 dtrace_speculation_t *spec;
801 dtrace_buffer_t *buf;
803 spec = &state->dts_speculations[j];
804 buf = &spec->dtsp_buffer[i];
805 stat->dtst_specdrops += buf->dtb_xamot_drops;
809 stat->dtst_specdrops_busy = state->dts_speculations_busy;
810 stat->dtst_specdrops_unavail = state->dts_speculations_unavail;
811 stat->dtst_stkstroverflows = state->dts_stkstroverflows;
812 stat->dtst_dblerrors = state->dts_dblerrors;
814 (state->dts_activity == DTRACE_ACTIVITY_KILLED);
815 stat->dtst_errors = nerrs;
817 mutex_exit(&dtrace_lock);
821 case DTRACEIOC_STOP: {
823 processorid_t *cpuid = (processorid_t *) addr;
825 DTRACE_IOCTL_PRINTF("%s(%d): DTRACEIOC_STOP\n",__func__,__LINE__);
827 mutex_enter(&dtrace_lock);
828 rval = dtrace_state_stop(state, cpuid);
829 mutex_exit(&dtrace_lock);