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
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.
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]
25 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
26 * Use is subject to license terms.
28 #include <sys/cdefs.h>
30 #include <sys/param.h>
31 #include <sys/systm.h>
32 #include <sys/kernel.h>
33 #include <sys/stack.h>
36 #include <machine/frame.h>
37 #include <machine/md_var.h>
38 #include <machine/pcb.h>
39 #include <machine/stack.h>
42 #include <vm/vm_param.h>
47 extern uintptr_t kernbase;
48 uintptr_t kernelbase = (uintptr_t) &kernbase;
50 #define INKERNEL(va) (((vm_offset_t)(va)) >= USRSTACK && \
51 ((vm_offset_t)(va)) < VM_MAX_KERNEL_ADDRESS)
53 uint8_t dtrace_fuword8_nocheck(void *);
54 uint16_t dtrace_fuword16_nocheck(void *);
55 uint32_t dtrace_fuword32_nocheck(void *);
56 uint64_t dtrace_fuword64_nocheck(void *);
59 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
64 struct i386_frame *frame;
66 pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
69 pcstack[depth++] = (pc_t) intrpc;
73 __asm __volatile("movl %%ebp,%0" : "=r" (ebp));
75 frame = (struct i386_frame *)ebp;
76 while (depth < pcstack_limit) {
80 callpc = frame->f_retaddr;
82 if (!INKERNEL(callpc))
87 if ((aframes == 0) && (caller != 0)) {
88 pcstack[depth++] = caller;
92 pcstack[depth++] = callpc;
95 if (frame->f_frame <= frame ||
96 (vm_offset_t)frame->f_frame >=
97 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
99 frame = frame->f_frame;
102 for (; depth < pcstack_limit; depth++) {
108 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
113 uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
116 volatile uint16_t *flags =
117 (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
120 ASSERT(pcstack == NULL || pcstack_limit > 0);
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);
127 s1 = sizeof (struct frame32) + 3 * sizeof (int);
128 s2 = s1 + sizeof (siginfo32_t);
134 if (pcstack != NULL) {
135 *pcstack++ = (uint64_t)pc;
137 if (pcstack_limit <= 0)
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;
150 sp = dtrace_fulword(&gregs[REG_FP]);
151 pc = dtrace_fulword(&gregs[REG_PC]);
153 oldcontext = dtrace_fulword(&ucp->uc_link);
155 ucontext32_t *ucp = (ucontext32_t *)oldcontext;
156 greg32_t *gregs = ucp->uc_mcontext.gregs;
158 sp = dtrace_fuword32(&gregs[EBP]);
159 pc = dtrace_fuword32(&gregs[EIP]);
161 oldcontext = dtrace_fuword32(&ucp->uc_link);
164 if (p->p_model == DATAMODEL_NATIVE) {
165 struct frame *fr = (struct frame *)sp;
167 pc = dtrace_fulword(&fr->fr_savpc);
168 sp = dtrace_fulword(&fr->fr_savfp);
170 struct frame32 *fr = (struct frame32 *)sp;
172 pc = dtrace_fuword32(&fr->fr_savpc);
173 sp = dtrace_fuword32(&fr->fr_savfp);
177 pc = dtrace_fuword32((void *)(sp +
178 offsetof(struct i386_frame, f_retaddr)));
179 sp = dtrace_fuword32((void *)sp);
180 #endif /* ! notyet */
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.
187 if (*flags & CPU_DTRACE_FAULT) {
188 *flags &= ~CPU_DTRACE_FAULT;
197 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
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;
206 if (*flags & CPU_DTRACE_FAULT)
209 if (pcstack_limit <= 0)
213 * If there's no user context we still need to zero the stack.
215 if (p == NULL || (tf = curthread->td_frame) == NULL)
218 *pcstack++ = (uint64_t)p->p_pid;
221 if (pcstack_limit <= 0)
228 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
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.
238 *pcstack++ = (uint64_t)pc;
240 if (pcstack_limit <= 0)
243 pc = dtrace_fuword32((void *) sp);
246 n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
248 ASSERT(n <= pcstack_limit);
254 while (pcstack_limit-- > 0)
259 dtrace_getustackdepth(void)
262 struct trapframe *tf;
263 uintptr_t pc, fp, sp;
266 if (p == NULL || (tf = curthread->td_frame) == NULL)
269 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
276 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
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.
286 pc = dtrace_fuword32((void *) sp);
290 n += dtrace_getustack_common(NULL, 0, pc, fp);
296 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
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;
308 if (*flags & CPU_DTRACE_FAULT)
311 if (pcstack_limit <= 0)
315 * If there's no user context we still need to zero the stack.
317 if (p == NULL || (tf = curthread->td_frame) == NULL)
320 *pcstack++ = (uint64_t)p->p_pid;
323 if (pcstack_limit <= 0)
330 #ifdef notyet /* XXX signal stack */
331 oldcontext = lwp->lwp_oldcontext;
333 if (p->p_model == DATAMODEL_NATIVE) {
334 s1 = sizeof (struct frame) + 2 * sizeof (long);
335 s2 = s1 + sizeof (siginfo_t);
337 s1 = sizeof (struct frame32) + 3 * sizeof (int);
338 s2 = s1 + sizeof (siginfo32_t);
342 if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
343 *pcstack++ = (uint64_t)pc;
346 if (pcstack_limit <= 0)
349 pc = dtrace_fuword32((void *)sp);
353 *pcstack++ = (uint64_t)pc;
356 if (pcstack_limit <= 0)
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;
368 sp = dtrace_fulword(&gregs[REG_FP]);
369 pc = dtrace_fulword(&gregs[REG_PC]);
371 oldcontext = dtrace_fulword(&ucp->uc_link);
373 ucontext_t *ucp = (ucontext_t *)oldcontext;
374 greg_t *gregs = ucp->uc_mcontext.gregs;
376 sp = dtrace_fuword32(&gregs[EBP]);
377 pc = dtrace_fuword32(&gregs[EIP]);
379 oldcontext = dtrace_fuword32(&ucp->uc_link);
384 pc = dtrace_fuword32((void *)(fp +
385 offsetof(struct i386_frame, f_retaddr)));
386 fp = dtrace_fuword32((void *)fp);
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.
394 if (*flags & CPU_DTRACE_FAULT) {
395 *flags &= ~CPU_DTRACE_FAULT;
401 while (pcstack_limit-- > 0)
406 dtrace_getarg(int arg, int aframes)
409 struct i386_frame *fp = (struct i386_frame *)dtrace_getfp();
413 for (i = 1; i <= aframes; i++) {
416 if (P2ROUNDUP(fp->f_retaddr, 4) ==
417 (long)dtrace_invop_callsite) {
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.
426 stack = ((uintptr_t **)&fp[1])[0] + 1;
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).
442 stack = (uintptr_t *)fp + 2;
445 DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
447 DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
453 dtrace_getstackdepth(int aframes)
456 struct i386_frame *frame;
460 ebp = dtrace_getfp();
461 frame = (struct i386_frame *)ebp;
464 if (!INKERNEL((long) frame))
466 if (!INKERNEL((long) frame->f_frame))
469 if (frame->f_frame <= frame ||
470 (vm_offset_t)frame->f_frame >=
471 (vm_offset_t)ebp + KSTACK_PAGES * PAGE_SIZE)
473 frame = frame->f_frame;
478 return depth - aframes;
482 dtrace_getreg(struct trapframe *rp, uint_t reg)
485 int regmap[] = { /* Order is dependent on reg.d */
492 REG_RBP, /* 6 EBP, REG_FP */
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 */
502 REG_RFL, /* 16 EFL, REG_PS */
503 REG_RSP, /* 17 UESP, REG_SP */
508 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
512 if (reg >= sizeof (regmap) / sizeof (int)) {
513 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
521 if ((pcb = curthread->td_pcb) == NULL) {
522 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
525 return (pcb->pcb_gs);
547 return (rp->tf_trapno);
555 return (rp->tf_eflags);
563 DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
569 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
571 ASSERT(kaddr >= kernelbase && kaddr + size >= kaddr);
573 if (uaddr + size >= kernelbase || uaddr + size < uaddr) {
574 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
575 cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
583 dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
584 volatile uint16_t *flags)
586 if (dtrace_copycheck(uaddr, kaddr, size))
587 dtrace_copy(uaddr, kaddr, size);
591 dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
592 volatile uint16_t *flags)
594 if (dtrace_copycheck(uaddr, kaddr, size))
595 dtrace_copy(kaddr, uaddr, size);
599 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
600 volatile uint16_t *flags)
602 if (dtrace_copycheck(uaddr, kaddr, size))
603 dtrace_copystr(uaddr, kaddr, size, flags);
607 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
608 volatile uint16_t *flags)
610 if (dtrace_copycheck(uaddr, kaddr, size))
611 dtrace_copystr(kaddr, uaddr, size, flags);
615 dtrace_fuword8(void *uaddr)
617 if ((uintptr_t)uaddr >= kernelbase) {
618 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
619 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
622 return (dtrace_fuword8_nocheck(uaddr));
626 dtrace_fuword16(void *uaddr)
628 if ((uintptr_t)uaddr >= kernelbase) {
629 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
630 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
633 return (dtrace_fuword16_nocheck(uaddr));
637 dtrace_fuword32(void *uaddr)
639 if ((uintptr_t)uaddr >= kernelbase) {
640 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
641 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
644 return (dtrace_fuword32_nocheck(uaddr));
648 dtrace_fuword64(void *uaddr)
650 if ((uintptr_t)uaddr >= kernelbase) {
651 DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
652 cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
655 return (dtrace_fuword64_nocheck(uaddr));