xref: /xnu-10002.1.13/bsd/dev/dtrace/dtrace_glue.c (revision 1031c584a5e37aff177559b9f69dbd3c8c3fd30a)
1*1031c584SApple OSS Distributions /*
2*1031c584SApple OSS Distributions  * Copyright (c) 2005-2021 Apple Computer, Inc. All rights reserved.
3*1031c584SApple OSS Distributions  *
4*1031c584SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5*1031c584SApple OSS Distributions  *
6*1031c584SApple OSS Distributions  * This file contains Original Code and/or Modifications of Original Code
7*1031c584SApple OSS Distributions  * as defined in and that are subject to the Apple Public Source License
8*1031c584SApple OSS Distributions  * Version 2.0 (the 'License'). You may not use this file except in
9*1031c584SApple OSS Distributions  * compliance with the License. The rights granted to you under the License
10*1031c584SApple OSS Distributions  * may not be used to create, or enable the creation or redistribution of,
11*1031c584SApple OSS Distributions  * unlawful or unlicensed copies of an Apple operating system, or to
12*1031c584SApple OSS Distributions  * circumvent, violate, or enable the circumvention or violation of, any
13*1031c584SApple OSS Distributions  * terms of an Apple operating system software license agreement.
14*1031c584SApple OSS Distributions  *
15*1031c584SApple OSS Distributions  * Please obtain a copy of the License at
16*1031c584SApple OSS Distributions  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17*1031c584SApple OSS Distributions  *
18*1031c584SApple OSS Distributions  * The Original Code and all software distributed under the License are
19*1031c584SApple OSS Distributions  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20*1031c584SApple OSS Distributions  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21*1031c584SApple OSS Distributions  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22*1031c584SApple OSS Distributions  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23*1031c584SApple OSS Distributions  * Please see the License for the specific language governing rights and
24*1031c584SApple OSS Distributions  * limitations under the License.
25*1031c584SApple OSS Distributions  *
26*1031c584SApple OSS Distributions  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27*1031c584SApple OSS Distributions  */
28*1031c584SApple OSS Distributions 
29*1031c584SApple OSS Distributions #include <kern/thread.h>
30*1031c584SApple OSS Distributions 
31*1031c584SApple OSS Distributions #include <sys/time.h>
32*1031c584SApple OSS Distributions #include <sys/proc.h>
33*1031c584SApple OSS Distributions #include <sys/kauth.h>
34*1031c584SApple OSS Distributions #include <sys/user.h>
35*1031c584SApple OSS Distributions #include <sys/systm.h>
36*1031c584SApple OSS Distributions #include <sys/dtrace.h>
37*1031c584SApple OSS Distributions #include <sys/dtrace_impl.h>
38*1031c584SApple OSS Distributions #include <machine/atomic.h>
39*1031c584SApple OSS Distributions #include <libkern/OSKextLibPrivate.h>
40*1031c584SApple OSS Distributions #include <kern/kern_types.h>
41*1031c584SApple OSS Distributions #include <kern/timer_call.h>
42*1031c584SApple OSS Distributions #include <kern/thread_call.h>
43*1031c584SApple OSS Distributions #include <kern/task.h>
44*1031c584SApple OSS Distributions #include <kern/sched_prim.h>
45*1031c584SApple OSS Distributions #include <miscfs/devfs/devfs.h>
46*1031c584SApple OSS Distributions #include <kern/kalloc.h>
47*1031c584SApple OSS Distributions 
48*1031c584SApple OSS Distributions #include <mach/vm_param.h>
49*1031c584SApple OSS Distributions #include <mach/mach_vm.h>
50*1031c584SApple OSS Distributions #include <mach/task.h>
51*1031c584SApple OSS Distributions #include <vm/vm_map.h> /* All the bits we care about are guarded by MACH_KERNEL_PRIVATE :-( */
52*1031c584SApple OSS Distributions 
53*1031c584SApple OSS Distributions /*
54*1031c584SApple OSS Distributions  * pid/proc
55*1031c584SApple OSS Distributions  */
56*1031c584SApple OSS Distributions /* Solaris proc_t is the struct. Darwin's proc_t is a pointer to it. */
57*1031c584SApple OSS Distributions #define proc_t struct proc /* Steer clear of the Darwin typedef for proc_t */
58*1031c584SApple OSS Distributions 
59*1031c584SApple OSS Distributions KALLOC_HEAP_DEFINE(KHEAP_DTRACE, "dtrace", KHEAP_ID_KT_VAR);
60*1031c584SApple OSS Distributions 
61*1031c584SApple OSS Distributions void
dtrace_sprlock(proc_t * p)62*1031c584SApple OSS Distributions dtrace_sprlock(proc_t *p)
63*1031c584SApple OSS Distributions {
64*1031c584SApple OSS Distributions 	lck_mtx_lock(&p->p_dtrace_sprlock);
65*1031c584SApple OSS Distributions }
66*1031c584SApple OSS Distributions 
67*1031c584SApple OSS Distributions void
dtrace_sprunlock(proc_t * p)68*1031c584SApple OSS Distributions dtrace_sprunlock(proc_t *p)
69*1031c584SApple OSS Distributions {
70*1031c584SApple OSS Distributions 	lck_mtx_unlock(&p->p_dtrace_sprlock);
71*1031c584SApple OSS Distributions }
72*1031c584SApple OSS Distributions 
73*1031c584SApple OSS Distributions /* Not called from probe context */
74*1031c584SApple OSS Distributions proc_t *
sprlock(pid_t pid)75*1031c584SApple OSS Distributions sprlock(pid_t pid)
76*1031c584SApple OSS Distributions {
77*1031c584SApple OSS Distributions 	proc_t* p;
78*1031c584SApple OSS Distributions 
79*1031c584SApple OSS Distributions 	if ((p = proc_find(pid)) == PROC_NULL) {
80*1031c584SApple OSS Distributions 		return PROC_NULL;
81*1031c584SApple OSS Distributions 	}
82*1031c584SApple OSS Distributions 
83*1031c584SApple OSS Distributions 	task_suspend_internal(proc_task(p));
84*1031c584SApple OSS Distributions 
85*1031c584SApple OSS Distributions 	dtrace_sprlock(p);
86*1031c584SApple OSS Distributions 
87*1031c584SApple OSS Distributions 	return p;
88*1031c584SApple OSS Distributions }
89*1031c584SApple OSS Distributions 
90*1031c584SApple OSS Distributions /* Not called from probe context */
91*1031c584SApple OSS Distributions void
sprunlock(proc_t * p)92*1031c584SApple OSS Distributions sprunlock(proc_t *p)
93*1031c584SApple OSS Distributions {
94*1031c584SApple OSS Distributions 	if (p != PROC_NULL) {
95*1031c584SApple OSS Distributions 		dtrace_sprunlock(p);
96*1031c584SApple OSS Distributions 
97*1031c584SApple OSS Distributions 		task_resume_internal(proc_task(p));
98*1031c584SApple OSS Distributions 
99*1031c584SApple OSS Distributions 		proc_rele(p);
100*1031c584SApple OSS Distributions 	}
101*1031c584SApple OSS Distributions }
102*1031c584SApple OSS Distributions 
103*1031c584SApple OSS Distributions /*
104*1031c584SApple OSS Distributions  * uread/uwrite
105*1031c584SApple OSS Distributions  */
106*1031c584SApple OSS Distributions 
107*1031c584SApple OSS Distributions // These are not exported from vm_map.h.
108*1031c584SApple OSS Distributions extern kern_return_t vm_map_read_user(vm_map_t map, vm_map_address_t src_addr, void *dst_p, vm_size_t size);
109*1031c584SApple OSS Distributions extern kern_return_t vm_map_write_user(vm_map_t map, void *src_p, vm_map_address_t dst_addr, vm_size_t size);
110*1031c584SApple OSS Distributions 
111*1031c584SApple OSS Distributions /* Not called from probe context */
112*1031c584SApple OSS Distributions int
uread(proc_t * p,void * buf,user_size_t len,user_addr_t a)113*1031c584SApple OSS Distributions uread(proc_t *p, void *buf, user_size_t len, user_addr_t a)
114*1031c584SApple OSS Distributions {
115*1031c584SApple OSS Distributions 	kern_return_t ret;
116*1031c584SApple OSS Distributions 
117*1031c584SApple OSS Distributions 	ASSERT(p != PROC_NULL);
118*1031c584SApple OSS Distributions 	ASSERT(proc_task(p) != NULL);
119*1031c584SApple OSS Distributions 
120*1031c584SApple OSS Distributions 	task_t task = proc_task(p);
121*1031c584SApple OSS Distributions 
122*1031c584SApple OSS Distributions 	/*
123*1031c584SApple OSS Distributions 	 * Grab a reference to the task vm_map_t to make sure
124*1031c584SApple OSS Distributions 	 * the map isn't pulled out from under us.
125*1031c584SApple OSS Distributions 	 *
126*1031c584SApple OSS Distributions 	 * Because the proc_lock is not held at all times on all code
127*1031c584SApple OSS Distributions 	 * paths leading here, it is possible for the proc to have
128*1031c584SApple OSS Distributions 	 * exited. If the map is null, fail.
129*1031c584SApple OSS Distributions 	 */
130*1031c584SApple OSS Distributions 	vm_map_t map = get_task_map_reference(task);
131*1031c584SApple OSS Distributions 	if (map) {
132*1031c584SApple OSS Distributions 		ret = vm_map_read_user( map, (vm_map_address_t)a, buf, (vm_size_t)len);
133*1031c584SApple OSS Distributions 		vm_map_deallocate(map);
134*1031c584SApple OSS Distributions 	} else {
135*1031c584SApple OSS Distributions 		ret = KERN_TERMINATED;
136*1031c584SApple OSS Distributions 	}
137*1031c584SApple OSS Distributions 
138*1031c584SApple OSS Distributions 	return (int)ret;
139*1031c584SApple OSS Distributions }
140*1031c584SApple OSS Distributions 
141*1031c584SApple OSS Distributions 
142*1031c584SApple OSS Distributions /* Not called from probe context */
143*1031c584SApple OSS Distributions int
uwrite(proc_t * p,void * buf,user_size_t len,user_addr_t a)144*1031c584SApple OSS Distributions uwrite(proc_t *p, void *buf, user_size_t len, user_addr_t a)
145*1031c584SApple OSS Distributions {
146*1031c584SApple OSS Distributions 	kern_return_t ret;
147*1031c584SApple OSS Distributions 
148*1031c584SApple OSS Distributions 	ASSERT(p != NULL);
149*1031c584SApple OSS Distributions 	ASSERT(proc_task(p) != NULL);
150*1031c584SApple OSS Distributions 
151*1031c584SApple OSS Distributions 	task_t task = proc_task(p);
152*1031c584SApple OSS Distributions 
153*1031c584SApple OSS Distributions 	/*
154*1031c584SApple OSS Distributions 	 * Grab a reference to the task vm_map_t to make sure
155*1031c584SApple OSS Distributions 	 * the map isn't pulled out from under us.
156*1031c584SApple OSS Distributions 	 *
157*1031c584SApple OSS Distributions 	 * Because the proc_lock is not held at all times on all code
158*1031c584SApple OSS Distributions 	 * paths leading here, it is possible for the proc to have
159*1031c584SApple OSS Distributions 	 * exited. If the map is null, fail.
160*1031c584SApple OSS Distributions 	 */
161*1031c584SApple OSS Distributions 	vm_map_t map = get_task_map_reference(task);
162*1031c584SApple OSS Distributions 	if (map) {
163*1031c584SApple OSS Distributions 		/* Find the memory permissions. */
164*1031c584SApple OSS Distributions 		uint32_t nestingDepth = 999999;
165*1031c584SApple OSS Distributions 		vm_region_submap_short_info_data_64_t info;
166*1031c584SApple OSS Distributions 		mach_msg_type_number_t count = VM_REGION_SUBMAP_SHORT_INFO_COUNT_64;
167*1031c584SApple OSS Distributions 		mach_vm_address_t address = (mach_vm_address_t)a;
168*1031c584SApple OSS Distributions 		mach_vm_size_t sizeOfRegion = (mach_vm_size_t)len;
169*1031c584SApple OSS Distributions 
170*1031c584SApple OSS Distributions 		ret = mach_vm_region_recurse(map, &address, &sizeOfRegion, &nestingDepth, (vm_region_recurse_info_t)&info, &count);
171*1031c584SApple OSS Distributions 		if (ret != KERN_SUCCESS) {
172*1031c584SApple OSS Distributions 			goto done;
173*1031c584SApple OSS Distributions 		}
174*1031c584SApple OSS Distributions 
175*1031c584SApple OSS Distributions 		vm_prot_t reprotect;
176*1031c584SApple OSS Distributions 
177*1031c584SApple OSS Distributions 		if (!(info.protection & VM_PROT_WRITE)) {
178*1031c584SApple OSS Distributions 			/* Save the original protection values for restoration later */
179*1031c584SApple OSS Distributions 			reprotect = info.protection;
180*1031c584SApple OSS Distributions 
181*1031c584SApple OSS Distributions 			if (info.max_protection & VM_PROT_WRITE) {
182*1031c584SApple OSS Distributions 				/* The memory is not currently writable, but can be made writable. */
183*1031c584SApple OSS Distributions 				ret = mach_vm_protect(map, (mach_vm_offset_t)a, (mach_vm_size_t)len, 0, (reprotect & ~VM_PROT_EXECUTE) | VM_PROT_WRITE);
184*1031c584SApple OSS Distributions 			} else {
185*1031c584SApple OSS Distributions 				/*
186*1031c584SApple OSS Distributions 				 * The memory is not currently writable, and cannot be made writable. We need to COW this memory.
187*1031c584SApple OSS Distributions 				 *
188*1031c584SApple OSS Distributions 				 * Strange, we can't just say "reprotect | VM_PROT_COPY", that fails.
189*1031c584SApple OSS Distributions 				 */
190*1031c584SApple OSS Distributions 				ret = mach_vm_protect(map, (mach_vm_offset_t)a, (mach_vm_size_t)len, 0, VM_PROT_COPY | VM_PROT_READ | VM_PROT_WRITE);
191*1031c584SApple OSS Distributions 			}
192*1031c584SApple OSS Distributions 
193*1031c584SApple OSS Distributions 			if (ret != KERN_SUCCESS) {
194*1031c584SApple OSS Distributions 				goto done;
195*1031c584SApple OSS Distributions 			}
196*1031c584SApple OSS Distributions 		} else {
197*1031c584SApple OSS Distributions 			/* The memory was already writable. */
198*1031c584SApple OSS Distributions 			reprotect = VM_PROT_NONE;
199*1031c584SApple OSS Distributions 		}
200*1031c584SApple OSS Distributions 
201*1031c584SApple OSS Distributions 		ret = vm_map_write_user( map,
202*1031c584SApple OSS Distributions 		    buf,
203*1031c584SApple OSS Distributions 		    (vm_map_address_t)a,
204*1031c584SApple OSS Distributions 		    (vm_size_t)len);
205*1031c584SApple OSS Distributions 
206*1031c584SApple OSS Distributions 		dtrace_flush_caches();
207*1031c584SApple OSS Distributions 
208*1031c584SApple OSS Distributions 		if (ret != KERN_SUCCESS) {
209*1031c584SApple OSS Distributions 			goto done;
210*1031c584SApple OSS Distributions 		}
211*1031c584SApple OSS Distributions 
212*1031c584SApple OSS Distributions 		if (reprotect != VM_PROT_NONE) {
213*1031c584SApple OSS Distributions 			ASSERT(reprotect & VM_PROT_EXECUTE);
214*1031c584SApple OSS Distributions 			ret = mach_vm_protect(map, (mach_vm_offset_t)a, (mach_vm_size_t)len, 0, reprotect);
215*1031c584SApple OSS Distributions 		}
216*1031c584SApple OSS Distributions 
217*1031c584SApple OSS Distributions done:
218*1031c584SApple OSS Distributions 		vm_map_deallocate(map);
219*1031c584SApple OSS Distributions 	} else {
220*1031c584SApple OSS Distributions 		ret = KERN_TERMINATED;
221*1031c584SApple OSS Distributions 	}
222*1031c584SApple OSS Distributions 
223*1031c584SApple OSS Distributions 	return (int)ret;
224*1031c584SApple OSS Distributions }
225*1031c584SApple OSS Distributions 
226*1031c584SApple OSS Distributions /*
227*1031c584SApple OSS Distributions  * cpuvar
228*1031c584SApple OSS Distributions  */
229*1031c584SApple OSS Distributions LCK_MTX_DECLARE_ATTR(cpu_lock, &dtrace_lck_grp, &dtrace_lck_attr);
230*1031c584SApple OSS Distributions LCK_MTX_DECLARE_ATTR(cyc_lock, &dtrace_lck_grp, &dtrace_lck_attr);
231*1031c584SApple OSS Distributions LCK_MTX_DECLARE_ATTR(mod_lock, &dtrace_lck_grp, &dtrace_lck_attr);
232*1031c584SApple OSS Distributions 
233*1031c584SApple OSS Distributions dtrace_cpu_t *cpu_list;
234*1031c584SApple OSS Distributions cpu_core_t *cpu_core; /* XXX TLB lockdown? */
235*1031c584SApple OSS Distributions 
236*1031c584SApple OSS Distributions /*
237*1031c584SApple OSS Distributions  * cred_t
238*1031c584SApple OSS Distributions  */
239*1031c584SApple OSS Distributions 
240*1031c584SApple OSS Distributions /*
241*1031c584SApple OSS Distributions  * dtrace_CRED() can be called from probe context. We cannot simply call kauth_cred_get() since
242*1031c584SApple OSS Distributions  * that function may try to resolve a lazy credential binding, which entails taking the proc_lock.
243*1031c584SApple OSS Distributions  */
244*1031c584SApple OSS Distributions cred_t *
dtrace_CRED(void)245*1031c584SApple OSS Distributions dtrace_CRED(void)
246*1031c584SApple OSS Distributions {
247*1031c584SApple OSS Distributions 	return current_thread_ro_unchecked()->tro_cred;
248*1031c584SApple OSS Distributions }
249*1031c584SApple OSS Distributions 
250*1031c584SApple OSS Distributions int
PRIV_POLICY_CHOICE(void * cred,int priv,int all)251*1031c584SApple OSS Distributions PRIV_POLICY_CHOICE(void* cred, int priv, int all)
252*1031c584SApple OSS Distributions {
253*1031c584SApple OSS Distributions #pragma unused(priv, all)
254*1031c584SApple OSS Distributions 	return kauth_cred_issuser(cred); /* XXX TODO: How is this different from PRIV_POLICY_ONLY? */
255*1031c584SApple OSS Distributions }
256*1031c584SApple OSS Distributions 
257*1031c584SApple OSS Distributions int
PRIV_POLICY_ONLY(void * cr,int priv,int boolean)258*1031c584SApple OSS Distributions PRIV_POLICY_ONLY(void *cr, int priv, int boolean)
259*1031c584SApple OSS Distributions {
260*1031c584SApple OSS Distributions #pragma unused(priv, boolean)
261*1031c584SApple OSS Distributions 	return kauth_cred_issuser(cr); /* XXX TODO: HAS_PRIVILEGE(cr, priv); */
262*1031c584SApple OSS Distributions }
263*1031c584SApple OSS Distributions 
264*1031c584SApple OSS Distributions uid_t
crgetuid(const cred_t * cr)265*1031c584SApple OSS Distributions crgetuid(const cred_t *cr)
266*1031c584SApple OSS Distributions {
267*1031c584SApple OSS Distributions 	cred_t copy_cr = *cr; return kauth_cred_getuid(&copy_cr);
268*1031c584SApple OSS Distributions }
269*1031c584SApple OSS Distributions 
270*1031c584SApple OSS Distributions /*
271*1031c584SApple OSS Distributions  * "cyclic"
272*1031c584SApple OSS Distributions  */
273*1031c584SApple OSS Distributions 
274*1031c584SApple OSS Distributions typedef struct wrap_timer_call {
275*1031c584SApple OSS Distributions 	/* node attributes */
276*1031c584SApple OSS Distributions 	cyc_handler_t           hdlr;
277*1031c584SApple OSS Distributions 	cyc_time_t              when;
278*1031c584SApple OSS Distributions 	uint64_t                deadline;
279*1031c584SApple OSS Distributions 	int                     cpuid;
280*1031c584SApple OSS Distributions 	boolean_t               suspended;
281*1031c584SApple OSS Distributions 	struct timer_call       call;
282*1031c584SApple OSS Distributions 
283*1031c584SApple OSS Distributions 	/* next item in the linked list */
284*1031c584SApple OSS Distributions 	LIST_ENTRY(wrap_timer_call) entries;
285*1031c584SApple OSS Distributions } wrap_timer_call_t;
286*1031c584SApple OSS Distributions 
287*1031c584SApple OSS Distributions #define WAKEUP_REAPER           0x7FFFFFFFFFFFFFFFLL
288*1031c584SApple OSS Distributions #define NEARLY_FOREVER          0x7FFFFFFFFFFFFFFELL
289*1031c584SApple OSS Distributions 
290*1031c584SApple OSS Distributions 
291*1031c584SApple OSS Distributions typedef struct cyc_list {
292*1031c584SApple OSS Distributions 	cyc_omni_handler_t cyl_omni;
293*1031c584SApple OSS Distributions 	wrap_timer_call_t cyl_wrap_by_cpus[];
294*1031c584SApple OSS Distributions } cyc_list_t;
295*1031c584SApple OSS Distributions 
296*1031c584SApple OSS Distributions /* CPU going online/offline notifications */
297*1031c584SApple OSS Distributions void (*dtrace_cpu_state_changed_hook)(int, boolean_t) = NULL;
298*1031c584SApple OSS Distributions void dtrace_cpu_state_changed(int, boolean_t);
299*1031c584SApple OSS Distributions 
300*1031c584SApple OSS Distributions void
dtrace_install_cpu_hooks(void)301*1031c584SApple OSS Distributions dtrace_install_cpu_hooks(void)
302*1031c584SApple OSS Distributions {
303*1031c584SApple OSS Distributions 	dtrace_cpu_state_changed_hook = dtrace_cpu_state_changed;
304*1031c584SApple OSS Distributions }
305*1031c584SApple OSS Distributions 
306*1031c584SApple OSS Distributions void
dtrace_cpu_state_changed(int cpuid,boolean_t is_running)307*1031c584SApple OSS Distributions dtrace_cpu_state_changed(int cpuid, boolean_t is_running)
308*1031c584SApple OSS Distributions {
309*1031c584SApple OSS Distributions 	wrap_timer_call_t       *wrapTC = NULL;
310*1031c584SApple OSS Distributions 	boolean_t               suspend = (is_running ? FALSE : TRUE);
311*1031c584SApple OSS Distributions 	dtrace_icookie_t        s;
312*1031c584SApple OSS Distributions 
313*1031c584SApple OSS Distributions 	/* Ensure that we're not going to leave the CPU */
314*1031c584SApple OSS Distributions 	s = dtrace_interrupt_disable();
315*1031c584SApple OSS Distributions 
316*1031c584SApple OSS Distributions 	LIST_FOREACH(wrapTC, &(cpu_list[cpuid].cpu_cyc_list), entries) {
317*1031c584SApple OSS Distributions 		assert3u(wrapTC->cpuid, ==, cpuid);
318*1031c584SApple OSS Distributions 		if (suspend) {
319*1031c584SApple OSS Distributions 			assert(!wrapTC->suspended);
320*1031c584SApple OSS Distributions 			/* If this fails, we'll panic anyway, so let's do this now. */
321*1031c584SApple OSS Distributions 			if (!timer_call_cancel(&wrapTC->call)) {
322*1031c584SApple OSS Distributions 				panic("timer_call_cancel() failed to cancel a timer call: %p",
323*1031c584SApple OSS Distributions 				    &wrapTC->call);
324*1031c584SApple OSS Distributions 			}
325*1031c584SApple OSS Distributions 			wrapTC->suspended = TRUE;
326*1031c584SApple OSS Distributions 		} else {
327*1031c584SApple OSS Distributions 			/* Rearm the timer, but ensure it was suspended first. */
328*1031c584SApple OSS Distributions 			assert(wrapTC->suspended);
329*1031c584SApple OSS Distributions 			clock_deadline_for_periodic_event(wrapTC->when.cyt_interval, mach_absolute_time(),
330*1031c584SApple OSS Distributions 			    &wrapTC->deadline);
331*1031c584SApple OSS Distributions 			timer_call_enter1(&wrapTC->call, (void*) wrapTC, wrapTC->deadline,
332*1031c584SApple OSS Distributions 			    TIMER_CALL_SYS_CRITICAL | TIMER_CALL_LOCAL);
333*1031c584SApple OSS Distributions 			wrapTC->suspended = FALSE;
334*1031c584SApple OSS Distributions 		}
335*1031c584SApple OSS Distributions 	}
336*1031c584SApple OSS Distributions 
337*1031c584SApple OSS Distributions 	/* Restore the previous interrupt state. */
338*1031c584SApple OSS Distributions 	dtrace_interrupt_enable(s);
339*1031c584SApple OSS Distributions }
340*1031c584SApple OSS Distributions 
341*1031c584SApple OSS Distributions static void
_timer_call_apply_cyclic(void * ignore,void * vTChdl)342*1031c584SApple OSS Distributions _timer_call_apply_cyclic( void *ignore, void *vTChdl )
343*1031c584SApple OSS Distributions {
344*1031c584SApple OSS Distributions #pragma unused(ignore)
345*1031c584SApple OSS Distributions 	wrap_timer_call_t *wrapTC = (wrap_timer_call_t *)vTChdl;
346*1031c584SApple OSS Distributions 
347*1031c584SApple OSS Distributions 	(*(wrapTC->hdlr.cyh_func))( wrapTC->hdlr.cyh_arg );
348*1031c584SApple OSS Distributions 
349*1031c584SApple OSS Distributions 	clock_deadline_for_periodic_event( wrapTC->when.cyt_interval, mach_absolute_time(), &(wrapTC->deadline));
350*1031c584SApple OSS Distributions 	timer_call_enter1( &(wrapTC->call), (void *)wrapTC, wrapTC->deadline, TIMER_CALL_SYS_CRITICAL | TIMER_CALL_LOCAL );
351*1031c584SApple OSS Distributions }
352*1031c584SApple OSS Distributions 
353*1031c584SApple OSS Distributions static cyclic_id_t
timer_call_add_cyclic(wrap_timer_call_t * wrapTC,cyc_handler_t * handler,cyc_time_t * when)354*1031c584SApple OSS Distributions timer_call_add_cyclic(wrap_timer_call_t *wrapTC, cyc_handler_t *handler, cyc_time_t *when)
355*1031c584SApple OSS Distributions {
356*1031c584SApple OSS Distributions 	uint64_t now;
357*1031c584SApple OSS Distributions 	dtrace_icookie_t s;
358*1031c584SApple OSS Distributions 
359*1031c584SApple OSS Distributions 	timer_call_setup( &(wrapTC->call), _timer_call_apply_cyclic, NULL );
360*1031c584SApple OSS Distributions 	wrapTC->hdlr = *handler;
361*1031c584SApple OSS Distributions 	wrapTC->when = *when;
362*1031c584SApple OSS Distributions 
363*1031c584SApple OSS Distributions 	nanoseconds_to_absolutetime( wrapTC->when.cyt_interval, (uint64_t *)&wrapTC->when.cyt_interval );
364*1031c584SApple OSS Distributions 
365*1031c584SApple OSS Distributions 	now = mach_absolute_time();
366*1031c584SApple OSS Distributions 	wrapTC->deadline = now;
367*1031c584SApple OSS Distributions 
368*1031c584SApple OSS Distributions 	clock_deadline_for_periodic_event( wrapTC->when.cyt_interval, now, &(wrapTC->deadline));
369*1031c584SApple OSS Distributions 
370*1031c584SApple OSS Distributions 	/* Insert the timer to the list of the running timers on this CPU, and start it. */
371*1031c584SApple OSS Distributions 	s = dtrace_interrupt_disable();
372*1031c584SApple OSS Distributions 	wrapTC->cpuid = cpu_number();
373*1031c584SApple OSS Distributions 	LIST_INSERT_HEAD(&cpu_list[wrapTC->cpuid].cpu_cyc_list, wrapTC, entries);
374*1031c584SApple OSS Distributions 	timer_call_enter1(&wrapTC->call, (void*) wrapTC, wrapTC->deadline,
375*1031c584SApple OSS Distributions 	    TIMER_CALL_SYS_CRITICAL | TIMER_CALL_LOCAL);
376*1031c584SApple OSS Distributions 	wrapTC->suspended = FALSE;
377*1031c584SApple OSS Distributions 	dtrace_interrupt_enable(s);
378*1031c584SApple OSS Distributions 
379*1031c584SApple OSS Distributions 	return (cyclic_id_t)wrapTC;
380*1031c584SApple OSS Distributions }
381*1031c584SApple OSS Distributions 
382*1031c584SApple OSS Distributions /*
383*1031c584SApple OSS Distributions  * Executed on the CPU the timer is running on.
384*1031c584SApple OSS Distributions  */
385*1031c584SApple OSS Distributions static void
timer_call_remove_cyclic(wrap_timer_call_t * wrapTC)386*1031c584SApple OSS Distributions timer_call_remove_cyclic(wrap_timer_call_t *wrapTC)
387*1031c584SApple OSS Distributions {
388*1031c584SApple OSS Distributions 	assert(wrapTC);
389*1031c584SApple OSS Distributions 	assert(cpu_number() == wrapTC->cpuid);
390*1031c584SApple OSS Distributions 
391*1031c584SApple OSS Distributions 	if (!timer_call_cancel(&wrapTC->call)) {
392*1031c584SApple OSS Distributions 		panic("timer_call_remove_cyclic() failed to cancel a timer call");
393*1031c584SApple OSS Distributions 	}
394*1031c584SApple OSS Distributions 
395*1031c584SApple OSS Distributions 	LIST_REMOVE(wrapTC, entries);
396*1031c584SApple OSS Distributions }
397*1031c584SApple OSS Distributions 
398*1031c584SApple OSS Distributions static void *
timer_call_get_cyclic_arg(wrap_timer_call_t * wrapTC)399*1031c584SApple OSS Distributions timer_call_get_cyclic_arg(wrap_timer_call_t *wrapTC)
400*1031c584SApple OSS Distributions {
401*1031c584SApple OSS Distributions 	return wrapTC ? wrapTC->hdlr.cyh_arg : NULL;
402*1031c584SApple OSS Distributions }
403*1031c584SApple OSS Distributions 
404*1031c584SApple OSS Distributions cyclic_id_t
cyclic_timer_add(cyc_handler_t * handler,cyc_time_t * when)405*1031c584SApple OSS Distributions cyclic_timer_add(cyc_handler_t *handler, cyc_time_t *when)
406*1031c584SApple OSS Distributions {
407*1031c584SApple OSS Distributions 	wrap_timer_call_t *wrapTC = kalloc_type(wrap_timer_call_t, Z_ZERO | Z_WAITOK);
408*1031c584SApple OSS Distributions 	if (NULL == wrapTC) {
409*1031c584SApple OSS Distributions 		return CYCLIC_NONE;
410*1031c584SApple OSS Distributions 	} else {
411*1031c584SApple OSS Distributions 		return timer_call_add_cyclic( wrapTC, handler, when );
412*1031c584SApple OSS Distributions 	}
413*1031c584SApple OSS Distributions }
414*1031c584SApple OSS Distributions 
415*1031c584SApple OSS Distributions void
cyclic_timer_remove(cyclic_id_t cyclic)416*1031c584SApple OSS Distributions cyclic_timer_remove(cyclic_id_t cyclic)
417*1031c584SApple OSS Distributions {
418*1031c584SApple OSS Distributions 	ASSERT( cyclic != CYCLIC_NONE );
419*1031c584SApple OSS Distributions 
420*1031c584SApple OSS Distributions 	/* Removing a timer call must be done on the CPU the timer is running on. */
421*1031c584SApple OSS Distributions 	wrap_timer_call_t *wrapTC = (wrap_timer_call_t *) cyclic;
422*1031c584SApple OSS Distributions 	dtrace_xcall(wrapTC->cpuid, (dtrace_xcall_t) timer_call_remove_cyclic, (void*) cyclic);
423*1031c584SApple OSS Distributions 
424*1031c584SApple OSS Distributions 	kfree_type(wrap_timer_call_t, wrapTC);
425*1031c584SApple OSS Distributions }
426*1031c584SApple OSS Distributions 
427*1031c584SApple OSS Distributions static void
_cyclic_add_omni(cyc_list_t * cyc_list)428*1031c584SApple OSS Distributions _cyclic_add_omni(cyc_list_t *cyc_list)
429*1031c584SApple OSS Distributions {
430*1031c584SApple OSS Distributions 	cyc_time_t cT;
431*1031c584SApple OSS Distributions 	cyc_handler_t cH;
432*1031c584SApple OSS Distributions 	cyc_omni_handler_t *omni = &cyc_list->cyl_omni;
433*1031c584SApple OSS Distributions 
434*1031c584SApple OSS Distributions 	(omni->cyo_online)(omni->cyo_arg, CPU, &cH, &cT);
435*1031c584SApple OSS Distributions 
436*1031c584SApple OSS Distributions 	wrap_timer_call_t *wrapTC = &cyc_list->cyl_wrap_by_cpus[cpu_number()];
437*1031c584SApple OSS Distributions 	timer_call_add_cyclic(wrapTC, &cH, &cT);
438*1031c584SApple OSS Distributions }
439*1031c584SApple OSS Distributions 
440*1031c584SApple OSS Distributions cyclic_id_list_t
cyclic_add_omni(cyc_omni_handler_t * omni)441*1031c584SApple OSS Distributions cyclic_add_omni(cyc_omni_handler_t *omni)
442*1031c584SApple OSS Distributions {
443*1031c584SApple OSS Distributions 	cyc_list_t *cyc_list = kalloc_type(cyc_list_t, wrap_timer_call_t, NCPU, Z_WAITOK | Z_ZERO);
444*1031c584SApple OSS Distributions 
445*1031c584SApple OSS Distributions 	if (NULL == cyc_list) {
446*1031c584SApple OSS Distributions 		return NULL;
447*1031c584SApple OSS Distributions 	}
448*1031c584SApple OSS Distributions 
449*1031c584SApple OSS Distributions 	cyc_list->cyl_omni = *omni;
450*1031c584SApple OSS Distributions 
451*1031c584SApple OSS Distributions 	dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)_cyclic_add_omni, (void *)cyc_list);
452*1031c584SApple OSS Distributions 
453*1031c584SApple OSS Distributions 	return (cyclic_id_list_t)cyc_list;
454*1031c584SApple OSS Distributions }
455*1031c584SApple OSS Distributions 
456*1031c584SApple OSS Distributions static void
_cyclic_remove_omni(cyc_list_t * cyc_list)457*1031c584SApple OSS Distributions _cyclic_remove_omni(cyc_list_t *cyc_list)
458*1031c584SApple OSS Distributions {
459*1031c584SApple OSS Distributions 	cyc_omni_handler_t *omni = &cyc_list->cyl_omni;
460*1031c584SApple OSS Distributions 	void *oarg;
461*1031c584SApple OSS Distributions 	wrap_timer_call_t *wrapTC;
462*1031c584SApple OSS Distributions 
463*1031c584SApple OSS Distributions 	/*
464*1031c584SApple OSS Distributions 	 * If the processor was offline when dtrace started, we did not allocate
465*1031c584SApple OSS Distributions 	 * a cyclic timer for this CPU.
466*1031c584SApple OSS Distributions 	 */
467*1031c584SApple OSS Distributions 	if ((wrapTC = &cyc_list->cyl_wrap_by_cpus[cpu_number()]) != NULL) {
468*1031c584SApple OSS Distributions 		oarg = timer_call_get_cyclic_arg(wrapTC);
469*1031c584SApple OSS Distributions 		timer_call_remove_cyclic(wrapTC);
470*1031c584SApple OSS Distributions 		(omni->cyo_offline)(omni->cyo_arg, CPU, oarg);
471*1031c584SApple OSS Distributions 	}
472*1031c584SApple OSS Distributions }
473*1031c584SApple OSS Distributions 
474*1031c584SApple OSS Distributions void
cyclic_remove_omni(cyclic_id_list_t cyc_list)475*1031c584SApple OSS Distributions cyclic_remove_omni(cyclic_id_list_t cyc_list)
476*1031c584SApple OSS Distributions {
477*1031c584SApple OSS Distributions 	ASSERT(cyc_list != NULL);
478*1031c584SApple OSS Distributions 
479*1031c584SApple OSS Distributions 	dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)_cyclic_remove_omni, (void *)cyc_list);
480*1031c584SApple OSS Distributions 	void *cyc_list_p = (void *)cyc_list;
481*1031c584SApple OSS Distributions 	kfree_type(cyc_list_t, wrap_timer_call_t, NCPU, cyc_list_p);
482*1031c584SApple OSS Distributions }
483*1031c584SApple OSS Distributions 
484*1031c584SApple OSS Distributions typedef struct wrap_thread_call {
485*1031c584SApple OSS Distributions 	thread_call_t TChdl;
486*1031c584SApple OSS Distributions 	cyc_handler_t hdlr;
487*1031c584SApple OSS Distributions 	cyc_time_t when;
488*1031c584SApple OSS Distributions 	uint64_t deadline;
489*1031c584SApple OSS Distributions } wrap_thread_call_t;
490*1031c584SApple OSS Distributions 
491*1031c584SApple OSS Distributions /*
492*1031c584SApple OSS Distributions  * _cyclic_apply will run on some thread under kernel_task. That's OK for the
493*1031c584SApple OSS Distributions  * cleaner and the deadman, but too distant in time and place for the profile provider.
494*1031c584SApple OSS Distributions  */
495*1031c584SApple OSS Distributions static void
_cyclic_apply(void * ignore,void * vTChdl)496*1031c584SApple OSS Distributions _cyclic_apply( void *ignore, void *vTChdl )
497*1031c584SApple OSS Distributions {
498*1031c584SApple OSS Distributions #pragma unused(ignore)
499*1031c584SApple OSS Distributions 	wrap_thread_call_t *wrapTC = (wrap_thread_call_t *)vTChdl;
500*1031c584SApple OSS Distributions 
501*1031c584SApple OSS Distributions 	(*(wrapTC->hdlr.cyh_func))( wrapTC->hdlr.cyh_arg );
502*1031c584SApple OSS Distributions 
503*1031c584SApple OSS Distributions 	clock_deadline_for_periodic_event( wrapTC->when.cyt_interval, mach_absolute_time(), &(wrapTC->deadline));
504*1031c584SApple OSS Distributions 	(void)thread_call_enter1_delayed( wrapTC->TChdl, (void *)wrapTC, wrapTC->deadline );
505*1031c584SApple OSS Distributions 
506*1031c584SApple OSS Distributions 	/* Did cyclic_remove request a wakeup call when this thread call was re-armed? */
507*1031c584SApple OSS Distributions 	if (wrapTC->when.cyt_interval == WAKEUP_REAPER) {
508*1031c584SApple OSS Distributions 		thread_wakeup((event_t)wrapTC);
509*1031c584SApple OSS Distributions 	}
510*1031c584SApple OSS Distributions }
511*1031c584SApple OSS Distributions 
512*1031c584SApple OSS Distributions cyclic_id_t
cyclic_add(cyc_handler_t * handler,cyc_time_t * when)513*1031c584SApple OSS Distributions cyclic_add(cyc_handler_t *handler, cyc_time_t *when)
514*1031c584SApple OSS Distributions {
515*1031c584SApple OSS Distributions 	uint64_t now;
516*1031c584SApple OSS Distributions 
517*1031c584SApple OSS Distributions 	wrap_thread_call_t *wrapTC = kalloc_type(wrap_thread_call_t, Z_ZERO | Z_WAITOK);
518*1031c584SApple OSS Distributions 	if (NULL == wrapTC) {
519*1031c584SApple OSS Distributions 		return CYCLIC_NONE;
520*1031c584SApple OSS Distributions 	}
521*1031c584SApple OSS Distributions 
522*1031c584SApple OSS Distributions 	wrapTC->TChdl = thread_call_allocate( _cyclic_apply, NULL );
523*1031c584SApple OSS Distributions 	wrapTC->hdlr = *handler;
524*1031c584SApple OSS Distributions 	wrapTC->when = *when;
525*1031c584SApple OSS Distributions 
526*1031c584SApple OSS Distributions 	ASSERT(when->cyt_when == 0);
527*1031c584SApple OSS Distributions 	ASSERT(when->cyt_interval < WAKEUP_REAPER);
528*1031c584SApple OSS Distributions 
529*1031c584SApple OSS Distributions 	nanoseconds_to_absolutetime(wrapTC->when.cyt_interval, (uint64_t *)&wrapTC->when.cyt_interval);
530*1031c584SApple OSS Distributions 
531*1031c584SApple OSS Distributions 	now = mach_absolute_time();
532*1031c584SApple OSS Distributions 	wrapTC->deadline = now;
533*1031c584SApple OSS Distributions 
534*1031c584SApple OSS Distributions 	clock_deadline_for_periodic_event( wrapTC->when.cyt_interval, now, &(wrapTC->deadline));
535*1031c584SApple OSS Distributions 	(void)thread_call_enter1_delayed( wrapTC->TChdl, (void *)wrapTC, wrapTC->deadline );
536*1031c584SApple OSS Distributions 
537*1031c584SApple OSS Distributions 	return (cyclic_id_t)wrapTC;
538*1031c584SApple OSS Distributions }
539*1031c584SApple OSS Distributions 
540*1031c584SApple OSS Distributions static void
noop_cyh_func(void * ignore)541*1031c584SApple OSS Distributions noop_cyh_func(void * ignore)
542*1031c584SApple OSS Distributions {
543*1031c584SApple OSS Distributions #pragma unused(ignore)
544*1031c584SApple OSS Distributions }
545*1031c584SApple OSS Distributions 
546*1031c584SApple OSS Distributions void
cyclic_remove(cyclic_id_t cyclic)547*1031c584SApple OSS Distributions cyclic_remove(cyclic_id_t cyclic)
548*1031c584SApple OSS Distributions {
549*1031c584SApple OSS Distributions 	wrap_thread_call_t *wrapTC = (wrap_thread_call_t *)cyclic;
550*1031c584SApple OSS Distributions 
551*1031c584SApple OSS Distributions 	ASSERT(cyclic != CYCLIC_NONE);
552*1031c584SApple OSS Distributions 
553*1031c584SApple OSS Distributions 	while (!thread_call_cancel(wrapTC->TChdl)) {
554*1031c584SApple OSS Distributions 		int ret = assert_wait(wrapTC, THREAD_UNINT);
555*1031c584SApple OSS Distributions 		ASSERT(ret == THREAD_WAITING);
556*1031c584SApple OSS Distributions 
557*1031c584SApple OSS Distributions 		wrapTC->when.cyt_interval = WAKEUP_REAPER;
558*1031c584SApple OSS Distributions 
559*1031c584SApple OSS Distributions 		ret = thread_block(THREAD_CONTINUE_NULL);
560*1031c584SApple OSS Distributions 		ASSERT(ret == THREAD_AWAKENED);
561*1031c584SApple OSS Distributions 	}
562*1031c584SApple OSS Distributions 
563*1031c584SApple OSS Distributions 	if (thread_call_free(wrapTC->TChdl)) {
564*1031c584SApple OSS Distributions 		kfree_type(wrap_thread_call_t, wrapTC);
565*1031c584SApple OSS Distributions 	} else {
566*1031c584SApple OSS Distributions 		/* Gut this cyclic and move on ... */
567*1031c584SApple OSS Distributions 		wrapTC->hdlr.cyh_func = noop_cyh_func;
568*1031c584SApple OSS Distributions 		wrapTC->when.cyt_interval = NEARLY_FOREVER;
569*1031c584SApple OSS Distributions 	}
570*1031c584SApple OSS Distributions }
571*1031c584SApple OSS Distributions 
572*1031c584SApple OSS Distributions int
ddi_driver_major(dev_info_t * devi)573*1031c584SApple OSS Distributions ddi_driver_major(dev_info_t     *devi)
574*1031c584SApple OSS Distributions {
575*1031c584SApple OSS Distributions 	return (int)major(CAST_DOWN_EXPLICIT(int, devi));
576*1031c584SApple OSS Distributions }
577*1031c584SApple OSS Distributions 
578*1031c584SApple OSS Distributions int
ddi_create_minor_node(dev_info_t * dip,const char * name,int spec_type,minor_t minor_num,const char * node_type,int flag)579*1031c584SApple OSS Distributions ddi_create_minor_node(dev_info_t *dip, const char *name, int spec_type,
580*1031c584SApple OSS Distributions     minor_t minor_num, const char *node_type, int flag)
581*1031c584SApple OSS Distributions {
582*1031c584SApple OSS Distributions #pragma unused(spec_type,node_type,flag)
583*1031c584SApple OSS Distributions 	dev_t dev = makedev( ddi_driver_major(dip), minor_num );
584*1031c584SApple OSS Distributions 
585*1031c584SApple OSS Distributions 	if (NULL == devfs_make_node( dev, DEVFS_CHAR, UID_ROOT, GID_WHEEL, 0666, "%s", name )) {
586*1031c584SApple OSS Distributions 		return DDI_FAILURE;
587*1031c584SApple OSS Distributions 	} else {
588*1031c584SApple OSS Distributions 		return DDI_SUCCESS;
589*1031c584SApple OSS Distributions 	}
590*1031c584SApple OSS Distributions }
591*1031c584SApple OSS Distributions 
592*1031c584SApple OSS Distributions void
ddi_remove_minor_node(dev_info_t * dip,char * name)593*1031c584SApple OSS Distributions ddi_remove_minor_node(dev_info_t *dip, char *name)
594*1031c584SApple OSS Distributions {
595*1031c584SApple OSS Distributions #pragma unused(dip,name)
596*1031c584SApple OSS Distributions /* XXX called from dtrace_detach, so NOTREACHED for now. */
597*1031c584SApple OSS Distributions }
598*1031c584SApple OSS Distributions 
599*1031c584SApple OSS Distributions major_t
getemajor(dev_t d)600*1031c584SApple OSS Distributions getemajor( dev_t d )
601*1031c584SApple OSS Distributions {
602*1031c584SApple OSS Distributions 	return (major_t) major(d);
603*1031c584SApple OSS Distributions }
604*1031c584SApple OSS Distributions 
605*1031c584SApple OSS Distributions minor_t
getminor(dev_t d)606*1031c584SApple OSS Distributions getminor( dev_t d )
607*1031c584SApple OSS Distributions {
608*1031c584SApple OSS Distributions 	return (minor_t) minor(d);
609*1031c584SApple OSS Distributions }
610*1031c584SApple OSS Distributions 
611*1031c584SApple OSS Distributions extern void Debugger(const char*);
612*1031c584SApple OSS Distributions 
613*1031c584SApple OSS Distributions void
debug_enter(char * c)614*1031c584SApple OSS Distributions debug_enter(char *c)
615*1031c584SApple OSS Distributions {
616*1031c584SApple OSS Distributions 	Debugger(c);
617*1031c584SApple OSS Distributions }
618*1031c584SApple OSS Distributions 
619*1031c584SApple OSS Distributions /*
620*1031c584SApple OSS Distributions  * kmem
621*1031c584SApple OSS Distributions  */
622*1031c584SApple OSS Distributions 
623*1031c584SApple OSS Distributions // rdar://88962505
624*1031c584SApple OSS Distributions __typed_allocators_ignore_push
625*1031c584SApple OSS Distributions 
626*1031c584SApple OSS Distributions void *
dt_kmem_alloc_tag(size_t size,int kmflag,vm_tag_t tag)627*1031c584SApple OSS Distributions dt_kmem_alloc_tag(size_t size, int kmflag, vm_tag_t tag)
628*1031c584SApple OSS Distributions {
629*1031c584SApple OSS Distributions #pragma unused(kmflag)
630*1031c584SApple OSS Distributions 
631*1031c584SApple OSS Distributions /*
632*1031c584SApple OSS Distributions  * We ignore the M_NOWAIT bit in kmflag (all of kmflag, in fact).
633*1031c584SApple OSS Distributions  * Requests larger than 8K with M_NOWAIT fail in kalloc_ext.
634*1031c584SApple OSS Distributions  */
635*1031c584SApple OSS Distributions 	return kheap_alloc_tag(KHEAP_DTRACE, size, Z_WAITOK, tag);
636*1031c584SApple OSS Distributions }
637*1031c584SApple OSS Distributions 
638*1031c584SApple OSS Distributions void *
dt_kmem_zalloc_tag(size_t size,int kmflag,vm_tag_t tag)639*1031c584SApple OSS Distributions dt_kmem_zalloc_tag(size_t size, int kmflag, vm_tag_t tag)
640*1031c584SApple OSS Distributions {
641*1031c584SApple OSS Distributions #pragma unused(kmflag)
642*1031c584SApple OSS Distributions 
643*1031c584SApple OSS Distributions /*
644*1031c584SApple OSS Distributions  * We ignore the M_NOWAIT bit in kmflag (all of kmflag, in fact).
645*1031c584SApple OSS Distributions  * Requests larger than 8K with M_NOWAIT fail in kalloc_ext.
646*1031c584SApple OSS Distributions  */
647*1031c584SApple OSS Distributions 	return kheap_alloc_tag(KHEAP_DTRACE, size, Z_WAITOK | Z_ZERO, tag);
648*1031c584SApple OSS Distributions }
649*1031c584SApple OSS Distributions 
650*1031c584SApple OSS Distributions void
dt_kmem_free(void * buf,size_t size)651*1031c584SApple OSS Distributions dt_kmem_free(void *buf, size_t size)
652*1031c584SApple OSS Distributions {
653*1031c584SApple OSS Distributions 	kheap_free(KHEAP_DTRACE, buf, size);
654*1031c584SApple OSS Distributions }
655*1031c584SApple OSS Distributions 
656*1031c584SApple OSS Distributions __typed_allocators_ignore_pop
657*1031c584SApple OSS Distributions 
658*1031c584SApple OSS Distributions 
659*1031c584SApple OSS Distributions /*
660*1031c584SApple OSS Distributions  * aligned dt_kmem allocator
661*1031c584SApple OSS Distributions  * align should be a power of two
662*1031c584SApple OSS Distributions  */
663*1031c584SApple OSS Distributions 
664*1031c584SApple OSS Distributions void*
dt_kmem_alloc_aligned_tag(size_t size,size_t align,int kmflag,vm_tag_t tag)665*1031c584SApple OSS Distributions dt_kmem_alloc_aligned_tag(size_t size, size_t align, int kmflag, vm_tag_t tag)
666*1031c584SApple OSS Distributions {
667*1031c584SApple OSS Distributions 	void *mem, **addr_to_free;
668*1031c584SApple OSS Distributions 	intptr_t mem_aligned;
669*1031c584SApple OSS Distributions 	size_t *size_to_free, hdr_size;
670*1031c584SApple OSS Distributions 
671*1031c584SApple OSS Distributions 	/* Must be a power of two. */
672*1031c584SApple OSS Distributions 	assert(align != 0);
673*1031c584SApple OSS Distributions 	assert((align & (align - 1)) == 0);
674*1031c584SApple OSS Distributions 
675*1031c584SApple OSS Distributions 	/*
676*1031c584SApple OSS Distributions 	 * We are going to add a header to the allocation. It contains
677*1031c584SApple OSS Distributions 	 * the address to free and the total size of the buffer.
678*1031c584SApple OSS Distributions 	 */
679*1031c584SApple OSS Distributions 	hdr_size = sizeof(size_t) + sizeof(void*);
680*1031c584SApple OSS Distributions 	mem = dt_kmem_alloc_tag(size + align + hdr_size, kmflag, tag);
681*1031c584SApple OSS Distributions 	if (mem == NULL) {
682*1031c584SApple OSS Distributions 		return NULL;
683*1031c584SApple OSS Distributions 	}
684*1031c584SApple OSS Distributions 
685*1031c584SApple OSS Distributions 	mem_aligned = (intptr_t) (((intptr_t) mem + align + hdr_size) & ~(align - 1));
686*1031c584SApple OSS Distributions 
687*1031c584SApple OSS Distributions 	/* Write the address to free in the header. */
688*1031c584SApple OSS Distributions 	addr_to_free = (void**) (mem_aligned - sizeof(void*));
689*1031c584SApple OSS Distributions 	*addr_to_free = mem;
690*1031c584SApple OSS Distributions 
691*1031c584SApple OSS Distributions 	/* Write the size to free in the header. */
692*1031c584SApple OSS Distributions 	size_to_free = (size_t*) (mem_aligned - hdr_size);
693*1031c584SApple OSS Distributions 	*size_to_free = size + align + hdr_size;
694*1031c584SApple OSS Distributions 
695*1031c584SApple OSS Distributions 	return (void*) mem_aligned;
696*1031c584SApple OSS Distributions }
697*1031c584SApple OSS Distributions 
698*1031c584SApple OSS Distributions void*
dt_kmem_zalloc_aligned_tag(size_t size,size_t align,int kmflag,vm_tag_t tag)699*1031c584SApple OSS Distributions dt_kmem_zalloc_aligned_tag(size_t size, size_t align, int kmflag, vm_tag_t tag)
700*1031c584SApple OSS Distributions {
701*1031c584SApple OSS Distributions 	void* buf;
702*1031c584SApple OSS Distributions 
703*1031c584SApple OSS Distributions 	buf = dt_kmem_alloc_aligned_tag(size, align, kmflag, tag);
704*1031c584SApple OSS Distributions 
705*1031c584SApple OSS Distributions 	if (!buf) {
706*1031c584SApple OSS Distributions 		return NULL;
707*1031c584SApple OSS Distributions 	}
708*1031c584SApple OSS Distributions 
709*1031c584SApple OSS Distributions 	bzero(buf, size);
710*1031c584SApple OSS Distributions 
711*1031c584SApple OSS Distributions 	return buf;
712*1031c584SApple OSS Distributions }
713*1031c584SApple OSS Distributions 
714*1031c584SApple OSS Distributions void
dt_kmem_free_aligned(void * buf,size_t size)715*1031c584SApple OSS Distributions dt_kmem_free_aligned(void* buf, size_t size)
716*1031c584SApple OSS Distributions {
717*1031c584SApple OSS Distributions #pragma unused(size)
718*1031c584SApple OSS Distributions 	intptr_t ptr = (intptr_t) buf;
719*1031c584SApple OSS Distributions 	void **addr_to_free = (void**) (ptr - sizeof(void*));
720*1031c584SApple OSS Distributions 	size_t *size_to_free = (size_t*) (ptr - (sizeof(size_t) + sizeof(void*)));
721*1031c584SApple OSS Distributions 
722*1031c584SApple OSS Distributions 	if (buf == NULL) {
723*1031c584SApple OSS Distributions 		return;
724*1031c584SApple OSS Distributions 	}
725*1031c584SApple OSS Distributions 
726*1031c584SApple OSS Distributions 	dt_kmem_free(*addr_to_free, *size_to_free);
727*1031c584SApple OSS Distributions }
728*1031c584SApple OSS Distributions 
729*1031c584SApple OSS Distributions /*
730*1031c584SApple OSS Distributions  * vmem (Solaris "slab" allocator) used by DTrace solely to hand out resource ids
731*1031c584SApple OSS Distributions  */
732*1031c584SApple OSS Distributions typedef unsigned int u_daddr_t;
733*1031c584SApple OSS Distributions #include "blist.h"
734*1031c584SApple OSS Distributions 
735*1031c584SApple OSS Distributions /* By passing around blist *handles*, the underlying blist can be resized as needed. */
736*1031c584SApple OSS Distributions struct blist_hdl {
737*1031c584SApple OSS Distributions 	blist_t blist;
738*1031c584SApple OSS Distributions };
739*1031c584SApple OSS Distributions 
740*1031c584SApple OSS Distributions vmem_t *
vmem_create(const char * name,void * base,size_t size,size_t quantum,void * ignore5,void * ignore6,vmem_t * source,size_t qcache_max,int vmflag)741*1031c584SApple OSS Distributions vmem_create(const char *name, void *base, size_t size, size_t quantum, void *ignore5,
742*1031c584SApple OSS Distributions     void *ignore6, vmem_t *source, size_t qcache_max, int vmflag)
743*1031c584SApple OSS Distributions {
744*1031c584SApple OSS Distributions #pragma unused(name,quantum,ignore5,ignore6,source,qcache_max,vmflag)
745*1031c584SApple OSS Distributions 	blist_t bl;
746*1031c584SApple OSS Distributions 	struct blist_hdl *p = kalloc_type(struct blist_hdl, Z_WAITOK);
747*1031c584SApple OSS Distributions 
748*1031c584SApple OSS Distributions 	ASSERT(quantum == 1);
749*1031c584SApple OSS Distributions 	ASSERT(NULL == ignore5);
750*1031c584SApple OSS Distributions 	ASSERT(NULL == ignore6);
751*1031c584SApple OSS Distributions 	ASSERT(NULL == source);
752*1031c584SApple OSS Distributions 	ASSERT(0 == qcache_max);
753*1031c584SApple OSS Distributions 	ASSERT(size <= INT32_MAX);
754*1031c584SApple OSS Distributions 	ASSERT(vmflag & VMC_IDENTIFIER);
755*1031c584SApple OSS Distributions 
756*1031c584SApple OSS Distributions 	size = MIN(128, size); /* Clamp to 128 initially, since the underlying data structure is pre-allocated */
757*1031c584SApple OSS Distributions 
758*1031c584SApple OSS Distributions 	p->blist = bl = blist_create((daddr_t)size);
759*1031c584SApple OSS Distributions 	blist_free(bl, 0, (daddr_t)size);
760*1031c584SApple OSS Distributions 	if (base) {
761*1031c584SApple OSS Distributions 		blist_alloc( bl, (daddr_t)(uintptr_t)base );   /* Chomp off initial ID(s) */
762*1031c584SApple OSS Distributions 	}
763*1031c584SApple OSS Distributions 	return (vmem_t *)p;
764*1031c584SApple OSS Distributions }
765*1031c584SApple OSS Distributions 
766*1031c584SApple OSS Distributions void *
vmem_alloc(vmem_t * vmp,size_t size,int vmflag)767*1031c584SApple OSS Distributions vmem_alloc(vmem_t *vmp, size_t size, int vmflag)
768*1031c584SApple OSS Distributions {
769*1031c584SApple OSS Distributions #pragma unused(vmflag)
770*1031c584SApple OSS Distributions 	struct blist_hdl *q = (struct blist_hdl *)vmp;
771*1031c584SApple OSS Distributions 	blist_t bl = q->blist;
772*1031c584SApple OSS Distributions 	daddr_t p;
773*1031c584SApple OSS Distributions 
774*1031c584SApple OSS Distributions 	p = blist_alloc(bl, (daddr_t)size);
775*1031c584SApple OSS Distributions 
776*1031c584SApple OSS Distributions 	if (p == SWAPBLK_NONE) {
777*1031c584SApple OSS Distributions 		blist_resize(&bl, (bl->bl_blocks) << 1, 1);
778*1031c584SApple OSS Distributions 		q->blist = bl;
779*1031c584SApple OSS Distributions 		p = blist_alloc(bl, (daddr_t)size);
780*1031c584SApple OSS Distributions 		if (p == SWAPBLK_NONE) {
781*1031c584SApple OSS Distributions 			panic("vmem_alloc: failure after blist_resize!");
782*1031c584SApple OSS Distributions 		}
783*1031c584SApple OSS Distributions 	}
784*1031c584SApple OSS Distributions 
785*1031c584SApple OSS Distributions 	return (void *)(uintptr_t)p;
786*1031c584SApple OSS Distributions }
787*1031c584SApple OSS Distributions 
788*1031c584SApple OSS Distributions void
vmem_free(vmem_t * vmp,void * vaddr,size_t size)789*1031c584SApple OSS Distributions vmem_free(vmem_t *vmp, void *vaddr, size_t size)
790*1031c584SApple OSS Distributions {
791*1031c584SApple OSS Distributions 	struct blist_hdl *p = (struct blist_hdl *)vmp;
792*1031c584SApple OSS Distributions 
793*1031c584SApple OSS Distributions 	blist_free( p->blist, (daddr_t)(uintptr_t)vaddr, (daddr_t)size );
794*1031c584SApple OSS Distributions }
795*1031c584SApple OSS Distributions 
796*1031c584SApple OSS Distributions void
vmem_destroy(vmem_t * vmp)797*1031c584SApple OSS Distributions vmem_destroy(vmem_t *vmp)
798*1031c584SApple OSS Distributions {
799*1031c584SApple OSS Distributions 	struct blist_hdl *p = (struct blist_hdl *)vmp;
800*1031c584SApple OSS Distributions 
801*1031c584SApple OSS Distributions 	blist_destroy( p->blist );
802*1031c584SApple OSS Distributions 	kfree_type(struct blist_hdl, p);
803*1031c584SApple OSS Distributions }
804*1031c584SApple OSS Distributions 
805*1031c584SApple OSS Distributions /*
806*1031c584SApple OSS Distributions  * Timing
807*1031c584SApple OSS Distributions  */
808*1031c584SApple OSS Distributions 
809*1031c584SApple OSS Distributions /*
810*1031c584SApple OSS Distributions  * dtrace_gethrestime() provides the "walltimestamp", a value that is anchored at
811*1031c584SApple OSS Distributions  * January 1, 1970. Because it can be called from probe context, it must take no locks.
812*1031c584SApple OSS Distributions  */
813*1031c584SApple OSS Distributions 
814*1031c584SApple OSS Distributions hrtime_t
dtrace_gethrestime(void)815*1031c584SApple OSS Distributions dtrace_gethrestime(void)
816*1031c584SApple OSS Distributions {
817*1031c584SApple OSS Distributions 	clock_sec_t             secs;
818*1031c584SApple OSS Distributions 	clock_nsec_t    nanosecs;
819*1031c584SApple OSS Distributions 	uint64_t                secs64, ns64;
820*1031c584SApple OSS Distributions 
821*1031c584SApple OSS Distributions 	clock_get_calendar_nanotime_nowait(&secs, &nanosecs);
822*1031c584SApple OSS Distributions 	secs64 = (uint64_t)secs;
823*1031c584SApple OSS Distributions 	ns64 = (uint64_t)nanosecs;
824*1031c584SApple OSS Distributions 
825*1031c584SApple OSS Distributions 	ns64 = ns64 + (secs64 * 1000000000LL);
826*1031c584SApple OSS Distributions 	return ns64;
827*1031c584SApple OSS Distributions }
828*1031c584SApple OSS Distributions 
829*1031c584SApple OSS Distributions /*
830*1031c584SApple OSS Distributions  * dtrace_gethrtime() provides high-resolution timestamps with machine-dependent origin.
831*1031c584SApple OSS Distributions  * Hence its primary use is to specify intervals.
832*1031c584SApple OSS Distributions  */
833*1031c584SApple OSS Distributions 
834*1031c584SApple OSS Distributions hrtime_t
dtrace_abs_to_nano(uint64_t elapsed)835*1031c584SApple OSS Distributions dtrace_abs_to_nano(uint64_t elapsed)
836*1031c584SApple OSS Distributions {
837*1031c584SApple OSS Distributions 	static mach_timebase_info_data_t    sTimebaseInfo = { 0, 0 };
838*1031c584SApple OSS Distributions 
839*1031c584SApple OSS Distributions 	/*
840*1031c584SApple OSS Distributions 	 * If this is the first time we've run, get the timebase.
841*1031c584SApple OSS Distributions 	 * We can use denom == 0 to indicate that sTimebaseInfo is
842*1031c584SApple OSS Distributions 	 * uninitialised because it makes no sense to have a zero
843*1031c584SApple OSS Distributions 	 * denominator in a fraction.
844*1031c584SApple OSS Distributions 	 */
845*1031c584SApple OSS Distributions 
846*1031c584SApple OSS Distributions 	if (sTimebaseInfo.denom == 0) {
847*1031c584SApple OSS Distributions 		(void) clock_timebase_info(&sTimebaseInfo);
848*1031c584SApple OSS Distributions 	}
849*1031c584SApple OSS Distributions 
850*1031c584SApple OSS Distributions 	/*
851*1031c584SApple OSS Distributions 	 * Convert to nanoseconds.
852*1031c584SApple OSS Distributions 	 * return (elapsed * (uint64_t)sTimebaseInfo.numer)/(uint64_t)sTimebaseInfo.denom;
853*1031c584SApple OSS Distributions 	 *
854*1031c584SApple OSS Distributions 	 * Provided the final result is representable in 64 bits the following maneuver will
855*1031c584SApple OSS Distributions 	 * deliver that result without intermediate overflow.
856*1031c584SApple OSS Distributions 	 */
857*1031c584SApple OSS Distributions 	if (sTimebaseInfo.denom == sTimebaseInfo.numer) {
858*1031c584SApple OSS Distributions 		return elapsed;
859*1031c584SApple OSS Distributions 	} else if (sTimebaseInfo.denom == 1) {
860*1031c584SApple OSS Distributions 		return elapsed * (uint64_t)sTimebaseInfo.numer;
861*1031c584SApple OSS Distributions 	} else {
862*1031c584SApple OSS Distributions 		/* Decompose elapsed = eta32 * 2^32 + eps32: */
863*1031c584SApple OSS Distributions 		uint64_t eta32 = elapsed >> 32;
864*1031c584SApple OSS Distributions 		uint64_t eps32 = elapsed & 0x00000000ffffffffLL;
865*1031c584SApple OSS Distributions 
866*1031c584SApple OSS Distributions 		uint32_t numer = sTimebaseInfo.numer, denom = sTimebaseInfo.denom;
867*1031c584SApple OSS Distributions 
868*1031c584SApple OSS Distributions 		/* Form product of elapsed64 (decomposed) and numer: */
869*1031c584SApple OSS Distributions 		uint64_t mu64 = numer * eta32;
870*1031c584SApple OSS Distributions 		uint64_t lambda64 = numer * eps32;
871*1031c584SApple OSS Distributions 
872*1031c584SApple OSS Distributions 		/* Divide the constituents by denom: */
873*1031c584SApple OSS Distributions 		uint64_t q32 = mu64 / denom;
874*1031c584SApple OSS Distributions 		uint64_t r32 = mu64 - (q32 * denom); /* mu64 % denom */
875*1031c584SApple OSS Distributions 
876*1031c584SApple OSS Distributions 		return (q32 << 32) + ((r32 << 32) + lambda64) / denom;
877*1031c584SApple OSS Distributions 	}
878*1031c584SApple OSS Distributions }
879*1031c584SApple OSS Distributions 
880*1031c584SApple OSS Distributions hrtime_t
dtrace_gethrtime(void)881*1031c584SApple OSS Distributions dtrace_gethrtime(void)
882*1031c584SApple OSS Distributions {
883*1031c584SApple OSS Distributions 	static uint64_t        start = 0;
884*1031c584SApple OSS Distributions 
885*1031c584SApple OSS Distributions 	if (start == 0) {
886*1031c584SApple OSS Distributions 		start = mach_absolute_time();
887*1031c584SApple OSS Distributions 	}
888*1031c584SApple OSS Distributions 
889*1031c584SApple OSS Distributions 	return dtrace_abs_to_nano(mach_absolute_time() - start);
890*1031c584SApple OSS Distributions }
891*1031c584SApple OSS Distributions 
892*1031c584SApple OSS Distributions /*
893*1031c584SApple OSS Distributions  * Atomicity and synchronization
894*1031c584SApple OSS Distributions  */
895*1031c584SApple OSS Distributions uint32_t
dtrace_cas32(uint32_t * target,uint32_t cmp,uint32_t new)896*1031c584SApple OSS Distributions dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
897*1031c584SApple OSS Distributions {
898*1031c584SApple OSS Distributions 	if (OSCompareAndSwap((UInt32)cmp, (UInt32)new, (volatile UInt32 *)target )) {
899*1031c584SApple OSS Distributions 		return cmp;
900*1031c584SApple OSS Distributions 	} else {
901*1031c584SApple OSS Distributions 		return ~cmp; /* Must return something *other* than cmp */
902*1031c584SApple OSS Distributions 	}
903*1031c584SApple OSS Distributions }
904*1031c584SApple OSS Distributions 
905*1031c584SApple OSS Distributions void *
dtrace_casptr(void * target,void * cmp,void * new)906*1031c584SApple OSS Distributions dtrace_casptr(void *target, void *cmp, void *new)
907*1031c584SApple OSS Distributions {
908*1031c584SApple OSS Distributions 	if (OSCompareAndSwapPtr( cmp, new, (void**)target )) {
909*1031c584SApple OSS Distributions 		return cmp;
910*1031c584SApple OSS Distributions 	} else {
911*1031c584SApple OSS Distributions 		return (void *)(~(uintptr_t)cmp); /* Must return something *other* than cmp */
912*1031c584SApple OSS Distributions 	}
913*1031c584SApple OSS Distributions }
914*1031c584SApple OSS Distributions 
915*1031c584SApple OSS Distributions /*
916*1031c584SApple OSS Distributions  * Interrupt manipulation
917*1031c584SApple OSS Distributions  */
918*1031c584SApple OSS Distributions dtrace_icookie_t
dtrace_interrupt_disable(void)919*1031c584SApple OSS Distributions dtrace_interrupt_disable(void)
920*1031c584SApple OSS Distributions {
921*1031c584SApple OSS Distributions 	return (dtrace_icookie_t)ml_set_interrupts_enabled(FALSE);
922*1031c584SApple OSS Distributions }
923*1031c584SApple OSS Distributions 
924*1031c584SApple OSS Distributions void
dtrace_interrupt_enable(dtrace_icookie_t reenable)925*1031c584SApple OSS Distributions dtrace_interrupt_enable(dtrace_icookie_t reenable)
926*1031c584SApple OSS Distributions {
927*1031c584SApple OSS Distributions 	(void)ml_set_interrupts_enabled((boolean_t)reenable);
928*1031c584SApple OSS Distributions }
929*1031c584SApple OSS Distributions 
930*1031c584SApple OSS Distributions /*
931*1031c584SApple OSS Distributions  * MP coordination
932*1031c584SApple OSS Distributions  */
933*1031c584SApple OSS Distributions static void
dtrace_sync_func(void)934*1031c584SApple OSS Distributions dtrace_sync_func(void)
935*1031c584SApple OSS Distributions {
936*1031c584SApple OSS Distributions }
937*1031c584SApple OSS Distributions 
938*1031c584SApple OSS Distributions /*
939*1031c584SApple OSS Distributions  * dtrace_sync() is not called from probe context.
940*1031c584SApple OSS Distributions  */
941*1031c584SApple OSS Distributions void
dtrace_sync(void)942*1031c584SApple OSS Distributions dtrace_sync(void)
943*1031c584SApple OSS Distributions {
944*1031c584SApple OSS Distributions 	dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
945*1031c584SApple OSS Distributions }
946*1031c584SApple OSS Distributions 
947*1031c584SApple OSS Distributions /*
948*1031c584SApple OSS Distributions  * The dtrace_copyin/out/instr and dtrace_fuword* routines can be called from probe context.
949*1031c584SApple OSS Distributions  */
950*1031c584SApple OSS Distributions 
951*1031c584SApple OSS Distributions extern kern_return_t dtrace_copyio_preflight(addr64_t);
952*1031c584SApple OSS Distributions extern kern_return_t dtrace_copyio_postflight(addr64_t);
953*1031c584SApple OSS Distributions 
954*1031c584SApple OSS Distributions static int
dtrace_copycheck(user_addr_t uaddr,uintptr_t kaddr,size_t size)955*1031c584SApple OSS Distributions dtrace_copycheck(user_addr_t uaddr, uintptr_t kaddr, size_t size)
956*1031c584SApple OSS Distributions {
957*1031c584SApple OSS Distributions #pragma unused(kaddr)
958*1031c584SApple OSS Distributions 
959*1031c584SApple OSS Distributions 	ASSERT(kaddr + size >= kaddr);
960*1031c584SApple OSS Distributions 
961*1031c584SApple OSS Distributions 	if (uaddr + size < uaddr ||             /* Avoid address wrap. */
962*1031c584SApple OSS Distributions 	    KERN_FAILURE == dtrace_copyio_preflight(uaddr)) {   /* Machine specific setup/constraints. */
963*1031c584SApple OSS Distributions 		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
964*1031c584SApple OSS Distributions 		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
965*1031c584SApple OSS Distributions 		return 0;
966*1031c584SApple OSS Distributions 	}
967*1031c584SApple OSS Distributions 	return 1;
968*1031c584SApple OSS Distributions }
969*1031c584SApple OSS Distributions 
970*1031c584SApple OSS Distributions void
dtrace_copyin(user_addr_t src,uintptr_t dst,size_t len,volatile uint16_t * flags)971*1031c584SApple OSS Distributions dtrace_copyin(user_addr_t src, uintptr_t dst, size_t len, volatile uint16_t *flags)
972*1031c584SApple OSS Distributions {
973*1031c584SApple OSS Distributions #pragma unused(flags)
974*1031c584SApple OSS Distributions 
975*1031c584SApple OSS Distributions 	if (dtrace_copycheck( src, dst, len )) {
976*1031c584SApple OSS Distributions 		if (copyin((const user_addr_t)src, (char *)dst, (vm_size_t)len)) {
977*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
978*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = src;
979*1031c584SApple OSS Distributions 		}
980*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(src);
981*1031c584SApple OSS Distributions 	}
982*1031c584SApple OSS Distributions }
983*1031c584SApple OSS Distributions 
984*1031c584SApple OSS Distributions void
dtrace_copyinstr(user_addr_t src,uintptr_t dst,size_t len,volatile uint16_t * flags)985*1031c584SApple OSS Distributions dtrace_copyinstr(user_addr_t src, uintptr_t dst, size_t len, volatile uint16_t *flags)
986*1031c584SApple OSS Distributions {
987*1031c584SApple OSS Distributions #pragma unused(flags)
988*1031c584SApple OSS Distributions 
989*1031c584SApple OSS Distributions 	size_t actual;
990*1031c584SApple OSS Distributions 
991*1031c584SApple OSS Distributions 	if (dtrace_copycheck( src, dst, len )) {
992*1031c584SApple OSS Distributions 		/*  copyin as many as 'len' bytes. */
993*1031c584SApple OSS Distributions 		int error = copyinstr((const user_addr_t)src, (char *)dst, (vm_size_t)len, &actual);
994*1031c584SApple OSS Distributions 
995*1031c584SApple OSS Distributions 		/*
996*1031c584SApple OSS Distributions 		 * ENAMETOOLONG is returned when 'len' bytes have been copied in but the NUL terminator was
997*1031c584SApple OSS Distributions 		 * not encountered. That does not require raising CPU_DTRACE_BADADDR, and we press on.
998*1031c584SApple OSS Distributions 		 * Note that we do *not* stuff a NUL terminator when returning ENAMETOOLONG, that's left
999*1031c584SApple OSS Distributions 		 * to the caller.
1000*1031c584SApple OSS Distributions 		 */
1001*1031c584SApple OSS Distributions 		if (error && error != ENAMETOOLONG) {
1002*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1003*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = src;
1004*1031c584SApple OSS Distributions 		}
1005*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(src);
1006*1031c584SApple OSS Distributions 	}
1007*1031c584SApple OSS Distributions }
1008*1031c584SApple OSS Distributions 
1009*1031c584SApple OSS Distributions void
dtrace_copyout(uintptr_t src,user_addr_t dst,size_t len,volatile uint16_t * flags)1010*1031c584SApple OSS Distributions dtrace_copyout(uintptr_t src, user_addr_t dst, size_t len, volatile uint16_t *flags)
1011*1031c584SApple OSS Distributions {
1012*1031c584SApple OSS Distributions #pragma unused(flags)
1013*1031c584SApple OSS Distributions 
1014*1031c584SApple OSS Distributions 	if (dtrace_copycheck( dst, src, len )) {
1015*1031c584SApple OSS Distributions 		if (copyout((const void *)src, dst, (vm_size_t)len)) {
1016*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1017*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = dst;
1018*1031c584SApple OSS Distributions 		}
1019*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(dst);
1020*1031c584SApple OSS Distributions 	}
1021*1031c584SApple OSS Distributions }
1022*1031c584SApple OSS Distributions 
1023*1031c584SApple OSS Distributions void
dtrace_copyoutstr(uintptr_t src,user_addr_t dst,size_t len,volatile uint16_t * flags)1024*1031c584SApple OSS Distributions dtrace_copyoutstr(uintptr_t src, user_addr_t dst, size_t len, volatile uint16_t *flags)
1025*1031c584SApple OSS Distributions {
1026*1031c584SApple OSS Distributions #pragma unused(flags)
1027*1031c584SApple OSS Distributions 
1028*1031c584SApple OSS Distributions 	size_t actual;
1029*1031c584SApple OSS Distributions 
1030*1031c584SApple OSS Distributions 	if (dtrace_copycheck( dst, src, len )) {
1031*1031c584SApple OSS Distributions 		/*
1032*1031c584SApple OSS Distributions 		 * ENAMETOOLONG is returned when 'len' bytes have been copied out but the NUL terminator was
1033*1031c584SApple OSS Distributions 		 * not encountered. We raise CPU_DTRACE_BADADDR in that case.
1034*1031c584SApple OSS Distributions 		 * Note that we do *not* stuff a NUL terminator when returning ENAMETOOLONG, that's left
1035*1031c584SApple OSS Distributions 		 * to the caller.
1036*1031c584SApple OSS Distributions 		 */
1037*1031c584SApple OSS Distributions 		if (copyoutstr((const void *)src, dst, (size_t)len, &actual)) {
1038*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1039*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = dst;
1040*1031c584SApple OSS Distributions 		}
1041*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(dst);
1042*1031c584SApple OSS Distributions 	}
1043*1031c584SApple OSS Distributions }
1044*1031c584SApple OSS Distributions 
1045*1031c584SApple OSS Distributions extern const int copysize_limit_panic;
1046*1031c584SApple OSS Distributions 
1047*1031c584SApple OSS Distributions int
dtrace_copy_maxsize(void)1048*1031c584SApple OSS Distributions dtrace_copy_maxsize(void)
1049*1031c584SApple OSS Distributions {
1050*1031c584SApple OSS Distributions 	return copysize_limit_panic;
1051*1031c584SApple OSS Distributions }
1052*1031c584SApple OSS Distributions 
1053*1031c584SApple OSS Distributions 
1054*1031c584SApple OSS Distributions int
dtrace_buffer_copyout(const void * kaddr,user_addr_t uaddr,vm_size_t nbytes)1055*1031c584SApple OSS Distributions dtrace_buffer_copyout(const void *kaddr, user_addr_t uaddr, vm_size_t nbytes)
1056*1031c584SApple OSS Distributions {
1057*1031c584SApple OSS Distributions 	int maxsize = dtrace_copy_maxsize();
1058*1031c584SApple OSS Distributions 	/*
1059*1031c584SApple OSS Distributions 	 * Partition the copyout in copysize_limit_panic-sized chunks
1060*1031c584SApple OSS Distributions 	 */
1061*1031c584SApple OSS Distributions 	while (nbytes >= (vm_size_t)maxsize) {
1062*1031c584SApple OSS Distributions 		if (copyout(kaddr, uaddr, maxsize) != 0) {
1063*1031c584SApple OSS Distributions 			return EFAULT;
1064*1031c584SApple OSS Distributions 		}
1065*1031c584SApple OSS Distributions 
1066*1031c584SApple OSS Distributions 		nbytes -= maxsize;
1067*1031c584SApple OSS Distributions 		uaddr += maxsize;
1068*1031c584SApple OSS Distributions 		kaddr = (const void *)((uintptr_t)kaddr + maxsize);
1069*1031c584SApple OSS Distributions 	}
1070*1031c584SApple OSS Distributions 	if (nbytes > 0) {
1071*1031c584SApple OSS Distributions 		if (copyout(kaddr, uaddr, nbytes) != 0) {
1072*1031c584SApple OSS Distributions 			return EFAULT;
1073*1031c584SApple OSS Distributions 		}
1074*1031c584SApple OSS Distributions 	}
1075*1031c584SApple OSS Distributions 
1076*1031c584SApple OSS Distributions 	return 0;
1077*1031c584SApple OSS Distributions }
1078*1031c584SApple OSS Distributions 
1079*1031c584SApple OSS Distributions uint8_t
dtrace_fuword8(user_addr_t uaddr)1080*1031c584SApple OSS Distributions dtrace_fuword8(user_addr_t uaddr)
1081*1031c584SApple OSS Distributions {
1082*1031c584SApple OSS Distributions 	uint8_t ret = 0;
1083*1031c584SApple OSS Distributions 
1084*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
1085*1031c584SApple OSS Distributions 	if (dtrace_copycheck( uaddr, (uintptr_t)&ret, sizeof(ret))) {
1086*1031c584SApple OSS Distributions 		if (copyin((const user_addr_t)uaddr, (char *)&ret, sizeof(ret))) {
1087*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1088*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
1089*1031c584SApple OSS Distributions 		}
1090*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(uaddr);
1091*1031c584SApple OSS Distributions 	}
1092*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
1093*1031c584SApple OSS Distributions 
1094*1031c584SApple OSS Distributions 	return ret;
1095*1031c584SApple OSS Distributions }
1096*1031c584SApple OSS Distributions 
1097*1031c584SApple OSS Distributions uint16_t
dtrace_fuword16(user_addr_t uaddr)1098*1031c584SApple OSS Distributions dtrace_fuword16(user_addr_t uaddr)
1099*1031c584SApple OSS Distributions {
1100*1031c584SApple OSS Distributions 	uint16_t ret = 0;
1101*1031c584SApple OSS Distributions 
1102*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
1103*1031c584SApple OSS Distributions 	if (dtrace_copycheck( uaddr, (uintptr_t)&ret, sizeof(ret))) {
1104*1031c584SApple OSS Distributions 		if (copyin((const user_addr_t)uaddr, (char *)&ret, sizeof(ret))) {
1105*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1106*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
1107*1031c584SApple OSS Distributions 		}
1108*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(uaddr);
1109*1031c584SApple OSS Distributions 	}
1110*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
1111*1031c584SApple OSS Distributions 
1112*1031c584SApple OSS Distributions 	return ret;
1113*1031c584SApple OSS Distributions }
1114*1031c584SApple OSS Distributions 
1115*1031c584SApple OSS Distributions uint32_t
dtrace_fuword32(user_addr_t uaddr)1116*1031c584SApple OSS Distributions dtrace_fuword32(user_addr_t uaddr)
1117*1031c584SApple OSS Distributions {
1118*1031c584SApple OSS Distributions 	uint32_t ret = 0;
1119*1031c584SApple OSS Distributions 
1120*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
1121*1031c584SApple OSS Distributions 	if (dtrace_copycheck( uaddr, (uintptr_t)&ret, sizeof(ret))) {
1122*1031c584SApple OSS Distributions 		if (copyin((const user_addr_t)uaddr, (char *)&ret, sizeof(ret))) {
1123*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1124*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
1125*1031c584SApple OSS Distributions 		}
1126*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(uaddr);
1127*1031c584SApple OSS Distributions 	}
1128*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
1129*1031c584SApple OSS Distributions 
1130*1031c584SApple OSS Distributions 	return ret;
1131*1031c584SApple OSS Distributions }
1132*1031c584SApple OSS Distributions 
1133*1031c584SApple OSS Distributions uint64_t
dtrace_fuword64(user_addr_t uaddr)1134*1031c584SApple OSS Distributions dtrace_fuword64(user_addr_t uaddr)
1135*1031c584SApple OSS Distributions {
1136*1031c584SApple OSS Distributions 	uint64_t ret = 0;
1137*1031c584SApple OSS Distributions 
1138*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
1139*1031c584SApple OSS Distributions 	if (dtrace_copycheck( uaddr, (uintptr_t)&ret, sizeof(ret))) {
1140*1031c584SApple OSS Distributions 		if (copyin((const user_addr_t)uaddr, (char *)&ret, sizeof(ret))) {
1141*1031c584SApple OSS Distributions 			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1142*1031c584SApple OSS Distributions 			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
1143*1031c584SApple OSS Distributions 		}
1144*1031c584SApple OSS Distributions 		dtrace_copyio_postflight(uaddr);
1145*1031c584SApple OSS Distributions 	}
1146*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
1147*1031c584SApple OSS Distributions 
1148*1031c584SApple OSS Distributions 	return ret;
1149*1031c584SApple OSS Distributions }
1150*1031c584SApple OSS Distributions 
1151*1031c584SApple OSS Distributions /*
1152*1031c584SApple OSS Distributions  * Emulation of Solaris fuword / suword
1153*1031c584SApple OSS Distributions  * Called from the fasttrap provider, so the use of copyin/out requires fewer safegaurds.
1154*1031c584SApple OSS Distributions  */
1155*1031c584SApple OSS Distributions 
1156*1031c584SApple OSS Distributions int
fuword8(user_addr_t uaddr,uint8_t * value)1157*1031c584SApple OSS Distributions fuword8(user_addr_t uaddr, uint8_t *value)
1158*1031c584SApple OSS Distributions {
1159*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint8_t)) != 0) {
1160*1031c584SApple OSS Distributions 		return -1;
1161*1031c584SApple OSS Distributions 	}
1162*1031c584SApple OSS Distributions 
1163*1031c584SApple OSS Distributions 	return 0;
1164*1031c584SApple OSS Distributions }
1165*1031c584SApple OSS Distributions 
1166*1031c584SApple OSS Distributions int
fuword16(user_addr_t uaddr,uint16_t * value)1167*1031c584SApple OSS Distributions fuword16(user_addr_t uaddr, uint16_t *value)
1168*1031c584SApple OSS Distributions {
1169*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint16_t)) != 0) {
1170*1031c584SApple OSS Distributions 		return -1;
1171*1031c584SApple OSS Distributions 	}
1172*1031c584SApple OSS Distributions 
1173*1031c584SApple OSS Distributions 	return 0;
1174*1031c584SApple OSS Distributions }
1175*1031c584SApple OSS Distributions 
1176*1031c584SApple OSS Distributions int
fuword32(user_addr_t uaddr,uint32_t * value)1177*1031c584SApple OSS Distributions fuword32(user_addr_t uaddr, uint32_t *value)
1178*1031c584SApple OSS Distributions {
1179*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint32_t)) != 0) {
1180*1031c584SApple OSS Distributions 		return -1;
1181*1031c584SApple OSS Distributions 	}
1182*1031c584SApple OSS Distributions 
1183*1031c584SApple OSS Distributions 	return 0;
1184*1031c584SApple OSS Distributions }
1185*1031c584SApple OSS Distributions 
1186*1031c584SApple OSS Distributions int
fuword64(user_addr_t uaddr,uint64_t * value)1187*1031c584SApple OSS Distributions fuword64(user_addr_t uaddr, uint64_t *value)
1188*1031c584SApple OSS Distributions {
1189*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint64_t)) != 0) {
1190*1031c584SApple OSS Distributions 		return -1;
1191*1031c584SApple OSS Distributions 	}
1192*1031c584SApple OSS Distributions 
1193*1031c584SApple OSS Distributions 	return 0;
1194*1031c584SApple OSS Distributions }
1195*1031c584SApple OSS Distributions 
1196*1031c584SApple OSS Distributions void
fuword32_noerr(user_addr_t uaddr,uint32_t * value)1197*1031c584SApple OSS Distributions fuword32_noerr(user_addr_t uaddr, uint32_t *value)
1198*1031c584SApple OSS Distributions {
1199*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint32_t))) {
1200*1031c584SApple OSS Distributions 		*value = 0;
1201*1031c584SApple OSS Distributions 	}
1202*1031c584SApple OSS Distributions }
1203*1031c584SApple OSS Distributions 
1204*1031c584SApple OSS Distributions void
fuword64_noerr(user_addr_t uaddr,uint64_t * value)1205*1031c584SApple OSS Distributions fuword64_noerr(user_addr_t uaddr, uint64_t *value)
1206*1031c584SApple OSS Distributions {
1207*1031c584SApple OSS Distributions 	if (copyin((const user_addr_t)uaddr, (char *)value, sizeof(uint64_t))) {
1208*1031c584SApple OSS Distributions 		*value = 0;
1209*1031c584SApple OSS Distributions 	}
1210*1031c584SApple OSS Distributions }
1211*1031c584SApple OSS Distributions 
1212*1031c584SApple OSS Distributions int
suword64(user_addr_t addr,uint64_t value)1213*1031c584SApple OSS Distributions suword64(user_addr_t addr, uint64_t value)
1214*1031c584SApple OSS Distributions {
1215*1031c584SApple OSS Distributions 	if (copyout((const void *)&value, addr, sizeof(value)) != 0) {
1216*1031c584SApple OSS Distributions 		return -1;
1217*1031c584SApple OSS Distributions 	}
1218*1031c584SApple OSS Distributions 
1219*1031c584SApple OSS Distributions 	return 0;
1220*1031c584SApple OSS Distributions }
1221*1031c584SApple OSS Distributions 
1222*1031c584SApple OSS Distributions int
suword32(user_addr_t addr,uint32_t value)1223*1031c584SApple OSS Distributions suword32(user_addr_t addr, uint32_t value)
1224*1031c584SApple OSS Distributions {
1225*1031c584SApple OSS Distributions 	if (copyout((const void *)&value, addr, sizeof(value)) != 0) {
1226*1031c584SApple OSS Distributions 		return -1;
1227*1031c584SApple OSS Distributions 	}
1228*1031c584SApple OSS Distributions 
1229*1031c584SApple OSS Distributions 	return 0;
1230*1031c584SApple OSS Distributions }
1231*1031c584SApple OSS Distributions 
1232*1031c584SApple OSS Distributions /*
1233*1031c584SApple OSS Distributions  * Miscellaneous
1234*1031c584SApple OSS Distributions  */
1235*1031c584SApple OSS Distributions extern boolean_t dtrace_tally_fault(user_addr_t);
1236*1031c584SApple OSS Distributions 
1237*1031c584SApple OSS Distributions boolean_t
dtrace_tally_fault(user_addr_t uaddr)1238*1031c584SApple OSS Distributions dtrace_tally_fault(user_addr_t uaddr)
1239*1031c584SApple OSS Distributions {
1240*1031c584SApple OSS Distributions 	DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
1241*1031c584SApple OSS Distributions 	cpu_core[CPU->cpu_id].cpuc_dtrace_illval = uaddr;
1242*1031c584SApple OSS Distributions 	return DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT) ? TRUE : FALSE;
1243*1031c584SApple OSS Distributions }
1244*1031c584SApple OSS Distributions 
1245*1031c584SApple OSS Distributions #define TOTTY   0x02
1246*1031c584SApple OSS Distributions extern int prf(const char *, va_list, int, struct tty *); /* bsd/kern/subr_prf.h */
1247*1031c584SApple OSS Distributions 
1248*1031c584SApple OSS Distributions int
vuprintf(const char * format,va_list ap)1249*1031c584SApple OSS Distributions vuprintf(const char *format, va_list ap)
1250*1031c584SApple OSS Distributions {
1251*1031c584SApple OSS Distributions 	return prf(format, ap, TOTTY, NULL);
1252*1031c584SApple OSS Distributions }
1253*1031c584SApple OSS Distributions 
1254*1031c584SApple OSS Distributions /* Not called from probe context */
1255*1031c584SApple OSS Distributions void
cmn_err(int level,const char * format,...)1256*1031c584SApple OSS Distributions cmn_err( int level, const char *format, ... )
1257*1031c584SApple OSS Distributions {
1258*1031c584SApple OSS Distributions #pragma unused(level)
1259*1031c584SApple OSS Distributions 	va_list alist;
1260*1031c584SApple OSS Distributions 
1261*1031c584SApple OSS Distributions 	va_start(alist, format);
1262*1031c584SApple OSS Distributions 	vuprintf(format, alist);
1263*1031c584SApple OSS Distributions 	va_end(alist);
1264*1031c584SApple OSS Distributions 	uprintf("\n");
1265*1031c584SApple OSS Distributions }
1266*1031c584SApple OSS Distributions 
1267*1031c584SApple OSS Distributions const void*
bsearch(const void * key,const void * base0,size_t nmemb,size_t size,int (* compar)(const void *,const void *))1268*1031c584SApple OSS Distributions bsearch(const void *key, const void *base0, size_t nmemb, size_t size, int (*compar)(const void *, const void *))
1269*1031c584SApple OSS Distributions {
1270*1031c584SApple OSS Distributions 	const char *base = base0;
1271*1031c584SApple OSS Distributions 	size_t lim;
1272*1031c584SApple OSS Distributions 	int cmp;
1273*1031c584SApple OSS Distributions 	const void *p;
1274*1031c584SApple OSS Distributions 	for (lim = nmemb; lim != 0; lim >>= 1) {
1275*1031c584SApple OSS Distributions 		p = base + (lim >> 1) * size;
1276*1031c584SApple OSS Distributions 		cmp = (*compar)(key, p);
1277*1031c584SApple OSS Distributions 		if (cmp == 0) {
1278*1031c584SApple OSS Distributions 			return p;
1279*1031c584SApple OSS Distributions 		}
1280*1031c584SApple OSS Distributions 		if (cmp > 0) {  /* key > p: move right */
1281*1031c584SApple OSS Distributions 			base = (const char *)p + size;
1282*1031c584SApple OSS Distributions 			lim--;
1283*1031c584SApple OSS Distributions 		}               /* else move left */
1284*1031c584SApple OSS Distributions 	}
1285*1031c584SApple OSS Distributions 	return NULL;
1286*1031c584SApple OSS Distributions }
1287*1031c584SApple OSS Distributions 
1288*1031c584SApple OSS Distributions /*
1289*1031c584SApple OSS Distributions  * Runtime and ABI
1290*1031c584SApple OSS Distributions  */
1291*1031c584SApple OSS Distributions uintptr_t
dtrace_caller(int ignore)1292*1031c584SApple OSS Distributions dtrace_caller(int ignore)
1293*1031c584SApple OSS Distributions {
1294*1031c584SApple OSS Distributions #pragma unused(ignore)
1295*1031c584SApple OSS Distributions 	return -1; /* Just as in Solaris dtrace_asm.s */
1296*1031c584SApple OSS Distributions }
1297*1031c584SApple OSS Distributions 
1298*1031c584SApple OSS Distributions int
dtrace_getstackdepth(int aframes)1299*1031c584SApple OSS Distributions dtrace_getstackdepth(int aframes)
1300*1031c584SApple OSS Distributions {
1301*1031c584SApple OSS Distributions 	struct frame *fp = (struct frame *)__builtin_frame_address(0);
1302*1031c584SApple OSS Distributions 	struct frame *nextfp, *minfp, *stacktop;
1303*1031c584SApple OSS Distributions 	int depth = 0;
1304*1031c584SApple OSS Distributions 	int on_intr;
1305*1031c584SApple OSS Distributions 
1306*1031c584SApple OSS Distributions 	if ((on_intr = CPU_ON_INTR(CPU)) != 0) {
1307*1031c584SApple OSS Distributions 		stacktop = (struct frame *)dtrace_get_cpu_int_stack_top();
1308*1031c584SApple OSS Distributions 	} else {
1309*1031c584SApple OSS Distributions 		stacktop = (struct frame *)(dtrace_get_kernel_stack(current_thread()) + kernel_stack_size);
1310*1031c584SApple OSS Distributions 	}
1311*1031c584SApple OSS Distributions 
1312*1031c584SApple OSS Distributions 	minfp = fp;
1313*1031c584SApple OSS Distributions 
1314*1031c584SApple OSS Distributions 	aframes++;
1315*1031c584SApple OSS Distributions 
1316*1031c584SApple OSS Distributions 	for (;;) {
1317*1031c584SApple OSS Distributions 		depth++;
1318*1031c584SApple OSS Distributions 
1319*1031c584SApple OSS Distributions 		nextfp = *(struct frame **)fp;
1320*1031c584SApple OSS Distributions 
1321*1031c584SApple OSS Distributions 		if (nextfp <= minfp || nextfp >= stacktop) {
1322*1031c584SApple OSS Distributions 			if (on_intr) {
1323*1031c584SApple OSS Distributions 				/*
1324*1031c584SApple OSS Distributions 				 * Hop from interrupt stack to thread stack.
1325*1031c584SApple OSS Distributions 				 */
1326*1031c584SApple OSS Distributions 				vm_offset_t kstack_base = dtrace_get_kernel_stack(current_thread());
1327*1031c584SApple OSS Distributions 
1328*1031c584SApple OSS Distributions 				minfp = (struct frame *)kstack_base;
1329*1031c584SApple OSS Distributions 				stacktop = (struct frame *)(kstack_base + kernel_stack_size);
1330*1031c584SApple OSS Distributions 
1331*1031c584SApple OSS Distributions 				on_intr = 0;
1332*1031c584SApple OSS Distributions 				continue;
1333*1031c584SApple OSS Distributions 			}
1334*1031c584SApple OSS Distributions 			break;
1335*1031c584SApple OSS Distributions 		}
1336*1031c584SApple OSS Distributions 
1337*1031c584SApple OSS Distributions 		fp = nextfp;
1338*1031c584SApple OSS Distributions 		minfp = fp;
1339*1031c584SApple OSS Distributions 	}
1340*1031c584SApple OSS Distributions 
1341*1031c584SApple OSS Distributions 	if (depth <= aframes) {
1342*1031c584SApple OSS Distributions 		return 0;
1343*1031c584SApple OSS Distributions 	}
1344*1031c584SApple OSS Distributions 
1345*1031c584SApple OSS Distributions 	return depth - aframes;
1346*1031c584SApple OSS Distributions }
1347*1031c584SApple OSS Distributions 
1348*1031c584SApple OSS Distributions int
dtrace_addr_in_module(const void * addr,const struct modctl * ctl)1349*1031c584SApple OSS Distributions dtrace_addr_in_module(const void* addr, const struct modctl *ctl)
1350*1031c584SApple OSS Distributions {
1351*1031c584SApple OSS Distributions 	return OSKextKextForAddress(addr) == (void*)ctl->mod_address;
1352*1031c584SApple OSS Distributions }
1353*1031c584SApple OSS Distributions 
1354*1031c584SApple OSS Distributions /*
1355*1031c584SApple OSS Distributions  * Unconsidered
1356*1031c584SApple OSS Distributions  */
1357*1031c584SApple OSS Distributions void
dtrace_vtime_enable(void)1358*1031c584SApple OSS Distributions dtrace_vtime_enable(void)
1359*1031c584SApple OSS Distributions {
1360*1031c584SApple OSS Distributions }
1361*1031c584SApple OSS Distributions 
1362*1031c584SApple OSS Distributions void
dtrace_vtime_disable(void)1363*1031c584SApple OSS Distributions dtrace_vtime_disable(void)
1364*1031c584SApple OSS Distributions {
1365*1031c584SApple OSS Distributions }
1366