1126745Sbenno/*
2126745Sbenno * CDDL HEADER START
3126745Sbenno *
4126745Sbenno * The contents of this file are subject to the terms of the
5126745Sbenno * Common Development and Distribution License (the "License").
6126745Sbenno * You may not use this file except in compliance with the License.
7126745Sbenno *
8126745Sbenno * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9126745Sbenno * or http://www.opensolaris.org/os/licensing.
10126745Sbenno * See the License for the specific language governing permissions
11126745Sbenno * and limitations under the License.
12126745Sbenno *
13126745Sbenno * When distributing Covered Code, include this CDDL HEADER in each
14126745Sbenno * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15126745Sbenno * If applicable, add the following below this CDDL HEADER, with the
16126745Sbenno * fields enclosed by brackets "[]" replaced with your own identifying
17126745Sbenno * information: Portions Copyright [yyyy] [name of copyright owner]
18126745Sbenno *
19126745Sbenno * CDDL HEADER END
20126745Sbenno *
21126745Sbenno * Portions Copyright 2010 The FreeBSD Foundation
22126745Sbenno *
23126745Sbenno * $FreeBSD: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/fasttrap.c 313758 2017-02-15 06:07:01Z markj $
24126745Sbenno */
25126745Sbenno
26126745Sbenno/*
27126745Sbenno * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
28126745Sbenno * Use is subject to license terms.
29126745Sbenno */
30126745Sbenno
31126745Sbenno/*
32126745Sbenno * Copyright (c) 2015, Joyent, Inc. All rights reserved.
33126745Sbenno */
34126745Sbenno
35126745Sbenno#include <sys/atomic.h>
36126745Sbenno#include <sys/errno.h>
37126745Sbenno#include <sys/stat.h>
38126745Sbenno#include <sys/modctl.h>
39126745Sbenno#include <sys/conf.h>
40126745Sbenno#include <sys/systm.h>
41126745Sbenno#ifdef illumos
42126745Sbenno#include <sys/ddi.h>
43126745Sbenno#endif
44126745Sbenno#include <sys/sunddi.h>
45126745Sbenno#include <sys/cpuvar.h>
46131861Sru#include <sys/kmem.h>
47131530Sru#ifdef illumos
48131530Sru#include <sys/strsubr.h>
49131861Sru#endif
50126745Sbenno#include <sys/fasttrap.h>
51131861Sru#include <sys/fasttrap_impl.h>
52131530Sru#include <sys/fasttrap_isa.h>
53131530Sru#include <sys/dtrace.h>
54131861Sru#include <sys/dtrace_impl.h>
55126745Sbenno#include <sys/sysmacros.h>
56131861Sru#include <sys/proc.h>
57131861Sru#include <sys/policy.h>
58126745Sbenno#ifdef illumos
59131861Sru#include <util/qsort.h>
60126745Sbenno#endif
61126745Sbenno#include <sys/mutex.h>
62126745Sbenno#include <sys/kernel.h>
63242997Sjoel#ifndef illumos
64131861Sru#include <sys/dtrace_bsd.h>
65126745Sbenno#include <sys/eventhandler.h>
66131861Sru#include <sys/rmlock.h>
67126745Sbenno#include <sys/sysent.h>
68126745Sbenno#include <sys/sysctl.h>
69131861Sru#include <sys/u8_textprep.h>
70131530Sru#include <sys/user.h>
71131861Sru
72126745Sbenno#include <vm/vm.h>
73126745Sbenno#include <vm/pmap.h>
74126745Sbenno#include <vm/vm_map.h>
75131861Sru#include <vm/vm_param.h>
76131530Sru
77131530Sru#include <cddl/dev/dtrace/dtrace_cddl.h>
78126745Sbenno#endif
79126745Sbenno
80126745Sbenno/*
81126745Sbenno * User-Land Trap-Based Tracing
82126745Sbenno * ----------------------------
83126745Sbenno *
84126745Sbenno * The fasttrap provider allows DTrace consumers to instrument any user-level
85126745Sbenno * instruction to gather data; this includes probes with semantic
86126745Sbenno * signifigance like entry and return as well as simple offsets into the
87126745Sbenno * function. While the specific techniques used are very ISA specific, the
88126745Sbenno * methodology is generalizable to any architecture.
89126745Sbenno *
90126745Sbenno *
91126745Sbenno * The General Methodology
92126745Sbenno * -----------------------
93126745Sbenno *
94126745Sbenno * With the primary goal of tracing every user-land instruction and the
95126745Sbenno * limitation that we can't trust user space so don't want to rely on much
96126745Sbenno * information there, we begin by replacing the instructions we want to trace
97 * with trap instructions. Each instruction we overwrite is saved into a hash
98 * table keyed by process ID and pc address. When we enter the kernel due to
99 * this trap instruction, we need the effects of the replaced instruction to
100 * appear to have occurred before we proceed with the user thread's
101 * execution.
102 *
103 * Each user level thread is represented by a ulwp_t structure which is
104 * always easily accessible through a register. The most basic way to produce
105 * the effects of the instruction we replaced is to copy that instruction out
106 * to a bit of scratch space reserved in the user thread's ulwp_t structure
107 * (a sort of kernel-private thread local storage), set the PC to that
108 * scratch space and single step. When we reenter the kernel after single
109 * stepping the instruction we must then adjust the PC to point to what would
110 * normally be the next instruction. Of course, special care must be taken
111 * for branches and jumps, but these represent such a small fraction of any
112 * instruction set that writing the code to emulate these in the kernel is
113 * not too difficult.
114 *
115 * Return probes may require several tracepoints to trace every return site,
116 * and, conversely, each tracepoint may activate several probes (the entry
117 * and offset 0 probes, for example). To solve this muliplexing problem,
118 * tracepoints contain lists of probes to activate and probes contain lists
119 * of tracepoints to enable. If a probe is activated, it adds its ID to
120 * existing tracepoints or creates new ones as necessary.
121 *
122 * Most probes are activated _before_ the instruction is executed, but return
123 * probes are activated _after_ the effects of the last instruction of the
124 * function are visible. Return probes must be fired _after_ we have
125 * single-stepped the instruction whereas all other probes are fired
126 * beforehand.
127 *
128 *
129 * Lock Ordering
130 * -------------
131 *
132 * The lock ordering below -- both internally and with respect to the DTrace
133 * framework -- is a little tricky and bears some explanation. Each provider
134 * has a lock (ftp_mtx) that protects its members including reference counts
135 * for enabled probes (ftp_rcount), consumers actively creating probes
136 * (ftp_ccount) and USDT consumers (ftp_mcount); all three prevent a provider
137 * from being freed. A provider is looked up by taking the bucket lock for the
138 * provider hash table, and is returned with its lock held. The provider lock
139 * may be taken in functions invoked by the DTrace framework, but may not be
140 * held while calling functions in the DTrace framework.
141 *
142 * To ensure consistency over multiple calls to the DTrace framework, the
143 * creation lock (ftp_cmtx) should be held. Naturally, the creation lock may
144 * not be taken when holding the provider lock as that would create a cyclic
145 * lock ordering. In situations where one would naturally take the provider
146 * lock and then the creation lock, we instead up a reference count to prevent
147 * the provider from disappearing, drop the provider lock, and acquire the
148 * creation lock.
149 *
150 * Briefly:
151 * 	bucket lock before provider lock
152 *	DTrace before provider lock
153 *	creation lock before DTrace
154 *	never hold the provider lock and creation lock simultaneously
155 */
156
157static d_open_t fasttrap_open;
158static d_ioctl_t fasttrap_ioctl;
159
160static struct cdevsw fasttrap_cdevsw = {
161	.d_version	= D_VERSION,
162	.d_open		= fasttrap_open,
163	.d_ioctl	= fasttrap_ioctl,
164	.d_name		= "fasttrap",
165};
166static struct cdev *fasttrap_cdev;
167static dtrace_meta_provider_id_t fasttrap_meta_id;
168
169static struct proc *fasttrap_cleanup_proc;
170static struct mtx fasttrap_cleanup_mtx;
171static uint_t fasttrap_cleanup_work, fasttrap_cleanup_drain, fasttrap_cleanup_cv;
172
173/*
174 * Generation count on modifications to the global tracepoint lookup table.
175 */
176static volatile uint64_t fasttrap_mod_gen;
177
178/*
179 * When the fasttrap provider is loaded, fasttrap_max is set to either
180 * FASTTRAP_MAX_DEFAULT, or the value for fasttrap-max-probes in the
181 * fasttrap.conf file (Illumos), or the value provied in the loader.conf (FreeBSD).
182 * Each time a probe is created, fasttrap_total is incremented by the number
183 * of tracepoints that may be associated with that probe; fasttrap_total is capped
184 * at fasttrap_max.
185 */
186#define	FASTTRAP_MAX_DEFAULT		250000
187static uint32_t fasttrap_max = FASTTRAP_MAX_DEFAULT;
188static uint32_t fasttrap_total;
189
190/*
191 * Copyright (c) 2011, Joyent, Inc. All rights reserved.
192 */
193
194#define	FASTTRAP_TPOINTS_DEFAULT_SIZE	0x4000
195#define	FASTTRAP_PROVIDERS_DEFAULT_SIZE	0x100
196#define	FASTTRAP_PROCS_DEFAULT_SIZE	0x100
197
198#define	FASTTRAP_PID_NAME		"pid"
199
200fasttrap_hash_t			fasttrap_tpoints;
201static fasttrap_hash_t		fasttrap_provs;
202static fasttrap_hash_t		fasttrap_procs;
203
204static uint64_t			fasttrap_pid_count;	/* pid ref count */
205static kmutex_t			fasttrap_count_mtx;	/* lock on ref count */
206
207#define	FASTTRAP_ENABLE_FAIL	1
208#define	FASTTRAP_ENABLE_PARTIAL	2
209
210static int fasttrap_tracepoint_enable(proc_t *, fasttrap_probe_t *, uint_t);
211static void fasttrap_tracepoint_disable(proc_t *, fasttrap_probe_t *, uint_t);
212
213static fasttrap_provider_t *fasttrap_provider_lookup(pid_t, const char *,
214    const dtrace_pattr_t *);
215static void fasttrap_provider_retire(pid_t, const char *, int);
216static void fasttrap_provider_free(fasttrap_provider_t *);
217
218static fasttrap_proc_t *fasttrap_proc_lookup(pid_t);
219static void fasttrap_proc_release(fasttrap_proc_t *);
220
221#ifndef illumos
222static void fasttrap_thread_dtor(void *, struct thread *);
223#endif
224
225#define	FASTTRAP_PROVS_INDEX(pid, name) \
226	((fasttrap_hash_str(name) + (pid)) & fasttrap_provs.fth_mask)
227
228#define	FASTTRAP_PROCS_INDEX(pid) ((pid) & fasttrap_procs.fth_mask)
229
230#ifndef illumos
231struct rmlock fasttrap_tp_lock;
232static eventhandler_tag fasttrap_thread_dtor_tag;
233#endif
234
235static unsigned long tpoints_hash_size = FASTTRAP_TPOINTS_DEFAULT_SIZE;
236
237#ifdef __FreeBSD__
238SYSCTL_DECL(_kern_dtrace);
239SYSCTL_NODE(_kern_dtrace, OID_AUTO, fasttrap, CTLFLAG_RD, 0, "DTrace fasttrap parameters");
240SYSCTL_UINT(_kern_dtrace_fasttrap, OID_AUTO, max_probes, CTLFLAG_RWTUN, &fasttrap_max,
241    FASTTRAP_MAX_DEFAULT, "Maximum number of fasttrap probes");
242SYSCTL_ULONG(_kern_dtrace_fasttrap, OID_AUTO, tpoints_hash_size, CTLFLAG_RDTUN, &tpoints_hash_size,
243    FASTTRAP_TPOINTS_DEFAULT_SIZE, "Size of the tracepoint hash table");
244#endif
245
246static int
247fasttrap_highbit(ulong_t i)
248{
249	int h = 1;
250
251	if (i == 0)
252		return (0);
253#ifdef _LP64
254	if (i & 0xffffffff00000000ul) {
255		h += 32; i >>= 32;
256	}
257#endif
258	if (i & 0xffff0000) {
259		h += 16; i >>= 16;
260	}
261	if (i & 0xff00) {
262		h += 8; i >>= 8;
263	}
264	if (i & 0xf0) {
265		h += 4; i >>= 4;
266	}
267	if (i & 0xc) {
268		h += 2; i >>= 2;
269	}
270	if (i & 0x2) {
271		h += 1;
272	}
273	return (h);
274}
275
276static uint_t
277fasttrap_hash_str(const char *p)
278{
279	unsigned int g;
280	uint_t hval = 0;
281
282	while (*p) {
283		hval = (hval << 4) + *p++;
284		if ((g = (hval & 0xf0000000)) != 0)
285			hval ^= g >> 24;
286		hval &= ~g;
287	}
288	return (hval);
289}
290
291void
292fasttrap_sigtrap(proc_t *p, kthread_t *t, uintptr_t pc)
293{
294#ifdef illumos
295	sigqueue_t *sqp = kmem_zalloc(sizeof (sigqueue_t), KM_SLEEP);
296
297	sqp->sq_info.si_signo = SIGTRAP;
298	sqp->sq_info.si_code = TRAP_DTRACE;
299	sqp->sq_info.si_addr = (caddr_t)pc;
300
301	mutex_enter(&p->p_lock);
302	sigaddqa(p, t, sqp);
303	mutex_exit(&p->p_lock);
304
305	if (t != NULL)
306		aston(t);
307#else
308	ksiginfo_t *ksi = kmem_zalloc(sizeof (ksiginfo_t), KM_SLEEP);
309
310	ksiginfo_init(ksi);
311	ksi->ksi_signo = SIGTRAP;
312	ksi->ksi_code = TRAP_DTRACE;
313	ksi->ksi_addr = (caddr_t)pc;
314	PROC_LOCK(p);
315	(void) tdsendsignal(p, t, SIGTRAP, ksi);
316	PROC_UNLOCK(p);
317#endif
318}
319
320#ifndef illumos
321/*
322 * Obtain a chunk of scratch space in the address space of the target process.
323 */
324fasttrap_scrspace_t *
325fasttrap_scraddr(struct thread *td, fasttrap_proc_t *fprc)
326{
327	fasttrap_scrblock_t *scrblk;
328	fasttrap_scrspace_t *scrspc;
329	struct proc *p;
330	vm_offset_t addr;
331	int error, i;
332
333	scrspc = NULL;
334	if (td->t_dtrace_sscr != NULL) {
335		/* If the thread already has scratch space, we're done. */
336		scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
337		return (scrspc);
338	}
339
340	p = td->td_proc;
341
342	mutex_enter(&fprc->ftpc_mtx);
343	if (LIST_EMPTY(&fprc->ftpc_fscr)) {
344		/*
345		 * No scratch space is available, so we'll map a new scratch
346		 * space block into the traced process' address space.
347		 */
348		addr = 0;
349		error = vm_map_find(&p->p_vmspace->vm_map, NULL, 0, &addr,
350		    FASTTRAP_SCRBLOCK_SIZE, 0, VMFS_ANY_SPACE, VM_PROT_ALL,
351		    VM_PROT_ALL, 0);
352		if (error != KERN_SUCCESS)
353			goto done;
354
355		scrblk = malloc(sizeof(*scrblk), M_SOLARIS, M_WAITOK);
356		scrblk->ftsb_addr = addr;
357		LIST_INSERT_HEAD(&fprc->ftpc_scrblks, scrblk, ftsb_next);
358
359		/*
360		 * Carve the block up into chunks and put them on the free list.
361		 */
362		for (i = 0;
363		    i < FASTTRAP_SCRBLOCK_SIZE / FASTTRAP_SCRSPACE_SIZE; i++) {
364			scrspc = malloc(sizeof(*scrspc), M_SOLARIS, M_WAITOK);
365			scrspc->ftss_addr = addr +
366			    i * FASTTRAP_SCRSPACE_SIZE;
367			LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc,
368			    ftss_next);
369		}
370	}
371
372	/*
373	 * Take the first scratch chunk off the free list, put it on the
374	 * allocated list, and return its address.
375	 */
376	scrspc = LIST_FIRST(&fprc->ftpc_fscr);
377	LIST_REMOVE(scrspc, ftss_next);
378	LIST_INSERT_HEAD(&fprc->ftpc_ascr, scrspc, ftss_next);
379
380	/*
381	 * This scratch space is reserved for use by td until the thread exits.
382	 */
383	td->t_dtrace_sscr = scrspc;
384
385done:
386	mutex_exit(&fprc->ftpc_mtx);
387
388	return (scrspc);
389}
390
391/*
392 * Return any allocated per-thread scratch space chunks back to the process'
393 * free list.
394 */
395static void
396fasttrap_thread_dtor(void *arg __unused, struct thread *td)
397{
398	fasttrap_bucket_t *bucket;
399	fasttrap_proc_t *fprc;
400	fasttrap_scrspace_t *scrspc;
401	pid_t pid;
402
403	if (td->t_dtrace_sscr == NULL)
404		return;
405
406	pid = td->td_proc->p_pid;
407	bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)];
408	fprc = NULL;
409
410	/* Look up the fasttrap process handle for this process. */
411	mutex_enter(&bucket->ftb_mtx);
412	for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
413		if (fprc->ftpc_pid == pid) {
414			mutex_enter(&fprc->ftpc_mtx);
415			mutex_exit(&bucket->ftb_mtx);
416			break;
417		}
418	}
419	if (fprc == NULL) {
420		mutex_exit(&bucket->ftb_mtx);
421		return;
422	}
423
424	scrspc = (fasttrap_scrspace_t *)td->t_dtrace_sscr;
425	LIST_REMOVE(scrspc, ftss_next);
426	LIST_INSERT_HEAD(&fprc->ftpc_fscr, scrspc, ftss_next);
427
428	mutex_exit(&fprc->ftpc_mtx);
429}
430#endif
431
432/*
433 * This function ensures that no threads are actively using the memory
434 * associated with probes that were formerly live.
435 */
436static void
437fasttrap_mod_barrier(uint64_t gen)
438{
439	int i;
440
441	if (gen < fasttrap_mod_gen)
442		return;
443
444	fasttrap_mod_gen++;
445
446#ifdef illumos
447	CPU_FOREACH(i) {
448		mutex_enter(&fasttrap_cpuc_pid_lock[i]);
449		mutex_exit(&fasttrap_cpuc_pid_lock[i]);
450	}
451#else
452	rm_wlock(&fasttrap_tp_lock);
453	rm_wunlock(&fasttrap_tp_lock);
454#endif
455}
456
457/*
458 * This function performs asynchronous cleanup of fasttrap providers. The
459 * Solaris implementation of this mechanism use a timeout that's activated in
460 * fasttrap_pid_cleanup(), but this doesn't work in FreeBSD: one may sleep while
461 * holding the DTrace mutexes, but it is unsafe to sleep in a callout handler.
462 * Thus we use a dedicated process to perform the cleanup when requested.
463 */
464/*ARGSUSED*/
465static void
466fasttrap_pid_cleanup_cb(void *data)
467{
468	fasttrap_provider_t **fpp, *fp;
469	fasttrap_bucket_t *bucket;
470	dtrace_provider_id_t provid;
471	int i, later = 0, rval;
472
473	mtx_lock(&fasttrap_cleanup_mtx);
474	while (!fasttrap_cleanup_drain || later > 0) {
475		fasttrap_cleanup_work = 0;
476		mtx_unlock(&fasttrap_cleanup_mtx);
477
478		later = 0;
479
480		/*
481		 * Iterate over all the providers trying to remove the marked
482		 * ones. If a provider is marked but not retired, we just
483		 * have to take a crack at removing it -- it's no big deal if
484		 * we can't.
485		 */
486		for (i = 0; i < fasttrap_provs.fth_nent; i++) {
487			bucket = &fasttrap_provs.fth_table[i];
488			mutex_enter(&bucket->ftb_mtx);
489			fpp = (fasttrap_provider_t **)&bucket->ftb_data;
490
491			while ((fp = *fpp) != NULL) {
492				if (!fp->ftp_marked) {
493					fpp = &fp->ftp_next;
494					continue;
495				}
496
497				mutex_enter(&fp->ftp_mtx);
498
499				/*
500				 * If this provider has consumers actively
501				 * creating probes (ftp_ccount) or is a USDT
502				 * provider (ftp_mcount), we can't unregister
503				 * or even condense.
504				 */
505				if (fp->ftp_ccount != 0 ||
506				    fp->ftp_mcount != 0) {
507					mutex_exit(&fp->ftp_mtx);
508					fp->ftp_marked = 0;
509					continue;
510				}
511
512				if (!fp->ftp_retired || fp->ftp_rcount != 0)
513					fp->ftp_marked = 0;
514
515				mutex_exit(&fp->ftp_mtx);
516
517				/*
518				 * If we successfully unregister this
519				 * provider we can remove it from the hash
520				 * chain and free the memory. If our attempt
521				 * to unregister fails and this is a retired
522				 * provider, increment our flag to try again
523				 * pretty soon. If we've consumed more than
524				 * half of our total permitted number of
525				 * probes call dtrace_condense() to try to
526				 * clean out the unenabled probes.
527				 */
528				provid = fp->ftp_provid;
529				if ((rval = dtrace_unregister(provid)) != 0) {
530					if (fasttrap_total > fasttrap_max / 2)
531						(void) dtrace_condense(provid);
532
533					if (rval == EAGAIN)
534						fp->ftp_marked = 1;
535
536					later += fp->ftp_marked;
537					fpp = &fp->ftp_next;
538				} else {
539					*fpp = fp->ftp_next;
540					fasttrap_provider_free(fp);
541				}
542			}
543			mutex_exit(&bucket->ftb_mtx);
544		}
545		mtx_lock(&fasttrap_cleanup_mtx);
546
547		/*
548		 * If we were unable to retire a provider, try again after a
549		 * second. This situation can occur in certain circumstances
550		 * where providers cannot be unregistered even though they have
551		 * no probes enabled because of an execution of dtrace -l or
552		 * something similar.
553		 */
554		if (later > 0 || fasttrap_cleanup_work ||
555		    fasttrap_cleanup_drain) {
556			mtx_unlock(&fasttrap_cleanup_mtx);
557			pause("ftclean", hz);
558			mtx_lock(&fasttrap_cleanup_mtx);
559		} else
560			mtx_sleep(&fasttrap_cleanup_cv, &fasttrap_cleanup_mtx,
561			    0, "ftcl", 0);
562	}
563
564	/*
565	 * Wake up the thread in fasttrap_unload() now that we're done.
566	 */
567	wakeup(&fasttrap_cleanup_drain);
568	mtx_unlock(&fasttrap_cleanup_mtx);
569
570	kthread_exit();
571}
572
573/*
574 * Activates the asynchronous cleanup mechanism.
575 */
576static void
577fasttrap_pid_cleanup(void)
578{
579
580	mtx_lock(&fasttrap_cleanup_mtx);
581	if (!fasttrap_cleanup_work) {
582		fasttrap_cleanup_work = 1;
583		wakeup(&fasttrap_cleanup_cv);
584	}
585	mtx_unlock(&fasttrap_cleanup_mtx);
586}
587
588/*
589 * This is called from cfork() via dtrace_fasttrap_fork(). The child
590 * process's address space is (roughly) a copy of the parent process's so
591 * we have to remove all the instrumentation we had previously enabled in the
592 * parent.
593 */
594static void
595fasttrap_fork(proc_t *p, proc_t *cp)
596{
597#ifndef illumos
598	fasttrap_scrblock_t *scrblk;
599	fasttrap_proc_t *fprc = NULL;
600#endif
601	pid_t ppid = p->p_pid;
602	int i;
603
604#ifdef illumos
605	ASSERT(curproc == p);
606	ASSERT(p->p_proc_flag & P_PR_LOCK);
607#else
608	PROC_LOCK_ASSERT(p, MA_OWNED);
609#endif
610#ifdef illumos
611	ASSERT(p->p_dtrace_count > 0);
612#else
613	if (p->p_dtrace_helpers) {
614		/*
615		 * dtrace_helpers_duplicate() allocates memory.
616		 */
617		_PHOLD(cp);
618		PROC_UNLOCK(p);
619		PROC_UNLOCK(cp);
620		dtrace_helpers_duplicate(p, cp);
621		PROC_LOCK(cp);
622		PROC_LOCK(p);
623		_PRELE(cp);
624	}
625	/*
626	 * This check is purposely here instead of in kern_fork.c because,
627	 * for legal resons, we cannot include the dtrace_cddl.h header
628	 * inside kern_fork.c and insert if-clause there.
629	 */
630	if (p->p_dtrace_count == 0)
631		return;
632#endif
633	ASSERT(cp->p_dtrace_count == 0);
634
635	/*
636	 * This would be simpler and faster if we maintained per-process
637	 * hash tables of enabled tracepoints. It could, however, potentially
638	 * slow down execution of a tracepoint since we'd need to go
639	 * through two levels of indirection. In the future, we should
640	 * consider either maintaining per-process ancillary lists of
641	 * enabled tracepoints or hanging a pointer to a per-process hash
642	 * table of enabled tracepoints off the proc structure.
643	 */
644
645	/*
646	 * We don't have to worry about the child process disappearing
647	 * because we're in fork().
648	 */
649#ifdef illumos
650	mtx_lock_spin(&cp->p_slock);
651	sprlock_proc(cp);
652	mtx_unlock_spin(&cp->p_slock);
653#else
654	/*
655	 * fasttrap_tracepoint_remove() expects the child process to be
656	 * unlocked and the VM then expects curproc to be unlocked.
657	 */
658	_PHOLD(cp);
659	PROC_UNLOCK(cp);
660	PROC_UNLOCK(p);
661#endif
662
663	/*
664	 * Iterate over every tracepoint looking for ones that belong to the
665	 * parent process, and remove each from the child process.
666	 */
667	for (i = 0; i < fasttrap_tpoints.fth_nent; i++) {
668		fasttrap_tracepoint_t *tp;
669		fasttrap_bucket_t *bucket = &fasttrap_tpoints.fth_table[i];
670
671		mutex_enter(&bucket->ftb_mtx);
672		for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
673			if (tp->ftt_pid == ppid &&
674			    tp->ftt_proc->ftpc_acount != 0) {
675				int ret = fasttrap_tracepoint_remove(cp, tp);
676				ASSERT(ret == 0);
677
678				/*
679				 * The count of active providers can only be
680				 * decremented (i.e. to zero) during exec,
681				 * exit, and removal of a meta provider so it
682				 * should be impossible to drop the count
683				 * mid-fork.
684				 */
685				ASSERT(tp->ftt_proc->ftpc_acount != 0);
686#ifndef illumos
687				fprc = tp->ftt_proc;
688#endif
689			}
690		}
691		mutex_exit(&bucket->ftb_mtx);
692
693#ifndef illumos
694		/*
695		 * Unmap any scratch space inherited from the parent's address
696		 * space.
697		 */
698		if (fprc != NULL) {
699			mutex_enter(&fprc->ftpc_mtx);
700			LIST_FOREACH(scrblk, &fprc->ftpc_scrblks, ftsb_next) {
701				vm_map_remove(&cp->p_vmspace->vm_map,
702				    scrblk->ftsb_addr,
703				    scrblk->ftsb_addr + FASTTRAP_SCRBLOCK_SIZE);
704			}
705			mutex_exit(&fprc->ftpc_mtx);
706		}
707#endif
708	}
709
710#ifdef illumos
711	mutex_enter(&cp->p_lock);
712	sprunlock(cp);
713#else
714	PROC_LOCK(p);
715	PROC_LOCK(cp);
716	_PRELE(cp);
717#endif
718}
719
720/*
721 * This is called from proc_exit() or from exec_common() if p_dtrace_probes
722 * is set on the proc structure to indicate that there is a pid provider
723 * associated with this process.
724 */
725static void
726fasttrap_exec_exit(proc_t *p)
727{
728#ifndef illumos
729	struct thread *td;
730#endif
731
732#ifdef illumos
733	ASSERT(p == curproc);
734#else
735	PROC_LOCK_ASSERT(p, MA_OWNED);
736	_PHOLD(p);
737	/*
738	 * Since struct threads may be recycled, we cannot rely on t_dtrace_sscr
739	 * fields to be zeroed by kdtrace_thread_ctor. Thus we must zero it
740	 * ourselves when a process exits.
741	 */
742	FOREACH_THREAD_IN_PROC(p, td)
743		td->t_dtrace_sscr = NULL;
744	PROC_UNLOCK(p);
745#endif
746
747	/*
748	 * We clean up the pid provider for this process here; user-land
749	 * static probes are handled by the meta-provider remove entry point.
750	 */
751	fasttrap_provider_retire(p->p_pid, FASTTRAP_PID_NAME, 0);
752#ifndef illumos
753	if (p->p_dtrace_helpers)
754		dtrace_helpers_destroy(p);
755	PROC_LOCK(p);
756	_PRELE(p);
757#endif
758}
759
760
761/*ARGSUSED*/
762static void
763fasttrap_pid_provide(void *arg, dtrace_probedesc_t *desc)
764{
765	/*
766	 * There are no "default" pid probes.
767	 */
768}
769
770static int
771fasttrap_tracepoint_enable(proc_t *p, fasttrap_probe_t *probe, uint_t index)
772{
773	fasttrap_tracepoint_t *tp, *new_tp = NULL;
774	fasttrap_bucket_t *bucket;
775	fasttrap_id_t *id;
776	pid_t pid;
777	uintptr_t pc;
778
779	ASSERT(index < probe->ftp_ntps);
780
781	pid = probe->ftp_pid;
782	pc = probe->ftp_tps[index].fit_tp->ftt_pc;
783	id = &probe->ftp_tps[index].fit_id;
784
785	ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
786
787#ifdef illumos
788	ASSERT(!(p->p_flag & SVFORK));
789#endif
790
791	/*
792	 * Before we make any modifications, make sure we've imposed a barrier
793	 * on the generation in which this probe was last modified.
794	 */
795	fasttrap_mod_barrier(probe->ftp_gen);
796
797	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
798
799	/*
800	 * If the tracepoint has already been enabled, just add our id to the
801	 * list of interested probes. This may be our second time through
802	 * this path in which case we'll have constructed the tracepoint we'd
803	 * like to install. If we can't find a match, and have an allocated
804	 * tracepoint ready to go, enable that one now.
805	 *
806	 * A tracepoint whose process is defunct is also considered defunct.
807	 */
808again:
809	mutex_enter(&bucket->ftb_mtx);
810	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
811		/*
812		 * Note that it's safe to access the active count on the
813		 * associated proc structure because we know that at least one
814		 * provider (this one) will still be around throughout this
815		 * operation.
816		 */
817		if (tp->ftt_pid != pid || tp->ftt_pc != pc ||
818		    tp->ftt_proc->ftpc_acount == 0)
819			continue;
820
821		/*
822		 * Now that we've found a matching tracepoint, it would be
823		 * a decent idea to confirm that the tracepoint is still
824		 * enabled and the trap instruction hasn't been overwritten.
825		 * Since this is a little hairy, we'll punt for now.
826		 */
827
828		/*
829		 * This can't be the first interested probe. We don't have
830		 * to worry about another thread being in the midst of
831		 * deleting this tracepoint (which would be the only valid
832		 * reason for a tracepoint to have no interested probes)
833		 * since we're holding P_PR_LOCK for this process.
834		 */
835		ASSERT(tp->ftt_ids != NULL || tp->ftt_retids != NULL);
836
837		switch (id->fti_ptype) {
838		case DTFTP_ENTRY:
839		case DTFTP_OFFSETS:
840		case DTFTP_IS_ENABLED:
841			id->fti_next = tp->ftt_ids;
842			membar_producer();
843			tp->ftt_ids = id;
844			membar_producer();
845			break;
846
847		case DTFTP_RETURN:
848		case DTFTP_POST_OFFSETS:
849			id->fti_next = tp->ftt_retids;
850			membar_producer();
851			tp->ftt_retids = id;
852			membar_producer();
853			break;
854
855		default:
856			ASSERT(0);
857		}
858
859		mutex_exit(&bucket->ftb_mtx);
860
861		if (new_tp != NULL) {
862			new_tp->ftt_ids = NULL;
863			new_tp->ftt_retids = NULL;
864		}
865
866		return (0);
867	}
868
869	/*
870	 * If we have a good tracepoint ready to go, install it now while
871	 * we have the lock held and no one can screw with us.
872	 */
873	if (new_tp != NULL) {
874		int rc = 0;
875
876		new_tp->ftt_next = bucket->ftb_data;
877		membar_producer();
878		bucket->ftb_data = new_tp;
879		membar_producer();
880		mutex_exit(&bucket->ftb_mtx);
881
882		/*
883		 * Activate the tracepoint in the ISA-specific manner.
884		 * If this fails, we need to report the failure, but
885		 * indicate that this tracepoint must still be disabled
886		 * by calling fasttrap_tracepoint_disable().
887		 */
888		if (fasttrap_tracepoint_install(p, new_tp) != 0)
889			rc = FASTTRAP_ENABLE_PARTIAL;
890
891		/*
892		 * Increment the count of the number of tracepoints active in
893		 * the victim process.
894		 */
895#ifdef illumos
896		ASSERT(p->p_proc_flag & P_PR_LOCK);
897#endif
898		p->p_dtrace_count++;
899
900		return (rc);
901	}
902
903	mutex_exit(&bucket->ftb_mtx);
904
905	/*
906	 * Initialize the tracepoint that's been preallocated with the probe.
907	 */
908	new_tp = probe->ftp_tps[index].fit_tp;
909
910	ASSERT(new_tp->ftt_pid == pid);
911	ASSERT(new_tp->ftt_pc == pc);
912	ASSERT(new_tp->ftt_proc == probe->ftp_prov->ftp_proc);
913	ASSERT(new_tp->ftt_ids == NULL);
914	ASSERT(new_tp->ftt_retids == NULL);
915
916	switch (id->fti_ptype) {
917	case DTFTP_ENTRY:
918	case DTFTP_OFFSETS:
919	case DTFTP_IS_ENABLED:
920		id->fti_next = NULL;
921		new_tp->ftt_ids = id;
922		break;
923
924	case DTFTP_RETURN:
925	case DTFTP_POST_OFFSETS:
926		id->fti_next = NULL;
927		new_tp->ftt_retids = id;
928		break;
929
930	default:
931		ASSERT(0);
932	}
933
934#ifdef __FreeBSD__
935	if (SV_PROC_FLAG(p, SV_LP64))
936		p->p_model = DATAMODEL_LP64;
937	else
938		p->p_model = DATAMODEL_ILP32;
939#endif
940
941	/*
942	 * If the ISA-dependent initialization goes to plan, go back to the
943	 * beginning and try to install this freshly made tracepoint.
944	 */
945	if (fasttrap_tracepoint_init(p, new_tp, pc, id->fti_ptype) == 0)
946		goto again;
947
948	new_tp->ftt_ids = NULL;
949	new_tp->ftt_retids = NULL;
950
951	return (FASTTRAP_ENABLE_FAIL);
952}
953
954static void
955fasttrap_tracepoint_disable(proc_t *p, fasttrap_probe_t *probe, uint_t index)
956{
957	fasttrap_bucket_t *bucket;
958	fasttrap_provider_t *provider = probe->ftp_prov;
959	fasttrap_tracepoint_t **pp, *tp;
960	fasttrap_id_t *id, **idp = NULL;
961	pid_t pid;
962	uintptr_t pc;
963
964	ASSERT(index < probe->ftp_ntps);
965
966	pid = probe->ftp_pid;
967	pc = probe->ftp_tps[index].fit_tp->ftt_pc;
968	id = &probe->ftp_tps[index].fit_id;
969
970	ASSERT(probe->ftp_tps[index].fit_tp->ftt_pid == pid);
971
972	/*
973	 * Find the tracepoint and make sure that our id is one of the
974	 * ones registered with it.
975	 */
976	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
977	mutex_enter(&bucket->ftb_mtx);
978	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
979		if (tp->ftt_pid == pid && tp->ftt_pc == pc &&
980		    tp->ftt_proc == provider->ftp_proc)
981			break;
982	}
983
984	/*
985	 * If we somehow lost this tracepoint, we're in a world of hurt.
986	 */
987	ASSERT(tp != NULL);
988
989	switch (id->fti_ptype) {
990	case DTFTP_ENTRY:
991	case DTFTP_OFFSETS:
992	case DTFTP_IS_ENABLED:
993		ASSERT(tp->ftt_ids != NULL);
994		idp = &tp->ftt_ids;
995		break;
996
997	case DTFTP_RETURN:
998	case DTFTP_POST_OFFSETS:
999		ASSERT(tp->ftt_retids != NULL);
1000		idp = &tp->ftt_retids;
1001		break;
1002
1003	default:
1004		ASSERT(0);
1005	}
1006
1007	while ((*idp)->fti_probe != probe) {
1008		idp = &(*idp)->fti_next;
1009		ASSERT(*idp != NULL);
1010	}
1011
1012	id = *idp;
1013	*idp = id->fti_next;
1014	membar_producer();
1015
1016	ASSERT(id->fti_probe == probe);
1017
1018	/*
1019	 * If there are other registered enablings of this tracepoint, we're
1020	 * all done, but if this was the last probe assocated with this
1021	 * this tracepoint, we need to remove and free it.
1022	 */
1023	if (tp->ftt_ids != NULL || tp->ftt_retids != NULL) {
1024
1025		/*
1026		 * If the current probe's tracepoint is in use, swap it
1027		 * for an unused tracepoint.
1028		 */
1029		if (tp == probe->ftp_tps[index].fit_tp) {
1030			fasttrap_probe_t *tmp_probe;
1031			fasttrap_tracepoint_t **tmp_tp;
1032			uint_t tmp_index;
1033
1034			if (tp->ftt_ids != NULL) {
1035				tmp_probe = tp->ftt_ids->fti_probe;
1036				/* LINTED - alignment */
1037				tmp_index = FASTTRAP_ID_INDEX(tp->ftt_ids);
1038				tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
1039			} else {
1040				tmp_probe = tp->ftt_retids->fti_probe;
1041				/* LINTED - alignment */
1042				tmp_index = FASTTRAP_ID_INDEX(tp->ftt_retids);
1043				tmp_tp = &tmp_probe->ftp_tps[tmp_index].fit_tp;
1044			}
1045
1046			ASSERT(*tmp_tp != NULL);
1047			ASSERT(*tmp_tp != probe->ftp_tps[index].fit_tp);
1048			ASSERT((*tmp_tp)->ftt_ids == NULL);
1049			ASSERT((*tmp_tp)->ftt_retids == NULL);
1050
1051			probe->ftp_tps[index].fit_tp = *tmp_tp;
1052			*tmp_tp = tp;
1053		}
1054
1055		mutex_exit(&bucket->ftb_mtx);
1056
1057		/*
1058		 * Tag the modified probe with the generation in which it was
1059		 * changed.
1060		 */
1061		probe->ftp_gen = fasttrap_mod_gen;
1062		return;
1063	}
1064
1065	mutex_exit(&bucket->ftb_mtx);
1066
1067	/*
1068	 * We can't safely remove the tracepoint from the set of active
1069	 * tracepoints until we've actually removed the fasttrap instruction
1070	 * from the process's text. We can, however, operate on this
1071	 * tracepoint secure in the knowledge that no other thread is going to
1072	 * be looking at it since we hold P_PR_LOCK on the process if it's
1073	 * live or we hold the provider lock on the process if it's dead and
1074	 * gone.
1075	 */
1076
1077	/*
1078	 * We only need to remove the actual instruction if we're looking
1079	 * at an existing process
1080	 */
1081	if (p != NULL) {
1082		/*
1083		 * If we fail to restore the instruction we need to kill
1084		 * this process since it's in a completely unrecoverable
1085		 * state.
1086		 */
1087		if (fasttrap_tracepoint_remove(p, tp) != 0)
1088			fasttrap_sigtrap(p, NULL, pc);
1089
1090		/*
1091		 * Decrement the count of the number of tracepoints active
1092		 * in the victim process.
1093		 */
1094#ifdef illumos
1095		ASSERT(p->p_proc_flag & P_PR_LOCK);
1096#endif
1097		p->p_dtrace_count--;
1098	}
1099
1100	/*
1101	 * Remove the probe from the hash table of active tracepoints.
1102	 */
1103	mutex_enter(&bucket->ftb_mtx);
1104	pp = (fasttrap_tracepoint_t **)&bucket->ftb_data;
1105	ASSERT(*pp != NULL);
1106	while (*pp != tp) {
1107		pp = &(*pp)->ftt_next;
1108		ASSERT(*pp != NULL);
1109	}
1110
1111	*pp = tp->ftt_next;
1112	membar_producer();
1113
1114	mutex_exit(&bucket->ftb_mtx);
1115
1116	/*
1117	 * Tag the modified probe with the generation in which it was changed.
1118	 */
1119	probe->ftp_gen = fasttrap_mod_gen;
1120}
1121
1122static void
1123fasttrap_enable_callbacks(void)
1124{
1125	/*
1126	 * We don't have to play the rw lock game here because we're
1127	 * providing something rather than taking something away --
1128	 * we can be sure that no threads have tried to follow this
1129	 * function pointer yet.
1130	 */
1131	mutex_enter(&fasttrap_count_mtx);
1132	if (fasttrap_pid_count == 0) {
1133		ASSERT(dtrace_pid_probe_ptr == NULL);
1134		ASSERT(dtrace_return_probe_ptr == NULL);
1135		dtrace_pid_probe_ptr = &fasttrap_pid_probe;
1136		dtrace_return_probe_ptr = &fasttrap_return_probe;
1137	}
1138	ASSERT(dtrace_pid_probe_ptr == &fasttrap_pid_probe);
1139	ASSERT(dtrace_return_probe_ptr == &fasttrap_return_probe);
1140	fasttrap_pid_count++;
1141	mutex_exit(&fasttrap_count_mtx);
1142}
1143
1144static void
1145fasttrap_disable_callbacks(void)
1146{
1147#ifdef illumos
1148	ASSERT(MUTEX_HELD(&cpu_lock));
1149#endif
1150
1151
1152	mutex_enter(&fasttrap_count_mtx);
1153	ASSERT(fasttrap_pid_count > 0);
1154	fasttrap_pid_count--;
1155	if (fasttrap_pid_count == 0) {
1156#ifdef illumos
1157		cpu_t *cur, *cpu = CPU;
1158
1159		for (cur = cpu->cpu_next_onln; cur != cpu;
1160		    cur = cur->cpu_next_onln) {
1161			rw_enter(&cur->cpu_ft_lock, RW_WRITER);
1162		}
1163#endif
1164		dtrace_pid_probe_ptr = NULL;
1165		dtrace_return_probe_ptr = NULL;
1166#ifdef illumos
1167		for (cur = cpu->cpu_next_onln; cur != cpu;
1168		    cur = cur->cpu_next_onln) {
1169			rw_exit(&cur->cpu_ft_lock);
1170		}
1171#endif
1172	}
1173	mutex_exit(&fasttrap_count_mtx);
1174}
1175
1176/*ARGSUSED*/
1177static void
1178fasttrap_pid_enable(void *arg, dtrace_id_t id, void *parg)
1179{
1180	fasttrap_probe_t *probe = parg;
1181	proc_t *p = NULL;
1182	int i, rc;
1183
1184	ASSERT(probe != NULL);
1185	ASSERT(!probe->ftp_enabled);
1186	ASSERT(id == probe->ftp_id);
1187#ifdef illumos
1188	ASSERT(MUTEX_HELD(&cpu_lock));
1189#endif
1190
1191	/*
1192	 * Increment the count of enabled probes on this probe's provider;
1193	 * the provider can't go away while the probe still exists. We
1194	 * must increment this even if we aren't able to properly enable
1195	 * this probe.
1196	 */
1197	mutex_enter(&probe->ftp_prov->ftp_mtx);
1198	probe->ftp_prov->ftp_rcount++;
1199	mutex_exit(&probe->ftp_prov->ftp_mtx);
1200
1201	/*
1202	 * If this probe's provider is retired (meaning it was valid in a
1203	 * previously exec'ed incarnation of this address space), bail out. The
1204	 * provider can't go away while we're in this code path.
1205	 */
1206	if (probe->ftp_prov->ftp_retired)
1207		return;
1208
1209	/*
1210	 * If we can't find the process, it may be that we're in the context of
1211	 * a fork in which the traced process is being born and we're copying
1212	 * USDT probes. Otherwise, the process is gone so bail.
1213	 */
1214#ifdef illumos
1215	if ((p = sprlock(probe->ftp_pid)) == NULL) {
1216		if ((curproc->p_flag & SFORKING) == 0)
1217			return;
1218
1219		mutex_enter(&pidlock);
1220		p = prfind(probe->ftp_pid);
1221
1222		if (p == NULL) {
1223			/*
1224			 * So it's not that the target process is being born,
1225			 * it's that it isn't there at all (and we simply
1226			 * happen to be forking).  Anyway, we know that the
1227			 * target is definitely gone, so bail out.
1228			 */
1229			mutex_exit(&pidlock);
1230			return (0);
1231		}
1232
1233		/*
1234		 * Confirm that curproc is indeed forking the process in which
1235		 * we're trying to enable probes.
1236		 */
1237		ASSERT(p->p_parent == curproc);
1238		ASSERT(p->p_stat == SIDL);
1239
1240		mutex_enter(&p->p_lock);
1241		mutex_exit(&pidlock);
1242
1243		sprlock_proc(p);
1244	}
1245
1246	ASSERT(!(p->p_flag & SVFORK));
1247	mutex_exit(&p->p_lock);
1248#else
1249	if (pget(probe->ftp_pid, PGET_HOLD | PGET_NOTWEXIT, &p) != 0)
1250		return;
1251#endif
1252
1253	/*
1254	 * We have to enable the trap entry point before any user threads have
1255	 * the chance to execute the trap instruction we're about to place
1256	 * in their process's text.
1257	 */
1258	fasttrap_enable_callbacks();
1259
1260	/*
1261	 * Enable all the tracepoints and add this probe's id to each
1262	 * tracepoint's list of active probes.
1263	 */
1264	for (i = 0; i < probe->ftp_ntps; i++) {
1265		if ((rc = fasttrap_tracepoint_enable(p, probe, i)) != 0) {
1266			/*
1267			 * If enabling the tracepoint failed completely,
1268			 * we don't have to disable it; if the failure
1269			 * was only partial we must disable it.
1270			 */
1271			if (rc == FASTTRAP_ENABLE_FAIL)
1272				i--;
1273			else
1274				ASSERT(rc == FASTTRAP_ENABLE_PARTIAL);
1275
1276			/*
1277			 * Back up and pull out all the tracepoints we've
1278			 * created so far for this probe.
1279			 */
1280			while (i >= 0) {
1281				fasttrap_tracepoint_disable(p, probe, i);
1282				i--;
1283			}
1284
1285#ifdef illumos
1286			mutex_enter(&p->p_lock);
1287			sprunlock(p);
1288#else
1289			PRELE(p);
1290#endif
1291
1292			/*
1293			 * Since we're not actually enabling this probe,
1294			 * drop our reference on the trap table entry.
1295			 */
1296			fasttrap_disable_callbacks();
1297			return;
1298		}
1299	}
1300#ifdef illumos
1301	mutex_enter(&p->p_lock);
1302	sprunlock(p);
1303#else
1304	PRELE(p);
1305#endif
1306
1307	probe->ftp_enabled = 1;
1308}
1309
1310/*ARGSUSED*/
1311static void
1312fasttrap_pid_disable(void *arg, dtrace_id_t id, void *parg)
1313{
1314	fasttrap_probe_t *probe = parg;
1315	fasttrap_provider_t *provider = probe->ftp_prov;
1316	proc_t *p;
1317	int i, whack = 0;
1318
1319	ASSERT(id == probe->ftp_id);
1320
1321	mutex_enter(&provider->ftp_mtx);
1322
1323	/*
1324	 * We won't be able to acquire a /proc-esque lock on the process
1325	 * iff the process is dead and gone. In this case, we rely on the
1326	 * provider lock as a point of mutual exclusion to prevent other
1327	 * DTrace consumers from disabling this probe.
1328	 */
1329	if (pget(probe->ftp_pid, PGET_HOLD | PGET_NOTWEXIT, &p) != 0)
1330		p = NULL;
1331
1332	/*
1333	 * Disable all the associated tracepoints (for fully enabled probes).
1334	 */
1335	if (probe->ftp_enabled) {
1336		for (i = 0; i < probe->ftp_ntps; i++) {
1337			fasttrap_tracepoint_disable(p, probe, i);
1338		}
1339	}
1340
1341	ASSERT(provider->ftp_rcount > 0);
1342	provider->ftp_rcount--;
1343
1344	if (p != NULL) {
1345		/*
1346		 * Even though we may not be able to remove it entirely, we
1347		 * mark this retired provider to get a chance to remove some
1348		 * of the associated probes.
1349		 */
1350		if (provider->ftp_retired && !provider->ftp_marked)
1351			whack = provider->ftp_marked = 1;
1352		mutex_exit(&provider->ftp_mtx);
1353	} else {
1354		/*
1355		 * If the process is dead, we're just waiting for the
1356		 * last probe to be disabled to be able to free it.
1357		 */
1358		if (provider->ftp_rcount == 0 && !provider->ftp_marked)
1359			whack = provider->ftp_marked = 1;
1360		mutex_exit(&provider->ftp_mtx);
1361	}
1362
1363	if (whack)
1364		fasttrap_pid_cleanup();
1365
1366#ifdef __FreeBSD__
1367	if (p != NULL)
1368		PRELE(p);
1369#endif
1370	if (!probe->ftp_enabled)
1371		return;
1372
1373	probe->ftp_enabled = 0;
1374
1375#ifdef illumos
1376	ASSERT(MUTEX_HELD(&cpu_lock));
1377#endif
1378	fasttrap_disable_callbacks();
1379}
1380
1381/*ARGSUSED*/
1382static void
1383fasttrap_pid_getargdesc(void *arg, dtrace_id_t id, void *parg,
1384    dtrace_argdesc_t *desc)
1385{
1386	fasttrap_probe_t *probe = parg;
1387	char *str;
1388	int i, ndx;
1389
1390	desc->dtargd_native[0] = '\0';
1391	desc->dtargd_xlate[0] = '\0';
1392
1393	if (probe->ftp_prov->ftp_retired != 0 ||
1394	    desc->dtargd_ndx >= probe->ftp_nargs) {
1395		desc->dtargd_ndx = DTRACE_ARGNONE;
1396		return;
1397	}
1398
1399	ndx = (probe->ftp_argmap != NULL) ?
1400	    probe->ftp_argmap[desc->dtargd_ndx] : desc->dtargd_ndx;
1401
1402	str = probe->ftp_ntypes;
1403	for (i = 0; i < ndx; i++) {
1404		str += strlen(str) + 1;
1405	}
1406
1407	ASSERT(strlen(str + 1) < sizeof (desc->dtargd_native));
1408	(void) strcpy(desc->dtargd_native, str);
1409
1410	if (probe->ftp_xtypes == NULL)
1411		return;
1412
1413	str = probe->ftp_xtypes;
1414	for (i = 0; i < desc->dtargd_ndx; i++) {
1415		str += strlen(str) + 1;
1416	}
1417
1418	ASSERT(strlen(str + 1) < sizeof (desc->dtargd_xlate));
1419	(void) strcpy(desc->dtargd_xlate, str);
1420}
1421
1422/*ARGSUSED*/
1423static void
1424fasttrap_pid_destroy(void *arg, dtrace_id_t id, void *parg)
1425{
1426	fasttrap_probe_t *probe = parg;
1427	int i;
1428	size_t size;
1429
1430	ASSERT(probe != NULL);
1431	ASSERT(!probe->ftp_enabled);
1432	ASSERT(fasttrap_total >= probe->ftp_ntps);
1433
1434	atomic_add_32(&fasttrap_total, -probe->ftp_ntps);
1435	size = offsetof(fasttrap_probe_t, ftp_tps[probe->ftp_ntps]);
1436
1437	if (probe->ftp_gen + 1 >= fasttrap_mod_gen)
1438		fasttrap_mod_barrier(probe->ftp_gen);
1439
1440	for (i = 0; i < probe->ftp_ntps; i++) {
1441		kmem_free(probe->ftp_tps[i].fit_tp,
1442		    sizeof (fasttrap_tracepoint_t));
1443	}
1444
1445	kmem_free(probe, size);
1446}
1447
1448
1449static const dtrace_pattr_t pid_attr = {
1450{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
1451{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
1452{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
1453{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
1454{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
1455};
1456
1457static dtrace_pops_t pid_pops = {
1458	fasttrap_pid_provide,
1459	NULL,
1460	fasttrap_pid_enable,
1461	fasttrap_pid_disable,
1462	NULL,
1463	NULL,
1464	fasttrap_pid_getargdesc,
1465	fasttrap_pid_getarg,
1466	NULL,
1467	fasttrap_pid_destroy
1468};
1469
1470static dtrace_pops_t usdt_pops = {
1471	fasttrap_pid_provide,
1472	NULL,
1473	fasttrap_pid_enable,
1474	fasttrap_pid_disable,
1475	NULL,
1476	NULL,
1477	fasttrap_pid_getargdesc,
1478	fasttrap_usdt_getarg,
1479	NULL,
1480	fasttrap_pid_destroy
1481};
1482
1483static fasttrap_proc_t *
1484fasttrap_proc_lookup(pid_t pid)
1485{
1486	fasttrap_bucket_t *bucket;
1487	fasttrap_proc_t *fprc, *new_fprc;
1488
1489
1490	bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)];
1491	mutex_enter(&bucket->ftb_mtx);
1492
1493	for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
1494		if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) {
1495			mutex_enter(&fprc->ftpc_mtx);
1496			mutex_exit(&bucket->ftb_mtx);
1497			fprc->ftpc_rcount++;
1498			atomic_inc_64(&fprc->ftpc_acount);
1499			ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount);
1500			mutex_exit(&fprc->ftpc_mtx);
1501
1502			return (fprc);
1503		}
1504	}
1505
1506	/*
1507	 * Drop the bucket lock so we don't try to perform a sleeping
1508	 * allocation under it.
1509	 */
1510	mutex_exit(&bucket->ftb_mtx);
1511
1512	new_fprc = kmem_zalloc(sizeof (fasttrap_proc_t), KM_SLEEP);
1513	new_fprc->ftpc_pid = pid;
1514	new_fprc->ftpc_rcount = 1;
1515	new_fprc->ftpc_acount = 1;
1516#ifndef illumos
1517	mutex_init(&new_fprc->ftpc_mtx, "fasttrap proc mtx", MUTEX_DEFAULT,
1518	    NULL);
1519#endif
1520
1521	mutex_enter(&bucket->ftb_mtx);
1522
1523	/*
1524	 * Take another lap through the list to make sure a proc hasn't
1525	 * been created for this pid while we weren't under the bucket lock.
1526	 */
1527	for (fprc = bucket->ftb_data; fprc != NULL; fprc = fprc->ftpc_next) {
1528		if (fprc->ftpc_pid == pid && fprc->ftpc_acount != 0) {
1529			mutex_enter(&fprc->ftpc_mtx);
1530			mutex_exit(&bucket->ftb_mtx);
1531			fprc->ftpc_rcount++;
1532			atomic_inc_64(&fprc->ftpc_acount);
1533			ASSERT(fprc->ftpc_acount <= fprc->ftpc_rcount);
1534			mutex_exit(&fprc->ftpc_mtx);
1535
1536			kmem_free(new_fprc, sizeof (fasttrap_proc_t));
1537
1538			return (fprc);
1539		}
1540	}
1541
1542	new_fprc->ftpc_next = bucket->ftb_data;
1543	bucket->ftb_data = new_fprc;
1544
1545	mutex_exit(&bucket->ftb_mtx);
1546
1547	return (new_fprc);
1548}
1549
1550static void
1551fasttrap_proc_release(fasttrap_proc_t *proc)
1552{
1553	fasttrap_bucket_t *bucket;
1554	fasttrap_proc_t *fprc, **fprcp;
1555	pid_t pid = proc->ftpc_pid;
1556#ifndef illumos
1557	fasttrap_scrblock_t *scrblk, *scrblktmp;
1558	fasttrap_scrspace_t *scrspc, *scrspctmp;
1559	struct proc *p;
1560	struct thread *td;
1561#endif
1562
1563	mutex_enter(&proc->ftpc_mtx);
1564
1565	ASSERT(proc->ftpc_rcount != 0);
1566	ASSERT(proc->ftpc_acount <= proc->ftpc_rcount);
1567
1568	if (--proc->ftpc_rcount != 0) {
1569		mutex_exit(&proc->ftpc_mtx);
1570		return;
1571	}
1572
1573#ifndef illumos
1574	/*
1575	 * Free all structures used to manage per-thread scratch space.
1576	 */
1577	LIST_FOREACH_SAFE(scrblk, &proc->ftpc_scrblks, ftsb_next,
1578	    scrblktmp) {
1579		LIST_REMOVE(scrblk, ftsb_next);
1580		free(scrblk, M_SOLARIS);
1581	}
1582	LIST_FOREACH_SAFE(scrspc, &proc->ftpc_fscr, ftss_next, scrspctmp) {
1583		LIST_REMOVE(scrspc, ftss_next);
1584		free(scrspc, M_SOLARIS);
1585	}
1586	LIST_FOREACH_SAFE(scrspc, &proc->ftpc_ascr, ftss_next, scrspctmp) {
1587		LIST_REMOVE(scrspc, ftss_next);
1588		free(scrspc, M_SOLARIS);
1589	}
1590
1591	if ((p = pfind(pid)) != NULL) {
1592		FOREACH_THREAD_IN_PROC(p, td)
1593			td->t_dtrace_sscr = NULL;
1594		PROC_UNLOCK(p);
1595	}
1596#endif
1597
1598	mutex_exit(&proc->ftpc_mtx);
1599
1600	/*
1601	 * There should definitely be no live providers associated with this
1602	 * process at this point.
1603	 */
1604	ASSERT(proc->ftpc_acount == 0);
1605
1606	bucket = &fasttrap_procs.fth_table[FASTTRAP_PROCS_INDEX(pid)];
1607	mutex_enter(&bucket->ftb_mtx);
1608
1609	fprcp = (fasttrap_proc_t **)&bucket->ftb_data;
1610	while ((fprc = *fprcp) != NULL) {
1611		if (fprc == proc)
1612			break;
1613
1614		fprcp = &fprc->ftpc_next;
1615	}
1616
1617	/*
1618	 * Something strange has happened if we can't find the proc.
1619	 */
1620	ASSERT(fprc != NULL);
1621
1622	*fprcp = fprc->ftpc_next;
1623
1624	mutex_exit(&bucket->ftb_mtx);
1625
1626	kmem_free(fprc, sizeof (fasttrap_proc_t));
1627}
1628
1629/*
1630 * Lookup a fasttrap-managed provider based on its name and associated pid.
1631 * If the pattr argument is non-NULL, this function instantiates the provider
1632 * if it doesn't exist otherwise it returns NULL. The provider is returned
1633 * with its lock held.
1634 */
1635static fasttrap_provider_t *
1636fasttrap_provider_lookup(pid_t pid, const char *name,
1637    const dtrace_pattr_t *pattr)
1638{
1639	fasttrap_provider_t *fp, *new_fp = NULL;
1640	fasttrap_bucket_t *bucket;
1641	char provname[DTRACE_PROVNAMELEN];
1642	proc_t *p;
1643	cred_t *cred;
1644
1645	ASSERT(strlen(name) < sizeof (fp->ftp_name));
1646	ASSERT(pattr != NULL);
1647
1648	bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)];
1649	mutex_enter(&bucket->ftb_mtx);
1650
1651	/*
1652	 * Take a lap through the list and return the match if we find it.
1653	 */
1654	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
1655		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
1656		    !fp->ftp_retired) {
1657			mutex_enter(&fp->ftp_mtx);
1658			mutex_exit(&bucket->ftb_mtx);
1659			return (fp);
1660		}
1661	}
1662
1663	/*
1664	 * Drop the bucket lock so we don't try to perform a sleeping
1665	 * allocation under it.
1666	 */
1667	mutex_exit(&bucket->ftb_mtx);
1668
1669	/*
1670	 * Make sure the process exists, isn't a child created as the result
1671	 * of a vfork(2), and isn't a zombie (but may be in fork).
1672	 */
1673	if ((p = pfind(pid)) == NULL)
1674		return (NULL);
1675
1676	/*
1677	 * Increment p_dtrace_probes so that the process knows to inform us
1678	 * when it exits or execs. fasttrap_provider_free() decrements this
1679	 * when we're done with this provider.
1680	 */
1681	p->p_dtrace_probes++;
1682
1683	/*
1684	 * Grab the credentials for this process so we have
1685	 * something to pass to dtrace_register().
1686	 */
1687	PROC_LOCK_ASSERT(p, MA_OWNED);
1688	crhold(p->p_ucred);
1689	cred = p->p_ucred;
1690	PROC_UNLOCK(p);
1691
1692	new_fp = kmem_zalloc(sizeof (fasttrap_provider_t), KM_SLEEP);
1693	new_fp->ftp_pid = pid;
1694	new_fp->ftp_proc = fasttrap_proc_lookup(pid);
1695#ifndef illumos
1696	mutex_init(&new_fp->ftp_mtx, "provider mtx", MUTEX_DEFAULT, NULL);
1697	mutex_init(&new_fp->ftp_cmtx, "lock on creating", MUTEX_DEFAULT, NULL);
1698#endif
1699
1700	ASSERT(new_fp->ftp_proc != NULL);
1701
1702	mutex_enter(&bucket->ftb_mtx);
1703
1704	/*
1705	 * Take another lap through the list to make sure a provider hasn't
1706	 * been created for this pid while we weren't under the bucket lock.
1707	 */
1708	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
1709		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
1710		    !fp->ftp_retired) {
1711			mutex_enter(&fp->ftp_mtx);
1712			mutex_exit(&bucket->ftb_mtx);
1713			fasttrap_provider_free(new_fp);
1714			crfree(cred);
1715			return (fp);
1716		}
1717	}
1718
1719	(void) strcpy(new_fp->ftp_name, name);
1720
1721	/*
1722	 * Fail and return NULL if either the provider name is too long
1723	 * or we fail to register this new provider with the DTrace
1724	 * framework. Note that this is the only place we ever construct
1725	 * the full provider name -- we keep it in pieces in the provider
1726	 * structure.
1727	 */
1728	if (snprintf(provname, sizeof (provname), "%s%u", name, (uint_t)pid) >=
1729	    sizeof (provname) ||
1730	    dtrace_register(provname, pattr,
1731	    DTRACE_PRIV_PROC | DTRACE_PRIV_OWNER | DTRACE_PRIV_ZONEOWNER, cred,
1732	    pattr == &pid_attr ? &pid_pops : &usdt_pops, new_fp,
1733	    &new_fp->ftp_provid) != 0) {
1734		mutex_exit(&bucket->ftb_mtx);
1735		fasttrap_provider_free(new_fp);
1736		crfree(cred);
1737		return (NULL);
1738	}
1739
1740	new_fp->ftp_next = bucket->ftb_data;
1741	bucket->ftb_data = new_fp;
1742
1743	mutex_enter(&new_fp->ftp_mtx);
1744	mutex_exit(&bucket->ftb_mtx);
1745
1746	crfree(cred);
1747	return (new_fp);
1748}
1749
1750static void
1751fasttrap_provider_free(fasttrap_provider_t *provider)
1752{
1753	pid_t pid = provider->ftp_pid;
1754	proc_t *p;
1755
1756	/*
1757	 * There need to be no associated enabled probes, no consumers
1758	 * creating probes, and no meta providers referencing this provider.
1759	 */
1760	ASSERT(provider->ftp_rcount == 0);
1761	ASSERT(provider->ftp_ccount == 0);
1762	ASSERT(provider->ftp_mcount == 0);
1763
1764	/*
1765	 * If this provider hasn't been retired, we need to explicitly drop the
1766	 * count of active providers on the associated process structure.
1767	 */
1768	if (!provider->ftp_retired) {
1769		atomic_dec_64(&provider->ftp_proc->ftpc_acount);
1770		ASSERT(provider->ftp_proc->ftpc_acount <
1771		    provider->ftp_proc->ftpc_rcount);
1772	}
1773
1774	fasttrap_proc_release(provider->ftp_proc);
1775
1776#ifndef illumos
1777	mutex_destroy(&provider->ftp_mtx);
1778	mutex_destroy(&provider->ftp_cmtx);
1779#endif
1780	kmem_free(provider, sizeof (fasttrap_provider_t));
1781
1782	/*
1783	 * Decrement p_dtrace_probes on the process whose provider we're
1784	 * freeing. We don't have to worry about clobbering somone else's
1785	 * modifications to it because we have locked the bucket that
1786	 * corresponds to this process's hash chain in the provider hash
1787	 * table. Don't sweat it if we can't find the process.
1788	 */
1789	if ((p = pfind(pid)) == NULL) {
1790		return;
1791	}
1792
1793	p->p_dtrace_probes--;
1794#ifndef illumos
1795	PROC_UNLOCK(p);
1796#endif
1797}
1798
1799static void
1800fasttrap_provider_retire(pid_t pid, const char *name, int mprov)
1801{
1802	fasttrap_provider_t *fp;
1803	fasttrap_bucket_t *bucket;
1804	dtrace_provider_id_t provid;
1805
1806	ASSERT(strlen(name) < sizeof (fp->ftp_name));
1807
1808	bucket = &fasttrap_provs.fth_table[FASTTRAP_PROVS_INDEX(pid, name)];
1809	mutex_enter(&bucket->ftb_mtx);
1810
1811	for (fp = bucket->ftb_data; fp != NULL; fp = fp->ftp_next) {
1812		if (fp->ftp_pid == pid && strcmp(fp->ftp_name, name) == 0 &&
1813		    !fp->ftp_retired)
1814			break;
1815	}
1816
1817	if (fp == NULL) {
1818		mutex_exit(&bucket->ftb_mtx);
1819		return;
1820	}
1821
1822	mutex_enter(&fp->ftp_mtx);
1823	ASSERT(!mprov || fp->ftp_mcount > 0);
1824	if (mprov && --fp->ftp_mcount != 0)  {
1825		mutex_exit(&fp->ftp_mtx);
1826		mutex_exit(&bucket->ftb_mtx);
1827		return;
1828	}
1829
1830	/*
1831	 * Mark the provider to be removed in our post-processing step, mark it
1832	 * retired, and drop the active count on its proc. Marking it indicates
1833	 * that we should try to remove it; setting the retired flag indicates
1834	 * that we're done with this provider; dropping the active the proc
1835	 * releases our hold, and when this reaches zero (as it will during
1836	 * exit or exec) the proc and associated providers become defunct.
1837	 *
1838	 * We obviously need to take the bucket lock before the provider lock
1839	 * to perform the lookup, but we need to drop the provider lock
1840	 * before calling into the DTrace framework since we acquire the
1841	 * provider lock in callbacks invoked from the DTrace framework. The
1842	 * bucket lock therefore protects the integrity of the provider hash
1843	 * table.
1844	 */
1845	atomic_dec_64(&fp->ftp_proc->ftpc_acount);
1846	ASSERT(fp->ftp_proc->ftpc_acount < fp->ftp_proc->ftpc_rcount);
1847
1848	fp->ftp_retired = 1;
1849	fp->ftp_marked = 1;
1850	provid = fp->ftp_provid;
1851	mutex_exit(&fp->ftp_mtx);
1852
1853	/*
1854	 * We don't have to worry about invalidating the same provider twice
1855	 * since fasttrap_provider_lookup() will ignore provider that have
1856	 * been marked as retired.
1857	 */
1858	dtrace_invalidate(provid);
1859
1860	mutex_exit(&bucket->ftb_mtx);
1861
1862	fasttrap_pid_cleanup();
1863}
1864
1865static int
1866fasttrap_uint32_cmp(const void *ap, const void *bp)
1867{
1868	return (*(const uint32_t *)ap - *(const uint32_t *)bp);
1869}
1870
1871static int
1872fasttrap_uint64_cmp(const void *ap, const void *bp)
1873{
1874	return (*(const uint64_t *)ap - *(const uint64_t *)bp);
1875}
1876
1877static int
1878fasttrap_add_probe(fasttrap_probe_spec_t *pdata)
1879{
1880	fasttrap_provider_t *provider;
1881	fasttrap_probe_t *pp;
1882	fasttrap_tracepoint_t *tp;
1883	char *name;
1884	int i, aframes = 0, whack;
1885
1886	/*
1887	 * There needs to be at least one desired trace point.
1888	 */
1889	if (pdata->ftps_noffs == 0)
1890		return (EINVAL);
1891
1892	switch (pdata->ftps_type) {
1893	case DTFTP_ENTRY:
1894		name = "entry";
1895		aframes = FASTTRAP_ENTRY_AFRAMES;
1896		break;
1897	case DTFTP_RETURN:
1898		name = "return";
1899		aframes = FASTTRAP_RETURN_AFRAMES;
1900		break;
1901	case DTFTP_OFFSETS:
1902		name = NULL;
1903		break;
1904	default:
1905		return (EINVAL);
1906	}
1907
1908	if ((provider = fasttrap_provider_lookup(pdata->ftps_pid,
1909	    FASTTRAP_PID_NAME, &pid_attr)) == NULL)
1910		return (ESRCH);
1911
1912	/*
1913	 * Increment this reference count to indicate that a consumer is
1914	 * actively adding a new probe associated with this provider. This
1915	 * prevents the provider from being deleted -- we'll need to check
1916	 * for pending deletions when we drop this reference count.
1917	 */
1918	provider->ftp_ccount++;
1919	mutex_exit(&provider->ftp_mtx);
1920
1921	/*
1922	 * Grab the creation lock to ensure consistency between calls to
1923	 * dtrace_probe_lookup() and dtrace_probe_create() in the face of
1924	 * other threads creating probes. We must drop the provider lock
1925	 * before taking this lock to avoid a three-way deadlock with the
1926	 * DTrace framework.
1927	 */
1928	mutex_enter(&provider->ftp_cmtx);
1929
1930	if (name == NULL) {
1931		for (i = 0; i < pdata->ftps_noffs; i++) {
1932			char name_str[17];
1933
1934			(void) sprintf(name_str, "%llx",
1935			    (unsigned long long)pdata->ftps_offs[i]);
1936
1937			if (dtrace_probe_lookup(provider->ftp_provid,
1938			    pdata->ftps_mod, pdata->ftps_func, name_str) != 0)
1939				continue;
1940
1941			atomic_inc_32(&fasttrap_total);
1942
1943			if (fasttrap_total > fasttrap_max) {
1944				atomic_dec_32(&fasttrap_total);
1945				goto no_mem;
1946			}
1947
1948			pp = kmem_zalloc(sizeof (fasttrap_probe_t), KM_SLEEP);
1949
1950			pp->ftp_prov = provider;
1951			pp->ftp_faddr = pdata->ftps_pc;
1952			pp->ftp_fsize = pdata->ftps_size;
1953			pp->ftp_pid = pdata->ftps_pid;
1954			pp->ftp_ntps = 1;
1955
1956			tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),
1957			    KM_SLEEP);
1958
1959			tp->ftt_proc = provider->ftp_proc;
1960			tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc;
1961			tp->ftt_pid = pdata->ftps_pid;
1962
1963			pp->ftp_tps[0].fit_tp = tp;
1964			pp->ftp_tps[0].fit_id.fti_probe = pp;
1965			pp->ftp_tps[0].fit_id.fti_ptype = pdata->ftps_type;
1966
1967			pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
1968			    pdata->ftps_mod, pdata->ftps_func, name_str,
1969			    FASTTRAP_OFFSET_AFRAMES, pp);
1970		}
1971
1972	} else if (dtrace_probe_lookup(provider->ftp_provid, pdata->ftps_mod,
1973	    pdata->ftps_func, name) == 0) {
1974		atomic_add_32(&fasttrap_total, pdata->ftps_noffs);
1975
1976		if (fasttrap_total > fasttrap_max) {
1977			atomic_add_32(&fasttrap_total, -pdata->ftps_noffs);
1978			goto no_mem;
1979		}
1980
1981		/*
1982		 * Make sure all tracepoint program counter values are unique.
1983		 * We later assume that each probe has exactly one tracepoint
1984		 * for a given pc.
1985		 */
1986		qsort(pdata->ftps_offs, pdata->ftps_noffs,
1987		    sizeof (uint64_t), fasttrap_uint64_cmp);
1988		for (i = 1; i < pdata->ftps_noffs; i++) {
1989			if (pdata->ftps_offs[i] > pdata->ftps_offs[i - 1])
1990				continue;
1991
1992			atomic_add_32(&fasttrap_total, -pdata->ftps_noffs);
1993			goto no_mem;
1994		}
1995
1996		ASSERT(pdata->ftps_noffs > 0);
1997		pp = kmem_zalloc(offsetof(fasttrap_probe_t,
1998		    ftp_tps[pdata->ftps_noffs]), KM_SLEEP);
1999
2000		pp->ftp_prov = provider;
2001		pp->ftp_faddr = pdata->ftps_pc;
2002		pp->ftp_fsize = pdata->ftps_size;
2003		pp->ftp_pid = pdata->ftps_pid;
2004		pp->ftp_ntps = pdata->ftps_noffs;
2005
2006		for (i = 0; i < pdata->ftps_noffs; i++) {
2007			tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t),
2008			    KM_SLEEP);
2009
2010			tp->ftt_proc = provider->ftp_proc;
2011			tp->ftt_pc = pdata->ftps_offs[i] + pdata->ftps_pc;
2012			tp->ftt_pid = pdata->ftps_pid;
2013
2014			pp->ftp_tps[i].fit_tp = tp;
2015			pp->ftp_tps[i].fit_id.fti_probe = pp;
2016			pp->ftp_tps[i].fit_id.fti_ptype = pdata->ftps_type;
2017		}
2018
2019		pp->ftp_id = dtrace_probe_create(provider->ftp_provid,
2020		    pdata->ftps_mod, pdata->ftps_func, name, aframes, pp);
2021	}
2022
2023	mutex_exit(&provider->ftp_cmtx);
2024
2025	/*
2026	 * We know that the provider is still valid since we incremented the
2027	 * creation reference count. If someone tried to clean up this provider
2028	 * while we were using it (e.g. because the process called exec(2) or
2029	 * exit(2)), take note of that and try to clean it up now.
2030	 */
2031	mutex_enter(&provider->ftp_mtx);
2032	provider->ftp_ccount--;
2033	whack = provider->ftp_retired;
2034	mutex_exit(&provider->ftp_mtx);
2035
2036	if (whack)
2037		fasttrap_pid_cleanup();
2038
2039	return (0);
2040
2041no_mem:
2042	/*
2043	 * If we've exhausted the allowable resources, we'll try to remove
2044	 * this provider to free some up. This is to cover the case where
2045	 * the user has accidentally created many more probes than was
2046	 * intended (e.g. pid123:::).
2047	 */
2048	mutex_exit(&provider->ftp_cmtx);
2049	mutex_enter(&provider->ftp_mtx);
2050	provider->ftp_ccount--;
2051	provider->ftp_marked = 1;
2052	mutex_exit(&provider->ftp_mtx);
2053
2054	fasttrap_pid_cleanup();
2055
2056	return (ENOMEM);
2057}
2058
2059/*ARGSUSED*/
2060static void *
2061fasttrap_meta_provide(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid)
2062{
2063	fasttrap_provider_t *provider;
2064
2065	/*
2066	 * A 32-bit unsigned integer (like a pid for example) can be
2067	 * expressed in 10 or fewer decimal digits. Make sure that we'll
2068	 * have enough space for the provider name.
2069	 */
2070	if (strlen(dhpv->dthpv_provname) + 10 >=
2071	    sizeof (provider->ftp_name)) {
2072		printf("failed to instantiate provider %s: "
2073		    "name too long to accomodate pid", dhpv->dthpv_provname);
2074		return (NULL);
2075	}
2076
2077	/*
2078	 * Don't let folks spoof the true pid provider.
2079	 */
2080	if (strcmp(dhpv->dthpv_provname, FASTTRAP_PID_NAME) == 0) {
2081		printf("failed to instantiate provider %s: "
2082		    "%s is an invalid name", dhpv->dthpv_provname,
2083		    FASTTRAP_PID_NAME);
2084		return (NULL);
2085	}
2086
2087	/*
2088	 * The highest stability class that fasttrap supports is ISA; cap
2089	 * the stability of the new provider accordingly.
2090	 */
2091	if (dhpv->dthpv_pattr.dtpa_provider.dtat_class > DTRACE_CLASS_ISA)
2092		dhpv->dthpv_pattr.dtpa_provider.dtat_class = DTRACE_CLASS_ISA;
2093	if (dhpv->dthpv_pattr.dtpa_mod.dtat_class > DTRACE_CLASS_ISA)
2094		dhpv->dthpv_pattr.dtpa_mod.dtat_class = DTRACE_CLASS_ISA;
2095	if (dhpv->dthpv_pattr.dtpa_func.dtat_class > DTRACE_CLASS_ISA)
2096		dhpv->dthpv_pattr.dtpa_func.dtat_class = DTRACE_CLASS_ISA;
2097	if (dhpv->dthpv_pattr.dtpa_name.dtat_class > DTRACE_CLASS_ISA)
2098		dhpv->dthpv_pattr.dtpa_name.dtat_class = DTRACE_CLASS_ISA;
2099	if (dhpv->dthpv_pattr.dtpa_args.dtat_class > DTRACE_CLASS_ISA)
2100		dhpv->dthpv_pattr.dtpa_args.dtat_class = DTRACE_CLASS_ISA;
2101
2102	if ((provider = fasttrap_provider_lookup(pid, dhpv->dthpv_provname,
2103	    &dhpv->dthpv_pattr)) == NULL) {
2104		printf("failed to instantiate provider %s for "
2105		    "process %u",  dhpv->dthpv_provname, (uint_t)pid);
2106		return (NULL);
2107	}
2108
2109	/*
2110	 * Up the meta provider count so this provider isn't removed until
2111	 * the meta provider has been told to remove it.
2112	 */
2113	provider->ftp_mcount++;
2114
2115	mutex_exit(&provider->ftp_mtx);
2116
2117	return (provider);
2118}
2119
2120/*
2121 * We know a few things about our context here:  we know that the probe being
2122 * created doesn't already exist (DTrace won't load DOF at the same address
2123 * twice, even if explicitly told to do so) and we know that we are
2124 * single-threaded with respect to the meta provider machinery. Knowing that
2125 * this is a new probe and that there is no way for us to race with another
2126 * operation on this provider allows us an important optimization: we need not
2127 * lookup a probe before adding it.  Saving this lookup is important because
2128 * this code is in the fork path for processes with USDT probes, and lookups
2129 * here are potentially very expensive because of long hash conflicts on
2130 * module, function and name (DTrace doesn't hash on provider name).
2131 */
2132/*ARGSUSED*/
2133static void
2134fasttrap_meta_create_probe(void *arg, void *parg,
2135    dtrace_helper_probedesc_t *dhpb)
2136{
2137	fasttrap_provider_t *provider = parg;
2138	fasttrap_probe_t *pp;
2139	fasttrap_tracepoint_t *tp;
2140	int i, j;
2141	uint32_t ntps;
2142
2143	/*
2144	 * Since the meta provider count is non-zero we don't have to worry
2145	 * about this provider disappearing.
2146	 */
2147	ASSERT(provider->ftp_mcount > 0);
2148
2149	/*
2150	 * The offsets must be unique.
2151	 */
2152	qsort(dhpb->dthpb_offs, dhpb->dthpb_noffs, sizeof (uint32_t),
2153	    fasttrap_uint32_cmp);
2154	for (i = 1; i < dhpb->dthpb_noffs; i++) {
2155		if (dhpb->dthpb_base + dhpb->dthpb_offs[i] <=
2156		    dhpb->dthpb_base + dhpb->dthpb_offs[i - 1])
2157			return;
2158	}
2159
2160	qsort(dhpb->dthpb_enoffs, dhpb->dthpb_nenoffs, sizeof (uint32_t),
2161	    fasttrap_uint32_cmp);
2162	for (i = 1; i < dhpb->dthpb_nenoffs; i++) {
2163		if (dhpb->dthpb_base + dhpb->dthpb_enoffs[i] <=
2164		    dhpb->dthpb_base + dhpb->dthpb_enoffs[i - 1])
2165			return;
2166	}
2167
2168	ntps = dhpb->dthpb_noffs + dhpb->dthpb_nenoffs;
2169	ASSERT(ntps > 0);
2170
2171	atomic_add_32(&fasttrap_total, ntps);
2172
2173	if (fasttrap_total > fasttrap_max) {
2174		atomic_add_32(&fasttrap_total, -ntps);
2175		return;
2176	}
2177
2178	pp = kmem_zalloc(offsetof(fasttrap_probe_t, ftp_tps[ntps]), KM_SLEEP);
2179
2180	pp->ftp_prov = provider;
2181	pp->ftp_pid = provider->ftp_pid;
2182	pp->ftp_ntps = ntps;
2183	pp->ftp_nargs = dhpb->dthpb_xargc;
2184	pp->ftp_xtypes = dhpb->dthpb_xtypes;
2185	pp->ftp_ntypes = dhpb->dthpb_ntypes;
2186
2187	/*
2188	 * First create a tracepoint for each actual point of interest.
2189	 */
2190	for (i = 0; i < dhpb->dthpb_noffs; i++) {
2191		tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP);
2192
2193		tp->ftt_proc = provider->ftp_proc;
2194		tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_offs[i];
2195		tp->ftt_pid = provider->ftp_pid;
2196
2197		pp->ftp_tps[i].fit_tp = tp;
2198		pp->ftp_tps[i].fit_id.fti_probe = pp;
2199#ifdef __sparc
2200		pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_POST_OFFSETS;
2201#else
2202		pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_OFFSETS;
2203#endif
2204	}
2205
2206	/*
2207	 * Then create a tracepoint for each is-enabled point.
2208	 */
2209	for (j = 0; i < ntps; i++, j++) {
2210		tp = kmem_zalloc(sizeof (fasttrap_tracepoint_t), KM_SLEEP);
2211
2212		tp->ftt_proc = provider->ftp_proc;
2213		tp->ftt_pc = dhpb->dthpb_base + dhpb->dthpb_enoffs[j];
2214		tp->ftt_pid = provider->ftp_pid;
2215
2216		pp->ftp_tps[i].fit_tp = tp;
2217		pp->ftp_tps[i].fit_id.fti_probe = pp;
2218		pp->ftp_tps[i].fit_id.fti_ptype = DTFTP_IS_ENABLED;
2219	}
2220
2221	/*
2222	 * If the arguments are shuffled around we set the argument remapping
2223	 * table. Later, when the probe fires, we only remap the arguments
2224	 * if the table is non-NULL.
2225	 */
2226	for (i = 0; i < dhpb->dthpb_xargc; i++) {
2227		if (dhpb->dthpb_args[i] != i) {
2228			pp->ftp_argmap = dhpb->dthpb_args;
2229			break;
2230		}
2231	}
2232
2233	/*
2234	 * The probe is fully constructed -- register it with DTrace.
2235	 */
2236	pp->ftp_id = dtrace_probe_create(provider->ftp_provid, dhpb->dthpb_mod,
2237	    dhpb->dthpb_func, dhpb->dthpb_name, FASTTRAP_OFFSET_AFRAMES, pp);
2238}
2239
2240/*ARGSUSED*/
2241static void
2242fasttrap_meta_remove(void *arg, dtrace_helper_provdesc_t *dhpv, pid_t pid)
2243{
2244	/*
2245	 * Clean up the USDT provider. There may be active consumers of the
2246	 * provider busy adding probes, no damage will actually befall the
2247	 * provider until that count has dropped to zero. This just puts
2248	 * the provider on death row.
2249	 */
2250	fasttrap_provider_retire(pid, dhpv->dthpv_provname, 1);
2251}
2252
2253static dtrace_mops_t fasttrap_mops = {
2254	fasttrap_meta_create_probe,
2255	fasttrap_meta_provide,
2256	fasttrap_meta_remove
2257};
2258
2259/*ARGSUSED*/
2260static int
2261fasttrap_open(struct cdev *dev __unused, int oflags __unused,
2262    int devtype __unused, struct thread *td __unused)
2263{
2264	return (0);
2265}
2266
2267/*ARGSUSED*/
2268static int
2269fasttrap_ioctl(struct cdev *dev, u_long cmd, caddr_t arg, int fflag,
2270    struct thread *td)
2271{
2272#ifdef notyet
2273	struct kinfo_proc kp;
2274	const cred_t *cr = td->td_ucred;
2275#endif
2276	if (!dtrace_attached())
2277		return (EAGAIN);
2278
2279	if (cmd == FASTTRAPIOC_MAKEPROBE) {
2280		fasttrap_probe_spec_t *uprobe = *(fasttrap_probe_spec_t **)arg;
2281		fasttrap_probe_spec_t *probe;
2282		uint64_t noffs;
2283		size_t size;
2284		int ret, err;
2285
2286		if (copyin(&uprobe->ftps_noffs, &noffs,
2287		    sizeof (uprobe->ftps_noffs)))
2288			return (EFAULT);
2289
2290		/*
2291		 * Probes must have at least one tracepoint.
2292		 */
2293		if (noffs == 0)
2294			return (EINVAL);
2295
2296		size = sizeof (fasttrap_probe_spec_t) +
2297		    sizeof (probe->ftps_offs[0]) * (noffs - 1);
2298
2299		if (size > 1024 * 1024)
2300			return (ENOMEM);
2301
2302		probe = kmem_alloc(size, KM_SLEEP);
2303
2304		if (copyin(uprobe, probe, size) != 0 ||
2305		    probe->ftps_noffs != noffs) {
2306			kmem_free(probe, size);
2307			return (EFAULT);
2308		}
2309
2310		/*
2311		 * Verify that the function and module strings contain no
2312		 * funny characters.
2313		 */
2314		if (u8_validate(probe->ftps_func, strlen(probe->ftps_func),
2315		    NULL, U8_VALIDATE_ENTIRE, &err) < 0) {
2316			ret = EINVAL;
2317			goto err;
2318		}
2319
2320		if (u8_validate(probe->ftps_mod, strlen(probe->ftps_mod),
2321		    NULL, U8_VALIDATE_ENTIRE, &err) < 0) {
2322			ret = EINVAL;
2323			goto err;
2324		}
2325
2326#ifdef notyet
2327		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {
2328			proc_t *p;
2329			pid_t pid = probe->ftps_pid;
2330
2331#ifdef illumos
2332			mutex_enter(&pidlock);
2333#endif
2334			/*
2335			 * Report an error if the process doesn't exist
2336			 * or is actively being birthed.
2337			 */
2338			sx_slock(&proctree_lock);
2339			p = pfind(pid);
2340			if (p)
2341				fill_kinfo_proc(p, &kp);
2342			sx_sunlock(&proctree_lock);
2343			if (p == NULL || kp.ki_stat == SIDL) {
2344#ifdef illumos
2345				mutex_exit(&pidlock);
2346#endif
2347				return (ESRCH);
2348			}
2349#ifdef illumos
2350			mutex_enter(&p->p_lock);
2351			mutex_exit(&pidlock);
2352#else
2353			PROC_LOCK_ASSERT(p, MA_OWNED);
2354#endif
2355
2356#ifdef notyet
2357			if ((ret = priv_proc_cred_perm(cr, p, NULL,
2358			    VREAD | VWRITE)) != 0) {
2359#ifdef illumos
2360				mutex_exit(&p->p_lock);
2361#else
2362				PROC_UNLOCK(p);
2363#endif
2364				return (ret);
2365			}
2366#endif /* notyet */
2367#ifdef illumos
2368			mutex_exit(&p->p_lock);
2369#else
2370			PROC_UNLOCK(p);
2371#endif
2372		}
2373#endif /* notyet */
2374
2375		ret = fasttrap_add_probe(probe);
2376err:
2377		kmem_free(probe, size);
2378
2379		return (ret);
2380
2381	} else if (cmd == FASTTRAPIOC_GETINSTR) {
2382		fasttrap_instr_query_t instr;
2383		fasttrap_tracepoint_t *tp;
2384		uint_t index;
2385#ifdef illumos
2386		int ret;
2387#endif
2388
2389#ifdef illumos
2390		if (copyin((void *)arg, &instr, sizeof (instr)) != 0)
2391			return (EFAULT);
2392#endif
2393
2394#ifdef notyet
2395		if (!PRIV_POLICY_CHOICE(cr, PRIV_ALL, B_FALSE)) {
2396			proc_t *p;
2397			pid_t pid = instr.ftiq_pid;
2398
2399#ifdef illumos
2400			mutex_enter(&pidlock);
2401#endif
2402			/*
2403			 * Report an error if the process doesn't exist
2404			 * or is actively being birthed.
2405			 */
2406			sx_slock(&proctree_lock);
2407			p = pfind(pid);
2408			if (p)
2409				fill_kinfo_proc(p, &kp);
2410			sx_sunlock(&proctree_lock);
2411			if (p == NULL || kp.ki_stat == SIDL) {
2412#ifdef illumos
2413				mutex_exit(&pidlock);
2414#endif
2415				return (ESRCH);
2416			}
2417#ifdef illumos
2418			mutex_enter(&p->p_lock);
2419			mutex_exit(&pidlock);
2420#else
2421			PROC_LOCK_ASSERT(p, MA_OWNED);
2422#endif
2423
2424#ifdef notyet
2425			if ((ret = priv_proc_cred_perm(cr, p, NULL,
2426			    VREAD)) != 0) {
2427#ifdef illumos
2428				mutex_exit(&p->p_lock);
2429#else
2430				PROC_UNLOCK(p);
2431#endif
2432				return (ret);
2433			}
2434#endif /* notyet */
2435
2436#ifdef illumos
2437			mutex_exit(&p->p_lock);
2438#else
2439			PROC_UNLOCK(p);
2440#endif
2441		}
2442#endif /* notyet */
2443
2444		index = FASTTRAP_TPOINTS_INDEX(instr.ftiq_pid, instr.ftiq_pc);
2445
2446		mutex_enter(&fasttrap_tpoints.fth_table[index].ftb_mtx);
2447		tp = fasttrap_tpoints.fth_table[index].ftb_data;
2448		while (tp != NULL) {
2449			if (instr.ftiq_pid == tp->ftt_pid &&
2450			    instr.ftiq_pc == tp->ftt_pc &&
2451			    tp->ftt_proc->ftpc_acount != 0)
2452				break;
2453
2454			tp = tp->ftt_next;
2455		}
2456
2457		if (tp == NULL) {
2458			mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx);
2459			return (ENOENT);
2460		}
2461
2462		bcopy(&tp->ftt_instr, &instr.ftiq_instr,
2463		    sizeof (instr.ftiq_instr));
2464		mutex_exit(&fasttrap_tpoints.fth_table[index].ftb_mtx);
2465
2466		if (copyout(&instr, (void *)arg, sizeof (instr)) != 0)
2467			return (EFAULT);
2468
2469		return (0);
2470	}
2471
2472	return (EINVAL);
2473}
2474
2475static int
2476fasttrap_load(void)
2477{
2478	ulong_t nent;
2479	int i, ret;
2480
2481        /* Create the /dev/dtrace/fasttrap entry. */
2482        fasttrap_cdev = make_dev(&fasttrap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
2483            "dtrace/fasttrap");
2484
2485	mtx_init(&fasttrap_cleanup_mtx, "fasttrap clean", "dtrace", MTX_DEF);
2486	mutex_init(&fasttrap_count_mtx, "fasttrap count mtx", MUTEX_DEFAULT,
2487	    NULL);
2488
2489#ifdef illumos
2490	fasttrap_max = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
2491	    "fasttrap-max-probes", FASTTRAP_MAX_DEFAULT);
2492#endif
2493	fasttrap_total = 0;
2494
2495	/*
2496	 * Conjure up the tracepoints hashtable...
2497	 */
2498#ifdef illumos
2499	nent = ddi_getprop(DDI_DEV_T_ANY, devi, DDI_PROP_DONTPASS,
2500	    "fasttrap-hash-size", FASTTRAP_TPOINTS_DEFAULT_SIZE);
2501#else
2502	nent = tpoints_hash_size;
2503#endif
2504
2505	if (nent == 0 || nent > 0x1000000)
2506		nent = FASTTRAP_TPOINTS_DEFAULT_SIZE;
2507
2508	tpoints_hash_size = nent;
2509
2510	if (ISP2(nent))
2511		fasttrap_tpoints.fth_nent = nent;
2512	else
2513		fasttrap_tpoints.fth_nent = 1 << fasttrap_highbit(nent);
2514	ASSERT(fasttrap_tpoints.fth_nent > 0);
2515	fasttrap_tpoints.fth_mask = fasttrap_tpoints.fth_nent - 1;
2516	fasttrap_tpoints.fth_table = kmem_zalloc(fasttrap_tpoints.fth_nent *
2517	    sizeof (fasttrap_bucket_t), KM_SLEEP);
2518#ifndef illumos
2519	for (i = 0; i < fasttrap_tpoints.fth_nent; i++)
2520		mutex_init(&fasttrap_tpoints.fth_table[i].ftb_mtx,
2521		    "tracepoints bucket mtx", MUTEX_DEFAULT, NULL);
2522#endif
2523
2524	/*
2525	 * ... and the providers hash table...
2526	 */
2527	nent = FASTTRAP_PROVIDERS_DEFAULT_SIZE;
2528	if (ISP2(nent))
2529		fasttrap_provs.fth_nent = nent;
2530	else
2531		fasttrap_provs.fth_nent = 1 << fasttrap_highbit(nent);
2532	ASSERT(fasttrap_provs.fth_nent > 0);
2533	fasttrap_provs.fth_mask = fasttrap_provs.fth_nent - 1;
2534	fasttrap_provs.fth_table = kmem_zalloc(fasttrap_provs.fth_nent *
2535	    sizeof (fasttrap_bucket_t), KM_SLEEP);
2536#ifndef illumos
2537	for (i = 0; i < fasttrap_provs.fth_nent; i++)
2538		mutex_init(&fasttrap_provs.fth_table[i].ftb_mtx,
2539		    "providers bucket mtx", MUTEX_DEFAULT, NULL);
2540#endif
2541
2542	ret = kproc_create(fasttrap_pid_cleanup_cb, NULL,
2543	    &fasttrap_cleanup_proc, 0, 0, "ftcleanup");
2544	if (ret != 0) {
2545		destroy_dev(fasttrap_cdev);
2546#ifndef illumos
2547		for (i = 0; i < fasttrap_provs.fth_nent; i++)
2548			mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx);
2549		for (i = 0; i < fasttrap_tpoints.fth_nent; i++)
2550			mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx);
2551#endif
2552		kmem_free(fasttrap_provs.fth_table, fasttrap_provs.fth_nent *
2553		    sizeof (fasttrap_bucket_t));
2554		mtx_destroy(&fasttrap_cleanup_mtx);
2555		mutex_destroy(&fasttrap_count_mtx);
2556		return (ret);
2557	}
2558
2559
2560	/*
2561	 * ... and the procs hash table.
2562	 */
2563	nent = FASTTRAP_PROCS_DEFAULT_SIZE;
2564	if (ISP2(nent))
2565		fasttrap_procs.fth_nent = nent;
2566	else
2567		fasttrap_procs.fth_nent = 1 << fasttrap_highbit(nent);
2568	ASSERT(fasttrap_procs.fth_nent > 0);
2569	fasttrap_procs.fth_mask = fasttrap_procs.fth_nent - 1;
2570	fasttrap_procs.fth_table = kmem_zalloc(fasttrap_procs.fth_nent *
2571	    sizeof (fasttrap_bucket_t), KM_SLEEP);
2572#ifndef illumos
2573	for (i = 0; i < fasttrap_procs.fth_nent; i++)
2574		mutex_init(&fasttrap_procs.fth_table[i].ftb_mtx,
2575		    "processes bucket mtx", MUTEX_DEFAULT, NULL);
2576
2577	rm_init(&fasttrap_tp_lock, "fasttrap tracepoint");
2578
2579	/*
2580	 * This event handler must run before kdtrace_thread_dtor() since it
2581	 * accesses the thread's struct kdtrace_thread.
2582	 */
2583	fasttrap_thread_dtor_tag = EVENTHANDLER_REGISTER(thread_dtor,
2584	    fasttrap_thread_dtor, NULL, EVENTHANDLER_PRI_FIRST);
2585#endif
2586
2587	/*
2588	 * Install our hooks into fork(2), exec(2), and exit(2).
2589	 */
2590	dtrace_fasttrap_fork = &fasttrap_fork;
2591	dtrace_fasttrap_exit = &fasttrap_exec_exit;
2592	dtrace_fasttrap_exec = &fasttrap_exec_exit;
2593
2594	(void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL,
2595	    &fasttrap_meta_id);
2596
2597	return (0);
2598}
2599
2600static int
2601fasttrap_unload(void)
2602{
2603	int i, fail = 0;
2604
2605	/*
2606	 * Unregister the meta-provider to make sure no new fasttrap-
2607	 * managed providers come along while we're trying to close up
2608	 * shop. If we fail to detach, we'll need to re-register as a
2609	 * meta-provider. We can fail to unregister as a meta-provider
2610	 * if providers we manage still exist.
2611	 */
2612	if (fasttrap_meta_id != DTRACE_METAPROVNONE &&
2613	    dtrace_meta_unregister(fasttrap_meta_id) != 0)
2614		return (-1);
2615
2616	/*
2617	 * Iterate over all of our providers. If there's still a process
2618	 * that corresponds to that pid, fail to detach.
2619	 */
2620	for (i = 0; i < fasttrap_provs.fth_nent; i++) {
2621		fasttrap_provider_t **fpp, *fp;
2622		fasttrap_bucket_t *bucket = &fasttrap_provs.fth_table[i];
2623
2624		mutex_enter(&bucket->ftb_mtx);
2625		fpp = (fasttrap_provider_t **)&bucket->ftb_data;
2626		while ((fp = *fpp) != NULL) {
2627			/*
2628			 * Acquire and release the lock as a simple way of
2629			 * waiting for any other consumer to finish with
2630			 * this provider. A thread must first acquire the
2631			 * bucket lock so there's no chance of another thread
2632			 * blocking on the provider's lock.
2633			 */
2634			mutex_enter(&fp->ftp_mtx);
2635			mutex_exit(&fp->ftp_mtx);
2636
2637			if (dtrace_unregister(fp->ftp_provid) != 0) {
2638				fail = 1;
2639				fpp = &fp->ftp_next;
2640			} else {
2641				*fpp = fp->ftp_next;
2642				fasttrap_provider_free(fp);
2643			}
2644		}
2645
2646		mutex_exit(&bucket->ftb_mtx);
2647	}
2648
2649	if (fail) {
2650		(void) dtrace_meta_register("fasttrap", &fasttrap_mops, NULL,
2651		    &fasttrap_meta_id);
2652
2653		return (-1);
2654	}
2655
2656	/*
2657	 * Stop new processes from entering these hooks now, before the
2658	 * fasttrap_cleanup thread runs.  That way all processes will hopefully
2659	 * be out of these hooks before we free fasttrap_provs.fth_table
2660	 */
2661	ASSERT(dtrace_fasttrap_fork == &fasttrap_fork);
2662	dtrace_fasttrap_fork = NULL;
2663
2664	ASSERT(dtrace_fasttrap_exec == &fasttrap_exec_exit);
2665	dtrace_fasttrap_exec = NULL;
2666
2667	ASSERT(dtrace_fasttrap_exit == &fasttrap_exec_exit);
2668	dtrace_fasttrap_exit = NULL;
2669
2670	mtx_lock(&fasttrap_cleanup_mtx);
2671	fasttrap_cleanup_drain = 1;
2672	/* Wait for the cleanup thread to finish up and signal us. */
2673	wakeup(&fasttrap_cleanup_cv);
2674	mtx_sleep(&fasttrap_cleanup_drain, &fasttrap_cleanup_mtx, 0, "ftcld",
2675	    0);
2676	fasttrap_cleanup_proc = NULL;
2677	mtx_destroy(&fasttrap_cleanup_mtx);
2678
2679#ifdef DEBUG
2680	mutex_enter(&fasttrap_count_mtx);
2681	ASSERT(fasttrap_pid_count == 0);
2682	mutex_exit(&fasttrap_count_mtx);
2683#endif
2684
2685#ifndef illumos
2686	EVENTHANDLER_DEREGISTER(thread_dtor, fasttrap_thread_dtor_tag);
2687
2688	for (i = 0; i < fasttrap_tpoints.fth_nent; i++)
2689		mutex_destroy(&fasttrap_tpoints.fth_table[i].ftb_mtx);
2690	for (i = 0; i < fasttrap_provs.fth_nent; i++)
2691		mutex_destroy(&fasttrap_provs.fth_table[i].ftb_mtx);
2692	for (i = 0; i < fasttrap_procs.fth_nent; i++)
2693		mutex_destroy(&fasttrap_procs.fth_table[i].ftb_mtx);
2694#endif
2695	kmem_free(fasttrap_tpoints.fth_table,
2696	    fasttrap_tpoints.fth_nent * sizeof (fasttrap_bucket_t));
2697	fasttrap_tpoints.fth_nent = 0;
2698
2699	kmem_free(fasttrap_provs.fth_table,
2700	    fasttrap_provs.fth_nent * sizeof (fasttrap_bucket_t));
2701	fasttrap_provs.fth_nent = 0;
2702
2703	kmem_free(fasttrap_procs.fth_table,
2704	    fasttrap_procs.fth_nent * sizeof (fasttrap_bucket_t));
2705	fasttrap_procs.fth_nent = 0;
2706
2707#ifndef illumos
2708	destroy_dev(fasttrap_cdev);
2709	mutex_destroy(&fasttrap_count_mtx);
2710	rm_destroy(&fasttrap_tp_lock);
2711#endif
2712
2713	return (0);
2714}
2715
2716/* ARGSUSED */
2717static int
2718fasttrap_modevent(module_t mod __unused, int type, void *data __unused)
2719{
2720	int error = 0;
2721
2722	switch (type) {
2723	case MOD_LOAD:
2724		break;
2725
2726	case MOD_UNLOAD:
2727		break;
2728
2729	case MOD_SHUTDOWN:
2730		break;
2731
2732	default:
2733		error = EOPNOTSUPP;
2734		break;
2735	}
2736	return (error);
2737}
2738
2739SYSINIT(fasttrap_load, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY, fasttrap_load,
2740    NULL);
2741SYSUNINIT(fasttrap_unload, SI_SUB_DTRACE_PROVIDER, SI_ORDER_ANY,
2742    fasttrap_unload, NULL);
2743
2744DEV_MODULE(fasttrap, fasttrap_modevent, NULL);
2745MODULE_VERSION(fasttrap, 1);
2746MODULE_DEPEND(fasttrap, dtrace, 1, 1, 1);
2747MODULE_DEPEND(fasttrap, opensolaris, 1, 1, 1);
2748