dtrace_subr.c revision 1.1.2.3 1 1.1.2.3 tls /* $NetBSD: dtrace_subr.c,v 1.1.2.3 2014/08/19 23:52:21 tls Exp $ */
2 1.1.2.3 tls
3 1.1.2.2 tls /*
4 1.1.2.2 tls * CDDL HEADER START
5 1.1.2.2 tls *
6 1.1.2.2 tls * The contents of this file are subject to the terms of the
7 1.1.2.2 tls * Common Development and Distribution License, Version 1.0 only
8 1.1.2.2 tls * (the "License"). You may not use this file except in compliance
9 1.1.2.2 tls * with the License.
10 1.1.2.2 tls *
11 1.1.2.2 tls * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
12 1.1.2.2 tls * or http://www.opensolaris.org/os/licensing.
13 1.1.2.2 tls * See the License for the specific language governing permissions
14 1.1.2.2 tls * and limitations under the License.
15 1.1.2.2 tls *
16 1.1.2.2 tls * When distributing Covered Code, include this CDDL HEADER in each
17 1.1.2.2 tls * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
18 1.1.2.2 tls * If applicable, add the following below this CDDL HEADER, with the
19 1.1.2.2 tls * fields enclosed by brackets "[]" replaced with your own identifying
20 1.1.2.2 tls * information: Portions Copyright [yyyy] [name of copyright owner]
21 1.1.2.2 tls *
22 1.1.2.2 tls * CDDL HEADER END
23 1.1.2.2 tls *
24 1.1.2.2 tls * $FreeBSD$
25 1.1.2.2 tls *
26 1.1.2.2 tls */
27 1.1.2.2 tls /*
28 1.1.2.2 tls * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
29 1.1.2.2 tls * Use is subject to license terms.
30 1.1.2.2 tls */
31 1.1.2.2 tls
32 1.1.2.2 tls #include <sys/param.h>
33 1.1.2.2 tls #include <sys/systm.h>
34 1.1.2.2 tls #include <sys/types.h>
35 1.1.2.2 tls #include <sys/kernel.h>
36 1.1.2.2 tls #include <sys/malloc.h>
37 1.1.2.2 tls #include <sys/kmem.h>
38 1.1.2.3 tls #include <sys/xcall.h>
39 1.1.2.3 tls #include <sys/cpu.h>
40 1.1.2.3 tls #include <sys/cpuvar.h>
41 1.1.2.2 tls #include <sys/dtrace_impl.h>
42 1.1.2.2 tls #include <sys/dtrace_bsd.h>
43 1.1.2.3 tls #include <machine/cpu.h>
44 1.1.2.2 tls #include <machine/frame.h>
45 1.1.2.3 tls #include <machine/vmparam.h>
46 1.1.2.3 tls #include <uvm/uvm_pglist.h>
47 1.1.2.3 tls #include <uvm/uvm_prot.h>
48 1.1.2.3 tls #include <uvm/uvm_pmap.h>
49 1.1.2.2 tls
50 1.1.2.3 tls extern uintptr_t kernelbase;
51 1.1.2.2 tls extern uintptr_t dtrace_in_probe_addr;
52 1.1.2.2 tls extern int dtrace_in_probe;
53 1.1.2.2 tls extern dtrace_id_t dtrace_probeid_error;
54 1.1.2.2 tls
55 1.1.2.2 tls int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
56 1.1.2.2 tls
57 1.1.2.2 tls typedef struct dtrace_invop_hdlr {
58 1.1.2.2 tls int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
59 1.1.2.2 tls struct dtrace_invop_hdlr *dtih_next;
60 1.1.2.2 tls } dtrace_invop_hdlr_t;
61 1.1.2.2 tls
62 1.1.2.2 tls dtrace_invop_hdlr_t *dtrace_invop_hdlr;
63 1.1.2.2 tls
64 1.1.2.3 tls void dtrace_gethrtime_init(void *arg);
65 1.1.2.3 tls
66 1.1.2.2 tls int
67 1.1.2.2 tls dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
68 1.1.2.2 tls {
69 1.1.2.2 tls dtrace_invop_hdlr_t *hdlr;
70 1.1.2.2 tls int rval;
71 1.1.2.2 tls
72 1.1.2.2 tls for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
73 1.1.2.2 tls if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
74 1.1.2.2 tls return (rval);
75 1.1.2.2 tls
76 1.1.2.2 tls return (0);
77 1.1.2.2 tls }
78 1.1.2.2 tls
79 1.1.2.3 tls void
80 1.1.2.3 tls dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
81 1.1.2.3 tls {
82 1.1.2.3 tls dtrace_invop_hdlr_t *hdlr;
83 1.1.2.3 tls
84 1.1.2.3 tls hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
85 1.1.2.3 tls hdlr->dtih_func = func;
86 1.1.2.3 tls hdlr->dtih_next = dtrace_invop_hdlr;
87 1.1.2.3 tls dtrace_invop_hdlr = hdlr;
88 1.1.2.3 tls }
89 1.1.2.3 tls
90 1.1.2.3 tls void
91 1.1.2.3 tls dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
92 1.1.2.3 tls {
93 1.1.2.3 tls dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
94 1.1.2.3 tls
95 1.1.2.3 tls for (;;) {
96 1.1.2.3 tls if (hdlr == NULL)
97 1.1.2.3 tls panic("attempt to remove non-existent invop handler");
98 1.1.2.3 tls
99 1.1.2.3 tls if (hdlr->dtih_func == func)
100 1.1.2.3 tls break;
101 1.1.2.3 tls
102 1.1.2.3 tls prev = hdlr;
103 1.1.2.3 tls hdlr = hdlr->dtih_next;
104 1.1.2.3 tls }
105 1.1.2.3 tls
106 1.1.2.3 tls if (prev == NULL) {
107 1.1.2.3 tls ASSERT(dtrace_invop_hdlr == hdlr);
108 1.1.2.3 tls dtrace_invop_hdlr = hdlr->dtih_next;
109 1.1.2.3 tls } else {
110 1.1.2.3 tls ASSERT(dtrace_invop_hdlr != hdlr);
111 1.1.2.3 tls prev->dtih_next = hdlr->dtih_next;
112 1.1.2.3 tls }
113 1.1.2.3 tls
114 1.1.2.3 tls kmem_free(hdlr, sizeof (dtrace_invop_hdlr_t));
115 1.1.2.3 tls }
116 1.1.2.2 tls
117 1.1.2.2 tls void
118 1.1.2.2 tls dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit))
119 1.1.2.2 tls {
120 1.1.2.3 tls (*func)(0, kernelbase);
121 1.1.2.3 tls }
122 1.1.2.3 tls
123 1.1.2.3 tls static void
124 1.1.2.3 tls xcall_func(void *arg0, void *arg1)
125 1.1.2.3 tls {
126 1.1.2.3 tls dtrace_xcall_t func = arg0;
127 1.1.2.3 tls
128 1.1.2.3 tls (*func)(arg1);
129 1.1.2.2 tls }
130 1.1.2.2 tls
131 1.1.2.2 tls void
132 1.1.2.2 tls dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
133 1.1.2.2 tls {
134 1.1.2.3 tls uint64_t where;
135 1.1.2.2 tls
136 1.1.2.3 tls if (cpu == DTRACE_CPUALL) {
137 1.1.2.3 tls where = xc_broadcast(0, xcall_func, func, arg);
138 1.1.2.3 tls } else {
139 1.1.2.3 tls struct cpu_info *cinfo = cpu_lookup(cpu);
140 1.1.2.2 tls
141 1.1.2.3 tls KASSERT(cinfo != NULL);
142 1.1.2.3 tls where = xc_unicast(0, xcall_func, func, arg, cinfo);
143 1.1.2.3 tls }
144 1.1.2.3 tls xc_wait(where);
145 1.1.2.3 tls
146 1.1.2.3 tls /* XXX Q. Do we really need the other cpus to wait also?
147 1.1.2.3 tls * (see solaris:xc_sync())
148 1.1.2.3 tls */
149 1.1.2.2 tls }
150 1.1.2.2 tls
151 1.1.2.2 tls static void
152 1.1.2.2 tls dtrace_sync_func(void)
153 1.1.2.2 tls {
154 1.1.2.2 tls }
155 1.1.2.2 tls
156 1.1.2.2 tls void
157 1.1.2.2 tls dtrace_sync(void)
158 1.1.2.2 tls {
159 1.1.2.2 tls dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
160 1.1.2.2 tls }
161 1.1.2.2 tls
162 1.1.2.2 tls /*
163 1.1.2.2 tls * DTrace needs a high resolution time function which can
164 1.1.2.2 tls * be called from a probe context and guaranteed not to have
165 1.1.2.2 tls * instrumented with probes itself.
166 1.1.2.2 tls *
167 1.1.2.2 tls * Returns nanoseconds since boot.
168 1.1.2.2 tls */
169 1.1.2.2 tls uint64_t
170 1.1.2.2 tls dtrace_gethrtime()
171 1.1.2.2 tls {
172 1.1.2.2 tls struct timespec curtime;
173 1.1.2.2 tls
174 1.1.2.2 tls nanouptime(&curtime);
175 1.1.2.2 tls
176 1.1.2.2 tls return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
177 1.1.2.2 tls
178 1.1.2.2 tls }
179 1.1.2.2 tls
180 1.1.2.2 tls uint64_t
181 1.1.2.2 tls dtrace_gethrestime(void)
182 1.1.2.2 tls {
183 1.1.2.2 tls struct timespec curtime;
184 1.1.2.2 tls
185 1.1.2.2 tls getnanotime(&curtime);
186 1.1.2.2 tls
187 1.1.2.2 tls return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
188 1.1.2.2 tls }
189 1.1.2.2 tls
190 1.1.2.3 tls /* Function to handle DTrace traps during probes. Not used on ARM yet */
191 1.1.2.2 tls int
192 1.1.2.2 tls dtrace_trap(struct trapframe *frame, u_int type)
193 1.1.2.2 tls {
194 1.1.2.3 tls cpuid_t cpuid = cpu_number(); /* current cpu id */
195 1.1.2.3 tls
196 1.1.2.2 tls /*
197 1.1.2.2 tls * A trap can occur while DTrace executes a probe. Before
198 1.1.2.2 tls * executing the probe, DTrace blocks re-scheduling and sets
199 1.1.2.2 tls * a flag in it's per-cpu flags to indicate that it doesn't
200 1.1.2.2 tls * want to fault. On returning from the probe, the no-fault
201 1.1.2.2 tls * flag is cleared and finally re-scheduling is enabled.
202 1.1.2.2 tls *
203 1.1.2.2 tls * Check if DTrace has enabled 'no-fault' mode:
204 1.1.2.2 tls *
205 1.1.2.2 tls */
206 1.1.2.3 tls
207 1.1.2.3 tls if ((cpu_core[cpuid].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
208 1.1.2.2 tls /*
209 1.1.2.2 tls * There are only a couple of trap types that are expected.
210 1.1.2.2 tls * All the rest will be handled in the usual way.
211 1.1.2.2 tls */
212 1.1.2.2 tls switch (type) {
213 1.1.2.2 tls /* Page fault. */
214 1.1.2.2 tls case 0:
215 1.1.2.2 tls /* Flag a bad address. */
216 1.1.2.3 tls cpu_core[cpuid].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
217 1.1.2.3 tls cpu_core[cpuid].cpuc_dtrace_illval = 0;
218 1.1.2.2 tls
219 1.1.2.2 tls /*
220 1.1.2.2 tls * Offset the instruction pointer to the instruction
221 1.1.2.2 tls * following the one causing the fault.
222 1.1.2.2 tls */
223 1.1.2.2 tls panic("%s", __func__);
224 1.1.2.2 tls // frame->pc += sizeof(int);
225 1.1.2.2 tls return (1);
226 1.1.2.2 tls default:
227 1.1.2.2 tls /* Handle all other traps in the usual way. */
228 1.1.2.2 tls break;
229 1.1.2.2 tls }
230 1.1.2.2 tls }
231 1.1.2.2 tls
232 1.1.2.2 tls /* Handle the trap in the usual way. */
233 1.1.2.2 tls return (0);
234 1.1.2.2 tls }
235 1.1.2.2 tls
236 1.1.2.2 tls void
237 1.1.2.2 tls dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
238 1.1.2.2 tls int fault, int fltoffs, uintptr_t illval)
239 1.1.2.2 tls {
240 1.1.2.2 tls
241 1.1.2.2 tls dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state,
242 1.1.2.2 tls (uintptr_t)epid,
243 1.1.2.2 tls (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
244 1.1.2.2 tls }
245 1.1.2.3 tls
246 1.1.2.3 tls void
247 1.1.2.3 tls dtrace_gethrtime_init(void *arg)
248 1.1.2.3 tls {
249 1.1.2.3 tls /* FIXME */
250 1.1.2.3 tls }
251