Deleted Added
full compact
dtrace_isa.c (269557) dtrace_isa.c (281482)
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 *
1/*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
8 *
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
13 *
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
19 *
20 * CDDL HEADER END
21 *
22 * $FreeBSD: stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c 269557 2014-08-05 01:53:15Z markj $
22 * $FreeBSD: stable/10/sys/cddl/dev/dtrace/i386/dtrace_isa.c 281482 2015-04-13 01:42:24Z markj $
23 */
24/*
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28#include <sys/cdefs.h>
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/stack.h>
34#include <sys/pcpu.h>
35
36#include <machine/frame.h>
37#include <machine/md_var.h>
38#include <machine/pcb.h>
39#include <machine/stack.h>
40
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/pmap.h>
44
45#include "regset.h"
46
47extern uintptr_t kernbase;
48uintptr_t kernelbase = (uintptr_t) &kernbase;
49
50#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK && \
51 ((vm_offset_t)(va)) < VM_MAX_KERNEL_ADDRESS)
52
53uint8_t dtrace_fuword8_nocheck(void *);
54uint16_t dtrace_fuword16_nocheck(void *);
55uint32_t dtrace_fuword32_nocheck(void *);
56uint64_t dtrace_fuword64_nocheck(void *);
57
23 */
24/*
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
27 */
28#include <sys/cdefs.h>
29
30#include <sys/param.h>
31#include <sys/systm.h>
32#include <sys/kernel.h>
33#include <sys/stack.h>
34#include <sys/pcpu.h>
35
36#include <machine/frame.h>
37#include <machine/md_var.h>
38#include <machine/pcb.h>
39#include <machine/stack.h>
40
41#include <vm/vm.h>
42#include <vm/vm_param.h>
43#include <vm/pmap.h>
44
45#include "regset.h"
46
47extern uintptr_t kernbase;
48uintptr_t kernelbase = (uintptr_t) &kernbase;
49
50#define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK && \
51 ((vm_offset_t)(va)) < VM_MAX_KERNEL_ADDRESS)
52
53uint8_t dtrace_fuword8_nocheck(void *);
54uint16_t dtrace_fuword16_nocheck(void *);
55uint32_t dtrace_fuword32_nocheck(void *);
56uint64_t dtrace_fuword64_nocheck(void *);
57
58int dtrace_ustackdepth_max = 2048;
59
58void
59dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
60 uint32_t *intrpc)
61{
62 int depth = 0;
63 register_t ebp;
64 struct i386_frame *frame;
65 vm_offset_t callpc;
66 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
67
68 if (intrpc != 0)
69 pcstack[depth++] = (pc_t) intrpc;
70
71 aframes++;
72
73 __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
74
75 frame = (struct i386_frame *)ebp;
76 while (depth < pcstack_limit) {
77 if (!INKERNEL(frame))
78 break;
79
80 callpc = frame->f_retaddr;
81
82 if (!INKERNEL(callpc))
83 break;
84
85 if (aframes > 0) {
86 aframes--;
87 if ((aframes == 0) && (caller != 0)) {
88 pcstack[depth++] = caller;
89 }
90 }
91 else {
92 pcstack[depth++] = callpc;
93 }
94
95 if (frame->f_frame <= frame ||
96 (vm_offset_t)frame->f_frame >=
97 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
98 break;
99 frame = frame->f_frame;
100 }
101
102 for (; depth < pcstack_limit; depth++) {
103 pcstack[depth] = 0;
104 }
105}
106
107static int
108dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
109 uintptr_t sp)
110{
111#ifdef notyet
112 proc_t *p = curproc;
113 uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
114 size_t s1, s2;
115#endif
60void
61dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
62 uint32_t *intrpc)
63{
64 int depth = 0;
65 register_t ebp;
66 struct i386_frame *frame;
67 vm_offset_t callpc;
68 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
69
70 if (intrpc != 0)
71 pcstack[depth++] = (pc_t) intrpc;
72
73 aframes++;
74
75 __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
76
77 frame = (struct i386_frame *)ebp;
78 while (depth < pcstack_limit) {
79 if (!INKERNEL(frame))
80 break;
81
82 callpc = frame->f_retaddr;
83
84 if (!INKERNEL(callpc))
85 break;
86
87 if (aframes > 0) {
88 aframes--;
89 if ((aframes == 0) && (caller != 0)) {
90 pcstack[depth++] = caller;
91 }
92 }
93 else {
94 pcstack[depth++] = callpc;
95 }
96
97 if (frame->f_frame <= frame ||
98 (vm_offset_t)frame->f_frame >=
99 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
100 break;
101 frame = frame->f_frame;
102 }
103
104 for (; depth < pcstack_limit; depth++) {
105 pcstack[depth] = 0;
106 }
107}
108
109static int
110dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
111 uintptr_t sp)
112{
113#ifdef notyet
114 proc_t *p = curproc;
115 uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
116 size_t s1, s2;
117#endif
118 uintptr_t oldsp;
116 volatile uint16_t *flags =
117 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
118 int ret = 0;
119
120 ASSERT(pcstack == NULL || pcstack_limit > 0);
119 volatile uint16_t *flags =
120 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
121 int ret = 0;
122
123 ASSERT(pcstack == NULL || pcstack_limit > 0);
124 ASSERT(dtrace_ustackdepth_max > 0);
121
122#ifdef notyet /* XXX signal stack. */
123 if (p->p_model == DATAMODEL_NATIVE) {
124 s1 = sizeof (struct frame) + 2 * sizeof (long);
125 s2 = s1 + sizeof (siginfo_t);
126 } else {
127 s1 = sizeof (struct frame32) + 3 * sizeof (int);
128 s2 = s1 + sizeof (siginfo32_t);
129 }
130#endif
131
132 while (pc != 0) {
125
126#ifdef notyet /* XXX signal stack. */
127 if (p->p_model == DATAMODEL_NATIVE) {
128 s1 = sizeof (struct frame) + 2 * sizeof (long);
129 s2 = s1 + sizeof (siginfo_t);
130 } else {
131 s1 = sizeof (struct frame32) + 3 * sizeof (int);
132 s2 = s1 + sizeof (siginfo32_t);
133 }
134#endif
135
136 while (pc != 0) {
133 ret++;
137 /*
138 * We limit the number of times we can go around this
139 * loop to account for a circular stack.
140 */
141 if (ret++ >= dtrace_ustackdepth_max) {
142 *flags |= CPU_DTRACE_BADSTACK;
143 cpu_core[curcpu].cpuc_dtrace_illval = sp;
144 break;
145 }
146
134 if (pcstack != NULL) {
135 *pcstack++ = (uint64_t)pc;
136 pcstack_limit--;
137 if (pcstack_limit <= 0)
138 break;
139 }
140
141 if (sp == 0)
142 break;
143
147 if (pcstack != NULL) {
148 *pcstack++ = (uint64_t)pc;
149 pcstack_limit--;
150 if (pcstack_limit <= 0)
151 break;
152 }
153
154 if (sp == 0)
155 break;
156
157 oldsp = sp;
158
144#ifdef notyet /* XXX signal stack. */
145 if (oldcontext == sp + s1 || oldcontext == sp + s2) {
146 if (p->p_model == DATAMODEL_NATIVE) {
147 ucontext_t *ucp = (ucontext_t *)oldcontext;
148 greg_t *gregs = ucp->uc_mcontext.gregs;
149
150 sp = dtrace_fulword(&gregs[REG_FP]);
151 pc = dtrace_fulword(&gregs[REG_PC]);
152
153 oldcontext = dtrace_fulword(&ucp->uc_link);
154 } else {
155 ucontext32_t *ucp = (ucontext32_t *)oldcontext;
156 greg32_t *gregs = ucp->uc_mcontext.gregs;
157
158 sp = dtrace_fuword32(&gregs[EBP]);
159 pc = dtrace_fuword32(&gregs[EIP]);
160
161 oldcontext = dtrace_fuword32(&ucp->uc_link);
162 }
163 } else {
164 if (p->p_model == DATAMODEL_NATIVE) {
165 struct frame *fr = (struct frame *)sp;
166
167 pc = dtrace_fulword(&fr->fr_savpc);
168 sp = dtrace_fulword(&fr->fr_savfp);
169 } else {
170 struct frame32 *fr = (struct frame32 *)sp;
171
172 pc = dtrace_fuword32(&fr->fr_savpc);
173 sp = dtrace_fuword32(&fr->fr_savfp);
174 }
175 }
176#else
177 pc = dtrace_fuword32((void *)(sp +
178 offsetof(struct i386_frame, f_retaddr)));
179 sp = dtrace_fuword32((void *)sp);
180#endif /* ! notyet */
181
159#ifdef notyet /* XXX signal stack. */
160 if (oldcontext == sp + s1 || oldcontext == sp + s2) {
161 if (p->p_model == DATAMODEL_NATIVE) {
162 ucontext_t *ucp = (ucontext_t *)oldcontext;
163 greg_t *gregs = ucp->uc_mcontext.gregs;
164
165 sp = dtrace_fulword(&gregs[REG_FP]);
166 pc = dtrace_fulword(&gregs[REG_PC]);
167
168 oldcontext = dtrace_fulword(&ucp->uc_link);
169 } else {
170 ucontext32_t *ucp = (ucontext32_t *)oldcontext;
171 greg32_t *gregs = ucp->uc_mcontext.gregs;
172
173 sp = dtrace_fuword32(&gregs[EBP]);
174 pc = dtrace_fuword32(&gregs[EIP]);
175
176 oldcontext = dtrace_fuword32(&ucp->uc_link);
177 }
178 } else {
179 if (p->p_model == DATAMODEL_NATIVE) {
180 struct frame *fr = (struct frame *)sp;
181
182 pc = dtrace_fulword(&fr->fr_savpc);
183 sp = dtrace_fulword(&fr->fr_savfp);
184 } else {
185 struct frame32 *fr = (struct frame32 *)sp;
186
187 pc = dtrace_fuword32(&fr->fr_savpc);
188 sp = dtrace_fuword32(&fr->fr_savfp);
189 }
190 }
191#else
192 pc = dtrace_fuword32((void *)(sp +
193 offsetof(struct i386_frame, f_retaddr)));
194 sp = dtrace_fuword32((void *)sp);
195#endif /* ! notyet */
196
197 if (sp == oldsp) {
198 *flags |= CPU_DTRACE_BADSTACK;
199 cpu_core[curcpu].cpuc_dtrace_illval = sp;
200 break;
201 }
202
182 /*
183 * This is totally bogus: if we faulted, we're going to clear
184 * the fault and break. This is to deal with the apparently
185 * broken Java stacks on x86.
186 */
187 if (*flags & CPU_DTRACE_FAULT) {
188 *flags &= ~CPU_DTRACE_FAULT;
189 break;
190 }
191 }
192
193 return (ret);
194}
195
196void
197dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
198{
199 proc_t *p = curproc;
200 struct trapframe *tf;
201 uintptr_t pc, sp, fp;
202 volatile uint16_t *flags =
203 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
204 int n;
205
206 if (*flags & CPU_DTRACE_FAULT)
207 return;
208
209 if (pcstack_limit <= 0)
210 return;
211
212 /*
213 * If there's no user context we still need to zero the stack.
214 */
215 if (p == NULL || (tf = curthread->td_frame) == NULL)
216 goto zero;
217
218 *pcstack++ = (uint64_t)p->p_pid;
219 pcstack_limit--;
220
221 if (pcstack_limit <= 0)
222 return;
223
224 pc = tf->tf_eip;
225 fp = tf->tf_ebp;
226 sp = tf->tf_esp;
227
228 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
229 /*
230 * In an entry probe. The frame pointer has not yet been
231 * pushed (that happens in the function prologue). The
232 * best approach is to add the current pc as a missing top
233 * of stack and back the pc up to the caller, which is stored
234 * at the current stack pointer address since the call
235 * instruction puts it there right before the branch.
236 */
237
238 *pcstack++ = (uint64_t)pc;
239 pcstack_limit--;
240 if (pcstack_limit <= 0)
241 return;
242
243 pc = dtrace_fuword32((void *) sp);
244 }
245
246 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
247 ASSERT(n >= 0);
248 ASSERT(n <= pcstack_limit);
249
250 pcstack += n;
251 pcstack_limit -= n;
252
253zero:
254 while (pcstack_limit-- > 0)
255 *pcstack++ = 0;
256}
257
258int
259dtrace_getustackdepth(void)
260{
261 proc_t *p = curproc;
262 struct trapframe *tf;
263 uintptr_t pc, fp, sp;
264 int n = 0;
265
266 if (p == NULL || (tf = curthread->td_frame) == NULL)
267 return (0);
268
269 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
270 return (-1);
271
272 pc = tf->tf_eip;
273 fp = tf->tf_ebp;
274 sp = tf->tf_esp;
275
276 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
277 /*
278 * In an entry probe. The frame pointer has not yet been
279 * pushed (that happens in the function prologue). The
280 * best approach is to add the current pc as a missing top
281 * of stack and back the pc up to the caller, which is stored
282 * at the current stack pointer address since the call
283 * instruction puts it there right before the branch.
284 */
285
286 pc = dtrace_fuword32((void *) sp);
287 n++;
288 }
289
290 n += dtrace_getustack_common(NULL, 0, pc, fp);
291
292 return (n);
293}
294
295void
296dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
297{
298 proc_t *p = curproc;
299 struct trapframe *tf;
300 uintptr_t pc, sp, fp;
301 volatile uint16_t *flags =
302 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
303#ifdef notyet /* XXX signal stack */
304 uintptr_t oldcontext;
305 size_t s1, s2;
306#endif
307
308 if (*flags & CPU_DTRACE_FAULT)
309 return;
310
311 if (pcstack_limit <= 0)
312 return;
313
314 /*
315 * If there's no user context we still need to zero the stack.
316 */
317 if (p == NULL || (tf = curthread->td_frame) == NULL)
318 goto zero;
319
320 *pcstack++ = (uint64_t)p->p_pid;
321 pcstack_limit--;
322
323 if (pcstack_limit <= 0)
324 return;
325
326 pc = tf->tf_eip;
327 fp = tf->tf_ebp;
328 sp = tf->tf_esp;
329
330#ifdef notyet /* XXX signal stack */
331 oldcontext = lwp->lwp_oldcontext;
332
333 if (p->p_model == DATAMODEL_NATIVE) {
334 s1 = sizeof (struct frame) + 2 * sizeof (long);
335 s2 = s1 + sizeof (siginfo_t);
336 } else {
337 s1 = sizeof (struct frame32) + 3 * sizeof (int);
338 s2 = s1 + sizeof (siginfo32_t);
339 }
340#endif
341
342 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
343 *pcstack++ = (uint64_t)pc;
344 *fpstack++ = 0;
345 pcstack_limit--;
346 if (pcstack_limit <= 0)
347 return;
348
349 pc = dtrace_fuword32((void *)sp);
350 }
351
352 while (pc != 0) {
353 *pcstack++ = (uint64_t)pc;
354 *fpstack++ = fp;
355 pcstack_limit--;
356 if (pcstack_limit <= 0)
357 break;
358
359 if (fp == 0)
360 break;
361
362#ifdef notyet /* XXX signal stack */
363 if (oldcontext == sp + s1 || oldcontext == sp + s2) {
364 if (p->p_model == DATAMODEL_NATIVE) {
365 ucontext_t *ucp = (ucontext_t *)oldcontext;
366 greg_t *gregs = ucp->uc_mcontext.gregs;
367
368 sp = dtrace_fulword(&gregs[REG_FP]);
369 pc = dtrace_fulword(&gregs[REG_PC]);
370
371 oldcontext = dtrace_fulword(&ucp->uc_link);
372 } else {
373 ucontext_t *ucp = (ucontext_t *)oldcontext;
374 greg_t *gregs = ucp->uc_mcontext.gregs;
375
376 sp = dtrace_fuword32(&gregs[EBP]);
377 pc = dtrace_fuword32(&gregs[EIP]);
378
379 oldcontext = dtrace_fuword32(&ucp->uc_link);
380 }
381 } else
382#endif /* XXX */
383 {
384 pc = dtrace_fuword32((void *)(fp +
385 offsetof(struct i386_frame, f_retaddr)));
386 fp = dtrace_fuword32((void *)fp);
387 }
388
389 /*
390 * This is totally bogus: if we faulted, we're going to clear
391 * the fault and break. This is to deal with the apparently
392 * broken Java stacks on x86.
393 */
394 if (*flags & CPU_DTRACE_FAULT) {
395 *flags &= ~CPU_DTRACE_FAULT;
396 break;
397 }
398 }
399
400zero:
401 while (pcstack_limit-- > 0)
402 *pcstack++ = 0;
403}
404
405uint64_t
406dtrace_getarg(int arg, int aframes)
407{
408 uintptr_t val;
409 struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
410 uintptr_t *stack;
411 int i;
412
413 for (i = 1; i <= aframes; i++) {
414 fp = fp->f_frame;
415
416 if (P2ROUNDUP(fp->f_retaddr, 4) ==
417 (long)dtrace_invop_callsite) {
418 /*
419 * If we pass through the invalid op handler, we will
420 * use the pointer that it passed to the stack as the
421 * second argument to dtrace_invop() as the pointer to
422 * the stack. When using this stack, we must step
423 * beyond the EIP/RIP that was pushed when the trap was
424 * taken -- hence the "+ 1" below.
425 */
426 stack = ((uintptr_t **)&fp[1])[0] + 1;
427 goto load;
428 }
429
430 }
431
432 /*
433 * We know that we did not come through a trap to get into
434 * dtrace_probe() -- the provider simply called dtrace_probe()
435 * directly. As this is the case, we need to shift the argument
436 * that we're looking for: the probe ID is the first argument to
437 * dtrace_probe(), so the argument n will actually be found where
438 * one would expect to find argument (n + 1).
439 */
440 arg++;
441
442 stack = (uintptr_t *)fp + 2;
443
444load:
445 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
446 val = stack[arg];
447 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
448
449 return (val);
450}
451
452int
453dtrace_getstackdepth(int aframes)
454{
455 int depth = 0;
456 struct i386_frame *frame;
457 vm_offset_t ebp;
458
459 aframes++;
460 ebp = dtrace_getfp();
461 frame = (struct i386_frame *)ebp;
462 depth++;
463 for(;;) {
464 if (!INKERNEL((long) frame))
465 break;
466 if (!INKERNEL((long) frame->f_frame))
467 break;
468 depth++;
469 if (frame->f_frame <= frame ||
470 (vm_offset_t)frame->f_frame >=
471 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
472 break;
473 frame = frame->f_frame;
474 }
475 if (depth < aframes)
476 return 0;
477 else
478 return depth - aframes;
479}
480
481ulong_t
482dtrace_getreg(struct trapframe *rp, uint_t reg)
483{
484 struct pcb *pcb;
485 int regmap[] = { /* Order is dependent on reg.d */
486 REG_GS, /* 0 GS */
487 REG_FS, /* 1 FS */
488 REG_ES, /* 2 ES */
489 REG_DS, /* 3 DS */
490 REG_RDI, /* 4 EDI */
491 REG_RSI, /* 5 ESI */
492 REG_RBP, /* 6 EBP, REG_FP */
493 REG_RSP, /* 7 ESP */
494 REG_RBX, /* 8 EBX */
495 REG_RDX, /* 9 EDX, REG_R1 */
496 REG_RCX, /* 10 ECX */
497 REG_RAX, /* 11 EAX, REG_R0 */
498 REG_TRAPNO, /* 12 TRAPNO */
499 REG_ERR, /* 13 ERR */
500 REG_RIP, /* 14 EIP, REG_PC */
501 REG_CS, /* 15 CS */
502 REG_RFL, /* 16 EFL, REG_PS */
503 REG_RSP, /* 17 UESP, REG_SP */
504 REG_SS /* 18 SS */
505 };
506
507 if (reg > SS) {
508 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
509 return (0);
510 }
511
512 if (reg >= sizeof (regmap) / sizeof (int)) {
513 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
514 return (0);
515 }
516
517 reg = regmap[reg];
518
519 switch(reg) {
520 case REG_GS:
521 if ((pcb = curthread->td_pcb) == NULL) {
522 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
523 return (0);
524 }
525 return (pcb->pcb_gs);
526 case REG_FS:
527 return (rp->tf_fs);
528 case REG_ES:
529 return (rp->tf_es);
530 case REG_DS:
531 return (rp->tf_ds);
532 case REG_RDI:
533 return (rp->tf_edi);
534 case REG_RSI:
535 return (rp->tf_esi);
536 case REG_RBP:
537 return (rp->tf_ebp);
538 case REG_RSP:
539 return (rp->tf_isp);
540 case REG_RBX:
541 return (rp->tf_ebx);
542 case REG_RCX:
543 return (rp->tf_ecx);
544 case REG_RAX:
545 return (rp->tf_eax);
546 case REG_TRAPNO:
547 return (rp->tf_trapno);
548 case REG_ERR:
549 return (rp->tf_err);
550 case REG_RIP:
551 return (rp->tf_eip);
552 case REG_CS:
553 return (rp->tf_cs);
554 case REG_RFL:
555 return (rp->tf_eflags);
556#if 0
557 case REG_RSP:
558 return (rp->tf_esp);
559#endif
560 case REG_SS:
561 return (rp->tf_ss);
562 default:
563 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
564 return (0);
565 }
566}
567
568static int
569dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
570{
571 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
572
573 if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
574 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
575 cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
576 return (0);
577 }
578
579 return (1);
580}
581
582void
583dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
584 volatile uint16_t *flags)
585{
586 if (dtrace_copycheck(uaddr, kaddr, size))
587 dtrace_copy(uaddr, kaddr, size);
588}
589
590void
591dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
592 volatile uint16_t *flags)
593{
594 if (dtrace_copycheck(uaddr, kaddr, size))
595 dtrace_copy(kaddr, uaddr, size);
596}
597
598void
599dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
600 volatile uint16_t *flags)
601{
602 if (dtrace_copycheck(uaddr, kaddr, size))
603 dtrace_copystr(uaddr, kaddr, size, flags);
604}
605
606void
607dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
608 volatile uint16_t *flags)
609{
610 if (dtrace_copycheck(uaddr, kaddr, size))
611 dtrace_copystr(kaddr, uaddr, size, flags);
612}
613
614uint8_t
615dtrace_fuword8(void *uaddr)
616{
617 if ((uintptr_t)uaddr >= kernelbase) {
618 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
619 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
620 return (0);
621 }
622 return (dtrace_fuword8_nocheck(uaddr));
623}
624
625uint16_t
626dtrace_fuword16(void *uaddr)
627{
628 if ((uintptr_t)uaddr >= kernelbase) {
629 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
630 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
631 return (0);
632 }
633 return (dtrace_fuword16_nocheck(uaddr));
634}
635
636uint32_t
637dtrace_fuword32(void *uaddr)
638{
639 if ((uintptr_t)uaddr >= kernelbase) {
640 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
641 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
642 return (0);
643 }
644 return (dtrace_fuword32_nocheck(uaddr));
645}
646
647uint64_t
648dtrace_fuword64(void *uaddr)
649{
650 if ((uintptr_t)uaddr >= kernelbase) {
651 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
652 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
653 return (0);
654 }
655 return (dtrace_fuword64_nocheck(uaddr));
656}
203 /*
204 * This is totally bogus: if we faulted, we're going to clear
205 * the fault and break. This is to deal with the apparently
206 * broken Java stacks on x86.
207 */
208 if (*flags & CPU_DTRACE_FAULT) {
209 *flags &= ~CPU_DTRACE_FAULT;
210 break;
211 }
212 }
213
214 return (ret);
215}
216
217void
218dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
219{
220 proc_t *p = curproc;
221 struct trapframe *tf;
222 uintptr_t pc, sp, fp;
223 volatile uint16_t *flags =
224 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
225 int n;
226
227 if (*flags & CPU_DTRACE_FAULT)
228 return;
229
230 if (pcstack_limit <= 0)
231 return;
232
233 /*
234 * If there's no user context we still need to zero the stack.
235 */
236 if (p == NULL || (tf = curthread->td_frame) == NULL)
237 goto zero;
238
239 *pcstack++ = (uint64_t)p->p_pid;
240 pcstack_limit--;
241
242 if (pcstack_limit <= 0)
243 return;
244
245 pc = tf->tf_eip;
246 fp = tf->tf_ebp;
247 sp = tf->tf_esp;
248
249 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
250 /*
251 * In an entry probe. The frame pointer has not yet been
252 * pushed (that happens in the function prologue). The
253 * best approach is to add the current pc as a missing top
254 * of stack and back the pc up to the caller, which is stored
255 * at the current stack pointer address since the call
256 * instruction puts it there right before the branch.
257 */
258
259 *pcstack++ = (uint64_t)pc;
260 pcstack_limit--;
261 if (pcstack_limit <= 0)
262 return;
263
264 pc = dtrace_fuword32((void *) sp);
265 }
266
267 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
268 ASSERT(n >= 0);
269 ASSERT(n <= pcstack_limit);
270
271 pcstack += n;
272 pcstack_limit -= n;
273
274zero:
275 while (pcstack_limit-- > 0)
276 *pcstack++ = 0;
277}
278
279int
280dtrace_getustackdepth(void)
281{
282 proc_t *p = curproc;
283 struct trapframe *tf;
284 uintptr_t pc, fp, sp;
285 int n = 0;
286
287 if (p == NULL || (tf = curthread->td_frame) == NULL)
288 return (0);
289
290 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
291 return (-1);
292
293 pc = tf->tf_eip;
294 fp = tf->tf_ebp;
295 sp = tf->tf_esp;
296
297 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
298 /*
299 * In an entry probe. The frame pointer has not yet been
300 * pushed (that happens in the function prologue). The
301 * best approach is to add the current pc as a missing top
302 * of stack and back the pc up to the caller, which is stored
303 * at the current stack pointer address since the call
304 * instruction puts it there right before the branch.
305 */
306
307 pc = dtrace_fuword32((void *) sp);
308 n++;
309 }
310
311 n += dtrace_getustack_common(NULL, 0, pc, fp);
312
313 return (n);
314}
315
316void
317dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
318{
319 proc_t *p = curproc;
320 struct trapframe *tf;
321 uintptr_t pc, sp, fp;
322 volatile uint16_t *flags =
323 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
324#ifdef notyet /* XXX signal stack */
325 uintptr_t oldcontext;
326 size_t s1, s2;
327#endif
328
329 if (*flags & CPU_DTRACE_FAULT)
330 return;
331
332 if (pcstack_limit <= 0)
333 return;
334
335 /*
336 * If there's no user context we still need to zero the stack.
337 */
338 if (p == NULL || (tf = curthread->td_frame) == NULL)
339 goto zero;
340
341 *pcstack++ = (uint64_t)p->p_pid;
342 pcstack_limit--;
343
344 if (pcstack_limit <= 0)
345 return;
346
347 pc = tf->tf_eip;
348 fp = tf->tf_ebp;
349 sp = tf->tf_esp;
350
351#ifdef notyet /* XXX signal stack */
352 oldcontext = lwp->lwp_oldcontext;
353
354 if (p->p_model == DATAMODEL_NATIVE) {
355 s1 = sizeof (struct frame) + 2 * sizeof (long);
356 s2 = s1 + sizeof (siginfo_t);
357 } else {
358 s1 = sizeof (struct frame32) + 3 * sizeof (int);
359 s2 = s1 + sizeof (siginfo32_t);
360 }
361#endif
362
363 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
364 *pcstack++ = (uint64_t)pc;
365 *fpstack++ = 0;
366 pcstack_limit--;
367 if (pcstack_limit <= 0)
368 return;
369
370 pc = dtrace_fuword32((void *)sp);
371 }
372
373 while (pc != 0) {
374 *pcstack++ = (uint64_t)pc;
375 *fpstack++ = fp;
376 pcstack_limit--;
377 if (pcstack_limit <= 0)
378 break;
379
380 if (fp == 0)
381 break;
382
383#ifdef notyet /* XXX signal stack */
384 if (oldcontext == sp + s1 || oldcontext == sp + s2) {
385 if (p->p_model == DATAMODEL_NATIVE) {
386 ucontext_t *ucp = (ucontext_t *)oldcontext;
387 greg_t *gregs = ucp->uc_mcontext.gregs;
388
389 sp = dtrace_fulword(&gregs[REG_FP]);
390 pc = dtrace_fulword(&gregs[REG_PC]);
391
392 oldcontext = dtrace_fulword(&ucp->uc_link);
393 } else {
394 ucontext_t *ucp = (ucontext_t *)oldcontext;
395 greg_t *gregs = ucp->uc_mcontext.gregs;
396
397 sp = dtrace_fuword32(&gregs[EBP]);
398 pc = dtrace_fuword32(&gregs[EIP]);
399
400 oldcontext = dtrace_fuword32(&ucp->uc_link);
401 }
402 } else
403#endif /* XXX */
404 {
405 pc = dtrace_fuword32((void *)(fp +
406 offsetof(struct i386_frame, f_retaddr)));
407 fp = dtrace_fuword32((void *)fp);
408 }
409
410 /*
411 * This is totally bogus: if we faulted, we're going to clear
412 * the fault and break. This is to deal with the apparently
413 * broken Java stacks on x86.
414 */
415 if (*flags & CPU_DTRACE_FAULT) {
416 *flags &= ~CPU_DTRACE_FAULT;
417 break;
418 }
419 }
420
421zero:
422 while (pcstack_limit-- > 0)
423 *pcstack++ = 0;
424}
425
426uint64_t
427dtrace_getarg(int arg, int aframes)
428{
429 uintptr_t val;
430 struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
431 uintptr_t *stack;
432 int i;
433
434 for (i = 1; i <= aframes; i++) {
435 fp = fp->f_frame;
436
437 if (P2ROUNDUP(fp->f_retaddr, 4) ==
438 (long)dtrace_invop_callsite) {
439 /*
440 * If we pass through the invalid op handler, we will
441 * use the pointer that it passed to the stack as the
442 * second argument to dtrace_invop() as the pointer to
443 * the stack. When using this stack, we must step
444 * beyond the EIP/RIP that was pushed when the trap was
445 * taken -- hence the "+ 1" below.
446 */
447 stack = ((uintptr_t **)&fp[1])[0] + 1;
448 goto load;
449 }
450
451 }
452
453 /*
454 * We know that we did not come through a trap to get into
455 * dtrace_probe() -- the provider simply called dtrace_probe()
456 * directly. As this is the case, we need to shift the argument
457 * that we're looking for: the probe ID is the first argument to
458 * dtrace_probe(), so the argument n will actually be found where
459 * one would expect to find argument (n + 1).
460 */
461 arg++;
462
463 stack = (uintptr_t *)fp + 2;
464
465load:
466 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
467 val = stack[arg];
468 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
469
470 return (val);
471}
472
473int
474dtrace_getstackdepth(int aframes)
475{
476 int depth = 0;
477 struct i386_frame *frame;
478 vm_offset_t ebp;
479
480 aframes++;
481 ebp = dtrace_getfp();
482 frame = (struct i386_frame *)ebp;
483 depth++;
484 for(;;) {
485 if (!INKERNEL((long) frame))
486 break;
487 if (!INKERNEL((long) frame->f_frame))
488 break;
489 depth++;
490 if (frame->f_frame <= frame ||
491 (vm_offset_t)frame->f_frame >=
492 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
493 break;
494 frame = frame->f_frame;
495 }
496 if (depth < aframes)
497 return 0;
498 else
499 return depth - aframes;
500}
501
502ulong_t
503dtrace_getreg(struct trapframe *rp, uint_t reg)
504{
505 struct pcb *pcb;
506 int regmap[] = { /* Order is dependent on reg.d */
507 REG_GS, /* 0 GS */
508 REG_FS, /* 1 FS */
509 REG_ES, /* 2 ES */
510 REG_DS, /* 3 DS */
511 REG_RDI, /* 4 EDI */
512 REG_RSI, /* 5 ESI */
513 REG_RBP, /* 6 EBP, REG_FP */
514 REG_RSP, /* 7 ESP */
515 REG_RBX, /* 8 EBX */
516 REG_RDX, /* 9 EDX, REG_R1 */
517 REG_RCX, /* 10 ECX */
518 REG_RAX, /* 11 EAX, REG_R0 */
519 REG_TRAPNO, /* 12 TRAPNO */
520 REG_ERR, /* 13 ERR */
521 REG_RIP, /* 14 EIP, REG_PC */
522 REG_CS, /* 15 CS */
523 REG_RFL, /* 16 EFL, REG_PS */
524 REG_RSP, /* 17 UESP, REG_SP */
525 REG_SS /* 18 SS */
526 };
527
528 if (reg > SS) {
529 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
530 return (0);
531 }
532
533 if (reg >= sizeof (regmap) / sizeof (int)) {
534 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
535 return (0);
536 }
537
538 reg = regmap[reg];
539
540 switch(reg) {
541 case REG_GS:
542 if ((pcb = curthread->td_pcb) == NULL) {
543 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
544 return (0);
545 }
546 return (pcb->pcb_gs);
547 case REG_FS:
548 return (rp->tf_fs);
549 case REG_ES:
550 return (rp->tf_es);
551 case REG_DS:
552 return (rp->tf_ds);
553 case REG_RDI:
554 return (rp->tf_edi);
555 case REG_RSI:
556 return (rp->tf_esi);
557 case REG_RBP:
558 return (rp->tf_ebp);
559 case REG_RSP:
560 return (rp->tf_isp);
561 case REG_RBX:
562 return (rp->tf_ebx);
563 case REG_RCX:
564 return (rp->tf_ecx);
565 case REG_RAX:
566 return (rp->tf_eax);
567 case REG_TRAPNO:
568 return (rp->tf_trapno);
569 case REG_ERR:
570 return (rp->tf_err);
571 case REG_RIP:
572 return (rp->tf_eip);
573 case REG_CS:
574 return (rp->tf_cs);
575 case REG_RFL:
576 return (rp->tf_eflags);
577#if 0
578 case REG_RSP:
579 return (rp->tf_esp);
580#endif
581 case REG_SS:
582 return (rp->tf_ss);
583 default:
584 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
585 return (0);
586 }
587}
588
589static int
590dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
591{
592 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
593
594 if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
595 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
596 cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
597 return (0);
598 }
599
600 return (1);
601}
602
603void
604dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
605 volatile uint16_t *flags)
606{
607 if (dtrace_copycheck(uaddr, kaddr, size))
608 dtrace_copy(uaddr, kaddr, size);
609}
610
611void
612dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
613 volatile uint16_t *flags)
614{
615 if (dtrace_copycheck(uaddr, kaddr, size))
616 dtrace_copy(kaddr, uaddr, size);
617}
618
619void
620dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
621 volatile uint16_t *flags)
622{
623 if (dtrace_copycheck(uaddr, kaddr, size))
624 dtrace_copystr(uaddr, kaddr, size, flags);
625}
626
627void
628dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
629 volatile uint16_t *flags)
630{
631 if (dtrace_copycheck(uaddr, kaddr, size))
632 dtrace_copystr(kaddr, uaddr, size, flags);
633}
634
635uint8_t
636dtrace_fuword8(void *uaddr)
637{
638 if ((uintptr_t)uaddr >= kernelbase) {
639 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
640 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
641 return (0);
642 }
643 return (dtrace_fuword8_nocheck(uaddr));
644}
645
646uint16_t
647dtrace_fuword16(void *uaddr)
648{
649 if ((uintptr_t)uaddr >= kernelbase) {
650 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
651 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
652 return (0);
653 }
654 return (dtrace_fuword16_nocheck(uaddr));
655}
656
657uint32_t
658dtrace_fuword32(void *uaddr)
659{
660 if ((uintptr_t)uaddr >= kernelbase) {
661 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
662 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
663 return (0);
664 }
665 return (dtrace_fuword32_nocheck(uaddr));
666}
667
668uint64_t
669dtrace_fuword64(void *uaddr)
670{
671 if ((uintptr_t)uaddr >= kernelbase) {
672 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
673 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
674 return (0);
675 }
676 return (dtrace_fuword64_nocheck(uaddr));
677}