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