Author: rpaulo
Date: Sun Aug 22 10:53:32 2010
New Revision: 211608
URL: http://svn.freebsd.org/changeset/base/211608

Log:
  Kernel DTrace support for:
  o uregs  (sson@)
  o ustack (sson@)
  o /dev/dtrace/helper device (needed for USDT probes)
  
  The work done by me was:
  Sponsored by: The FreeBSD Foundation

Added:
  head/sys/cddl/dev/dtrace/amd64/regset.h   (contents, props changed)
  head/sys/cddl/dev/dtrace/i386/regset.h   (contents, props changed)
Modified:
  head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
  head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
  head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
  head/sys/cddl/dev/dtrace/dtrace_ioctl.c
  head/sys/cddl/dev/dtrace/dtrace_load.c
  head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
  head/sys/cddl/dev/systrace/systrace.c
  head/sys/sys/sysent.h

Modified: head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Sun Aug 
22 10:40:15 2010        (r211607)
+++ head/sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c        Sun Aug 
22 10:53:32 2010        (r211608)
@@ -551,20 +551,16 @@ static void dtrace_enabling_provide(dtra
 static int dtrace_enabling_match(dtrace_enabling_t *, int *);
 static void dtrace_enabling_matchall(void);
 static dtrace_state_t *dtrace_anon_grab(void);
-#if defined(sun)
 static uint64_t dtrace_helper(int, dtrace_mstate_t *,
     dtrace_state_t *, uint64_t, uint64_t);
 static dtrace_helpers_t *dtrace_helpers_create(proc_t *);
-#endif
 static void dtrace_buffer_drop(dtrace_buffer_t *);
 static intptr_t dtrace_buffer_reserve(dtrace_buffer_t *, size_t, size_t,
     dtrace_state_t *, dtrace_mstate_t *);
 static int dtrace_state_option(dtrace_state_t *, dtrace_optid_t,
     dtrace_optval_t);
 static int dtrace_ecb_create_enable(dtrace_probe_t *, void *);
-#if defined(sun)
 static void dtrace_helper_provider_destroy(dtrace_helper_provider_t *);
-#endif
 uint16_t dtrace_load16(uintptr_t);
 uint32_t dtrace_load32(uintptr_t);
 uint64_t dtrace_load64(uintptr_t);
@@ -2784,6 +2780,21 @@ dtrace_dif_variable(dtrace_mstate_t *mst
                return (dtrace_getreg(lwp->lwp_regs, ndx));
                return (0);
        }
+#else
+       case DIF_VAR_UREGS: {
+               struct trapframe *tframe;
+
+               if (!dtrace_priv_proc(state))
+                       return (0);
+
+               if ((tframe = curthread->td_frame) == NULL) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+                       cpu_core[curcpu].cpuc_dtrace_illval = 0;
+                       return (0);
+               }
+
+               return (dtrace_getreg(tframe, ndx));
+       }
 #endif
 
        case DIF_VAR_CURTHREAD:
@@ -2839,7 +2850,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
                }
                return (mstate->dtms_stackdepth);
 
-#if defined(sun)
        case DIF_VAR_USTACKDEPTH:
                if (!dtrace_priv_proc(state))
                        return (0);
@@ -2859,7 +2869,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
                        mstate->dtms_present |= DTRACE_MSTATE_USTACKDEPTH;
                }
                return (mstate->dtms_ustackdepth);
-#endif
 
        case DIF_VAR_CALLER:
                if (!dtrace_priv_kernel(state))
@@ -2896,7 +2905,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
                }
                return (mstate->dtms_caller);
 
-#if defined(sun)
        case DIF_VAR_UCALLER:
                if (!dtrace_priv_proc(state))
                        return (0);
@@ -2920,7 +2928,6 @@ dtrace_dif_variable(dtrace_mstate_t *mst
                }
 
                return (mstate->dtms_ucaller);
-#endif
 
        case DIF_VAR_PROBEPROV:
                ASSERT(mstate->dtms_present & DTRACE_MSTATE_PROBE);
@@ -5736,7 +5743,6 @@ dtrace_action_chill(dtrace_mstate_t *mst
        cpu->cpu_dtrace_chilled += val;
 }
 
-#if defined(sun)
 static void
 dtrace_action_ustack(dtrace_mstate_t *mstate, dtrace_state_t *state,
     uint64_t *buf, uint64_t arg)
@@ -5849,7 +5855,6 @@ dtrace_action_ustack(dtrace_mstate_t *ms
 out:
        mstate->dtms_scratch_ptr = old;
 }
-#endif
 
 /*
  * If you're looking for the epicenter of DTrace, you just found it.  This
@@ -6172,7 +6177,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t a
                                    (uint32_t *)arg0);
                                continue;
 
-#if defined(sun)
                        case DTRACEACT_JSTACK:
                        case DTRACEACT_USTACK:
                                if (!dtrace_priv_proc(state))
@@ -6214,7 +6218,6 @@ dtrace_probe(dtrace_id_t id, uintptr_t a
                                    DTRACE_USTACK_NFRAMES(rec->dtrd_arg) + 1);
                                DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
                                continue;
-#endif
 
                        default:
                                break;
@@ -8141,7 +8144,6 @@ dtrace_helper_provide(dof_helper_t *dhp,
        dtrace_enabling_matchall();
 }
 
-#if defined(sun)
 static void
 dtrace_helper_provider_remove_one(dof_helper_t *dhp, dof_sec_t *sec, pid_t pid)
 {
@@ -8189,7 +8191,6 @@ dtrace_helper_provider_remove(dof_helper
                dtrace_helper_provider_remove_one(dhp, sec, pid);
        }
 }
-#endif
 
 /*
  * DTrace Meta Provider-to-Framework API Functions
@@ -8729,7 +8730,6 @@ dtrace_difo_validate(dtrace_difo_t *dp, 
        return (err);
 }
 
-#if defined(sun)
 /*
  * Validate a DTrace DIF object that it is to be used as a helper.  Helpers
  * are much more constrained than normal DIFOs.  Specifically, they may
@@ -8887,7 +8887,6 @@ dtrace_difo_validate_helper(dtrace_difo_
 
        return (err);
 }
-#endif
 
 /*
  * Returns 1 if the expression in the DIF object can be cached on a per-thread
@@ -13791,7 +13790,6 @@ dtrace_anon_property(void)
        }
 }
 
-#if defined(sun)
 /*
  * DTrace Helper Functions
  */
@@ -13855,9 +13853,7 @@ dtrace_helper_trace(dtrace_helper_action
                    ((uint64_t *)(uintptr_t)svar->dtsv_data)[curcpu];
        }
 }
-#endif
 
-#if defined(sun)
 static uint64_t
 dtrace_helper(int which, dtrace_mstate_t *mstate,
     dtrace_state_t *state, uint64_t arg0, uint64_t arg1)
@@ -13865,7 +13861,7 @@ dtrace_helper(int which, dtrace_mstate_t
        uint16_t *flags = &cpu_core[curcpu].cpuc_dtrace_flags;
        uint64_t sarg0 = mstate->dtms_arg[0];
        uint64_t sarg1 = mstate->dtms_arg[1];
-       uint64_t rval;
+       uint64_t rval = 0;
        dtrace_helpers_t *helpers = curproc->p_dtrace_helpers;
        dtrace_helper_action_t *helper;
        dtrace_vstate_t *vstate;
@@ -14056,9 +14052,7 @@ dtrace_helper_destroygen(int gen)
 
        return (0);
 }
-#endif
 
-#if defined(sun)
 static int
 dtrace_helper_validate(dtrace_helper_action_t *helper)
 {
@@ -14073,9 +14067,7 @@ dtrace_helper_validate(dtrace_helper_act
 
        return (err == 0);
 }
-#endif
 
-#if defined(sun)
 static int
 dtrace_helper_action_add(int which, dtrace_ecbdesc_t *ep)
 {
@@ -14622,6 +14614,7 @@ dtrace_helpers_create(proc_t *p)
        return (help);
 }
 
+#if defined(sun)
 static void
 dtrace_helpers_destroy(void)
 {
@@ -16466,6 +16459,7 @@ _fini(void)
 #else
 
 static d_ioctl_t       dtrace_ioctl;
+static d_ioctl_t       dtrace_ioctl_helper;
 static void            dtrace_load(void *);
 static int             dtrace_unload(void);
 #if __FreeBSD_version < 800039
@@ -16474,6 +16468,7 @@ static struct clonedevs *dtrace_clones; 
 static eventhandler_tag        eh_tag;                 /* Event handler tag. */
 #else
 static struct cdev     *dtrace_dev;
+static struct cdev     *helper_dev;
 #endif
 
 void dtrace_invop_init(void);
@@ -16488,6 +16483,13 @@ static struct cdevsw dtrace_cdevsw = {
        .d_name         = "dtrace",
 };
 
+static struct cdevsw helper_cdevsw = {
+       .d_version      = D_VERSION,
+       .d_flags        = D_TRACKCLOSE | D_NEEDMINOR,
+       .d_ioctl        = dtrace_ioctl_helper,
+       .d_name         = "helper",
+};
+
 #include <dtrace_anon.c>
 #if __FreeBSD_version < 800039
 #include <dtrace_clone.c>

Modified: head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h
==============================================================================
--- head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h      Sun Aug 
22 10:40:15 2010        (r211607)
+++ head/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace_impl.h      Sun Aug 
22 10:53:32 2010        (r211608)
@@ -1268,7 +1268,7 @@ extern void dtrace_copyout(uintptr_t, ui
 extern void dtrace_copyoutstr(uintptr_t, uintptr_t, size_t,
     volatile uint16_t *);
 extern void dtrace_getpcstack(pc_t *, int, int, uint32_t *);
-extern ulong_t dtrace_getreg(struct regs *, uint_t);
+extern ulong_t dtrace_getreg(struct trapframe *, uint_t);
 extern int dtrace_getstackdepth(int);
 extern void dtrace_getupcstack(uint64_t *, int);
 extern void dtrace_getufpstack(uint64_t *, uint64_t *, int);

Modified: head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c Sun Aug 22 10:40:15 2010        
(r211607)
+++ head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c Sun Aug 22 10:53:32 2010        
(r211608)
@@ -42,6 +42,7 @@
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+#include "regset.h"
 
 uint8_t dtrace_fuword8_nocheck(void *);
 uint16_t dtrace_fuword16_nocheck(void *);
@@ -103,12 +104,11 @@ dtrace_getustack_common(uint64_t *pcstac
 {
        volatile uint16_t *flags =
            (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
-       struct amd64_frame *frame;
        int ret = 0;
 
        ASSERT(pcstack == NULL || pcstack_limit > 0);
 
-       while (pc != 0 && sp != 0) {
+       while (pc != 0) {
                ret++;
                if (pcstack != NULL) {
                        *pcstack++ = (uint64_t)pc;
@@ -117,10 +117,12 @@ dtrace_getustack_common(uint64_t *pcstac
                                break;
                }
 
-               frame = (struct amd64_frame *) sp;
+               if (sp == 0)
+                       break;
 
-               pc = dtrace_fulword(&frame->f_retaddr);
-               sp = dtrace_fulword(&frame->f_frame);
+               pc = dtrace_fuword64((void *)(sp +
+                       offsetof(struct amd64_frame, f_retaddr)));
+               sp = dtrace_fuword64((void *)sp);
 
                /*
                 * This is totally bogus:  if we faulted, we're going to clear
@@ -141,7 +143,7 @@ dtrace_getupcstack(uint64_t *pcstack, in
 {
        proc_t *p = curproc;
        struct trapframe *tf;
-       uintptr_t pc, sp;
+       uintptr_t pc, sp, fp;
        volatile uint16_t *flags =
            (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
        int n;
@@ -165,18 +167,28 @@ dtrace_getupcstack(uint64_t *pcstack, in
                return;
 
        pc = tf->tf_rip;
+       fp = tf->tf_rbp;
        sp = tf->tf_rsp;
 
        if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+               /* 
+                * In an entry probe.  The frame pointer has not yet been
+                * pushed (that happens in the function prologue).  The
+                * best approach is to add the current pc as a missing top
+                * of stack and back the pc up to the caller, which is stored
+                * at the current stack pointer address since the call 
+                * instruction puts it there right before the branch.
+                */
+
                *pcstack++ = (uint64_t)pc;
                pcstack_limit--;
                if (pcstack_limit <= 0)
                        return;
 
-               pc = dtrace_fulword((void *) sp);
+               pc = dtrace_fuword64((void *) sp);
        }
 
-       n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
+       n = dtrace_getustack_common(pcstack, pcstack_limit, pc, fp);
        ASSERT(n >= 0);
        ASSERT(n <= pcstack_limit);
 
@@ -193,7 +205,7 @@ dtrace_getustackdepth(void)
 {
        proc_t *p = curproc;
        struct trapframe *tf;
-       uintptr_t pc, sp;
+       uintptr_t pc, fp, sp;
        int n = 0;
 
        if (p == NULL || (tf = curthread->td_frame) == NULL)
@@ -203,30 +215,40 @@ dtrace_getustackdepth(void)
                return (-1);
 
        pc = tf->tf_rip;
+       fp = tf->tf_rbp;
        sp = tf->tf_rsp;
 
        if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
-               n++;
+               /* 
+                * In an entry probe.  The frame pointer has not yet been
+                * pushed (that happens in the function prologue).  The
+                * best approach is to add the current pc as a missing top
+                * of stack and back the pc up to the caller, which is stored
+                * at the current stack pointer address since the call 
+                * instruction puts it there right before the branch.
+                */
 
-               pc = dtrace_fulword((void *) sp);
+               pc = dtrace_fuword64((void *) sp);
+               n++;
        }
 
-       n += dtrace_getustack_common(NULL, 0, pc, sp);
+       n += dtrace_getustack_common(NULL, 0, pc, fp);
 
        return (n);
 }
 
-#ifdef notyet
 void
 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
 {
-       klwp_t *lwp = ttolwp(curthread);
        proc_t *p = curproc;
-       struct regs *rp;
-       uintptr_t pc, sp, oldcontext;
+       struct trapframe *tf;
+       uintptr_t pc, sp, fp;
        volatile uint16_t *flags =
            (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+#ifdef notyet  /* XXX signal stack */
+       uintptr_t oldcontext;
        size_t s1, s2;
+#endif
 
        if (*flags & CPU_DTRACE_FAULT)
                return;
@@ -237,7 +259,7 @@ dtrace_getufpstack(uint64_t *pcstack, ui
        /*
         * If there's no user context we still need to zero the stack.
         */
-       if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
+       if (p == NULL || (tf = curthread->td_frame) == NULL)
                goto zero;
 
        *pcstack++ = (uint64_t)p->p_pid;
@@ -246,12 +268,15 @@ dtrace_getufpstack(uint64_t *pcstack, ui
        if (pcstack_limit <= 0)
                return;
 
-       pc = rp->r_pc;
-       sp = rp->r_fp;
-       oldcontext = lwp->lwp_oldcontext;
+       pc = tf->tf_rip;
+       sp = tf->tf_rsp;
+       fp = tf->tf_rbp;
 
+#ifdef notyet /* XXX signal stack */
+       oldcontext = lwp->lwp_oldcontext;
        s1 = sizeof (struct xframe) + 2 * sizeof (long);
        s2 = s1 + sizeof (siginfo_t);
+#endif
 
        if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
                *pcstack++ = (uint64_t)pc;
@@ -260,19 +285,20 @@ dtrace_getufpstack(uint64_t *pcstack, ui
                if (pcstack_limit <= 0)
                        return;
 
-               if (p->p_model == DATAMODEL_NATIVE)
-                       pc = dtrace_fulword((void *)rp->r_sp);
-               else
-                       pc = dtrace_fuword32((void *)rp->r_sp);
+               pc = dtrace_fuword64((void *)sp);
        }
 
-       while (pc != 0 && sp != 0) {
+       while (pc != 0) {
                *pcstack++ = (uint64_t)pc;
-               *fpstack++ = sp;
+               *fpstack++ = fp;
                pcstack_limit--;
                if (pcstack_limit <= 0)
                        break;
 
+               if (fp == 0)
+                       break;
+
+#ifdef notyet /* XXX signal stack */
                if (oldcontext == sp + s1 || oldcontext == sp + s2) {
                        ucontext_t *ucp = (ucontext_t *)oldcontext;
                        greg_t *gregs = ucp->uc_mcontext.gregs;
@@ -281,11 +307,12 @@ dtrace_getufpstack(uint64_t *pcstack, ui
                        pc = dtrace_fulword(&gregs[REG_PC]);
 
                        oldcontext = dtrace_fulword(&ucp->uc_link);
-               } else {
-                       struct xframe *fr = (struct xframe *)sp;
-
-                       pc = dtrace_fulword(&fr->fr_savpc);
-                       sp = dtrace_fulword(&fr->fr_savfp);
+               } else
+#endif /* XXX */
+               {
+                       pc = dtrace_fuword64((void *)(fp +
+                               offsetof(struct amd64_frame, f_retaddr)));
+                       fp = dtrace_fuword64((void *)fp);
                }
 
                /*
@@ -301,9 +328,8 @@ dtrace_getufpstack(uint64_t *pcstack, ui
 
 zero:
        while (pcstack_limit-- > 0)
-               *pcstack++ = NULL;
+               *pcstack++ = 0;
 }
-#endif
 
 /*ARGSUSED*/
 uint64_t
@@ -412,31 +438,30 @@ dtrace_getstackdepth(int aframes)
                return depth - aframes;
 }
 
-#ifdef notyet
 ulong_t
-dtrace_getreg(struct regs *rp, uint_t reg)
+dtrace_getreg(struct trapframe *rp, uint_t reg)
 {
-#if defined(__amd64)
+       /* This table is dependent on reg.d. */
        int regmap[] = {
-               REG_GS,         /* GS */
-               REG_FS,         /* FS */
-               REG_ES,         /* ES */
-               REG_DS,         /* DS */
-               REG_RDI,        /* EDI */
-               REG_RSI,        /* ESI */
-               REG_RBP,        /* EBP */
-               REG_RSP,        /* ESP */
-               REG_RBX,        /* EBX */
-               REG_RDX,        /* EDX */
-               REG_RCX,        /* ECX */
-               REG_RAX,        /* EAX */
-               REG_TRAPNO,     /* TRAPNO */
-               REG_ERR,        /* ERR */
-               REG_RIP,        /* EIP */
-               REG_CS,         /* CS */
-               REG_RFL,        /* EFL */
-               REG_RSP,        /* UESP */
-               REG_SS          /* SS */
+               REG_GS,         /* 0  GS */
+               REG_FS,         /* 1  FS */
+               REG_ES,         /* 2  ES */
+               REG_DS,         /* 3  DS */
+               REG_RDI,        /* 4  EDI */
+               REG_RSI,        /* 5  ESI */
+               REG_RBP,        /* 6  EBP, REG_FP */
+               REG_RSP,        /* 7  ESP */
+               REG_RBX,        /* 8  EBX, REG_R1 */
+               REG_RDX,        /* 9  EDX */
+               REG_RCX,        /* 10 ECX */
+               REG_RAX,        /* 11 EAX, REG_R0 */
+               REG_TRAPNO,     /* 12 TRAPNO */
+               REG_ERR,        /* 13 ERR */
+               REG_RIP,        /* 14 EIP, REG_PC */
+               REG_CS,         /* 15 CS */
+               REG_RFL,        /* 16 EFL, REG_PS */
+               REG_RSP,        /* 17 UESP, REG_SP */
+               REG_SS          /* 18 SS */
        };
 
        if (reg <= SS) {
@@ -447,77 +472,68 @@ dtrace_getreg(struct regs *rp, uint_t re
 
                reg = regmap[reg];
        } else {
+               /* This is dependent on reg.d. */
                reg -= SS + 1;
        }
 
        switch (reg) {
        case REG_RDI:
-               return (rp->r_rdi);
+               return (rp->tf_rdi);
        case REG_RSI:
-               return (rp->r_rsi);
+               return (rp->tf_rsi);
        case REG_RDX:
-               return (rp->r_rdx);
+               return (rp->tf_rdx);
        case REG_RCX:
-               return (rp->r_rcx);
+               return (rp->tf_rcx);
        case REG_R8:
-               return (rp->r_r8);
+               return (rp->tf_r8);
        case REG_R9:
-               return (rp->r_r9);
+               return (rp->tf_r9);
        case REG_RAX:
-               return (rp->r_rax);
+               return (rp->tf_rax);
        case REG_RBX:
-               return (rp->r_rbx);
+               return (rp->tf_rbx);
        case REG_RBP:
-               return (rp->r_rbp);
+               return (rp->tf_rbp);
        case REG_R10:
-               return (rp->r_r10);
+               return (rp->tf_r10);
        case REG_R11:
-               return (rp->r_r11);
+               return (rp->tf_r11);
        case REG_R12:
-               return (rp->r_r12);
+               return (rp->tf_r12);
        case REG_R13:
-               return (rp->r_r13);
+               return (rp->tf_r13);
        case REG_R14:
-               return (rp->r_r14);
+               return (rp->tf_r14);
        case REG_R15:
-               return (rp->r_r15);
+               return (rp->tf_r15);
        case REG_DS:
-               return (rp->r_ds);
+               return (rp->tf_ds);
        case REG_ES:
-               return (rp->r_es);
+               return (rp->tf_es);
        case REG_FS:
-               return (rp->r_fs);
+               return (rp->tf_fs);
        case REG_GS:
-               return (rp->r_gs);
+               return (rp->tf_gs);
        case REG_TRAPNO:
-               return (rp->r_trapno);
+               return (rp->tf_trapno);
        case REG_ERR:
-               return (rp->r_err);
+               return (rp->tf_err);
        case REG_RIP:
-               return (rp->r_rip);
+               return (rp->tf_rip);
        case REG_CS:
-               return (rp->r_cs);
+               return (rp->tf_cs);
        case REG_SS:
-               return (rp->r_ss);
+               return (rp->tf_ss);
        case REG_RFL:
-               return (rp->r_rfl);
+               return (rp->tf_rflags);
        case REG_RSP:
-               return (rp->r_rsp);
+               return (rp->tf_rsp);
        default:
                DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
                return (0);
        }
-
-#else
-       if (reg > SS) {
-               DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-               return (0);
-       }
-
-       return ((&rp->r_gs)[reg]);
-#endif
 }
-#endif
 
 static int
 dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)

Added: head/sys/cddl/dev/dtrace/amd64/regset.h
==============================================================================
--- /dev/null   00:00:00 1970   (empty, because file is newly added)
+++ head/sys/cddl/dev/dtrace/amd64/regset.h     Sun Aug 22 10:53:32 2010        
(r211608)
@@ -0,0 +1,127 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD$ 
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+/*     Copyright (c) 1990, 1991 UNIX System Laboratories, Inc. */
+
+/*     Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T         */
+/*     All Rights Reserved     */
+
+#ifndef        _REGSET_H
+#define        _REGSET_H
+
+/*
+ * #pragma ident       "@(#)regset.h   1.11    05/06/08 SMI"
+ */
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*
+ * The names and offsets defined here should be specified by the
+ * AMD64 ABI suppl.
+ *
+ * We make fsbase and gsbase part of the lwp context (since they're
+ * the only way to access the full 64-bit address range via the segment
+ * registers) and thus belong here too.  However we treat them as
+ * read-only; if %fs or %gs are updated, the results of the descriptor
+ * table lookup that those updates implicitly cause will be reflected
+ * in the corresponding fsbase and/or gsbase values the next time the
+ * context can be inspected.  However it is NOT possible to override
+ * the fsbase/gsbase settings via this interface.
+ *
+ * Direct modification of the base registers (thus overriding the
+ * descriptor table base address) can be achieved with _lwp_setprivate.
+ */
+
+#define        REG_GSBASE      27
+#define        REG_FSBASE      26
+#define        REG_DS          25
+#define        REG_ES          24
+
+#define        REG_GS          23
+#define        REG_FS          22
+#define        REG_SS          21
+#define        REG_RSP         20
+#define        REG_RFL         19
+#define        REG_CS          18
+#define        REG_RIP         17
+#define        REG_ERR         16
+#define        REG_TRAPNO      15
+#define        REG_RAX         14
+#define        REG_RCX         13
+#define        REG_RDX         12
+#define        REG_RBX         11
+#define        REG_RBP         10
+#define        REG_RSI         9
+#define        REG_RDI         8
+#define        REG_R8          7
+#define        REG_R9          6
+#define        REG_R10         5
+#define        REG_R11         4
+#define        REG_R12         3
+#define        REG_R13         2
+#define        REG_R14         1
+#define        REG_R15         0
+
+/*
+ * The names and offsets defined here are specified by i386 ABI suppl.
+ */
+
+#define        SS              18      /* only stored on a privilege 
transition */
+#define        UESP            17      /* only stored on a privilege 
transition */
+#define        EFL             16
+#define        CS              15
+#define        EIP             14
+#define        ERR             13
+#define        TRAPNO          12
+#define        EAX             11
+#define        ECX             10
+#define        EDX             9
+#define        EBX             8
+#define        ESP             7
+#define        EBP             6
+#define        ESI             5
+#define        EDI             4
+#define        DS              3
+#define        ES              2
+#define        FS              1
+#define        GS              0
+
+#define REG_PC  EIP
+#define REG_FP  EBP
+#define REG_SP  UESP
+#define REG_PS  EFL
+#define REG_R0  EAX
+#define REG_R1  EDX
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* _REGSET_H */

Modified: head/sys/cddl/dev/dtrace/dtrace_ioctl.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_ioctl.c     Sun Aug 22 10:40:15 2010        
(r211607)
+++ head/sys/cddl/dev/dtrace/dtrace_ioctl.c     Sun Aug 22 10:53:32 2010        
(r211608)
@@ -27,6 +27,55 @@ SYSCTL_INT(_debug_dtrace, OID_AUTO, verb
 
 #define DTRACE_IOCTL_PRINTF(fmt, ...)  if (dtrace_verbose_ioctl) printf(fmt, 
## __VA_ARGS__ )
 
+static int
+dtrace_ioctl_helper(struct cdev *dev, u_long cmd, caddr_t addr, int flags,
+    struct thread *td)
+{
+       int rval;
+       dof_helper_t *dhp = NULL;
+       dof_hdr_t *dof = NULL;
+
+       switch (cmd) {
+       case DTRACEHIOC_ADDDOF:
+               dhp = (dof_helper_t *)addr;
+               /* XXX all because dofhp_dof is 64 bit */
+#ifdef __i386
+               addr = (caddr_t)(uint32_t)dhp->dofhp_dof;
+#else
+               addr = (caddr_t)dhp->dofhp_dof;
+#endif
+               /* FALLTHROUGH */
+       case DTRACEHIOC_ADD:
+               dof = dtrace_dof_copyin((intptr_t)addr, &rval);
+
+               if (dof == NULL)
+                       return (rval);
+
+               mutex_enter(&dtrace_lock);
+               if ((rval = dtrace_helper_slurp((dof_hdr_t *)dof, dhp)) != -1) {
+                       if (dhp) {
+                               dhp->gen = rval;
+                               copyout(dhp, addr, sizeof(*dhp));
+                       }
+                       rval = 0;
+               } else {
+                       rval = EINVAL;
+               }
+               mutex_exit(&dtrace_lock);
+               return (rval);
+       case DTRACEHIOC_REMOVE:
+               mutex_enter(&dtrace_lock);
+               rval = dtrace_helper_destroygen((int)*addr);
+               mutex_exit(&dtrace_lock);
+
+               return (rval);
+       default:
+               break;
+       }
+
+       return (ENOTTY);
+}
+
 /* ARGSUSED */
 static int
 dtrace_ioctl(struct cdev *dev, u_long cmd, caddr_t addr,

Modified: head/sys/cddl/dev/dtrace/dtrace_load.c
==============================================================================
--- head/sys/cddl/dev/dtrace/dtrace_load.c      Sun Aug 22 10:40:15 2010        
(r211607)
+++ head/sys/cddl/dev/dtrace/dtrace_load.c      Sun Aug 22 10:53:32 2010        
(r211608)
@@ -161,7 +161,10 @@ dtrace_load(void *dummy)
        /* Setup device cloning events. */
        eh_tag = EVENTHANDLER_REGISTER(dev_clone, dtrace_clone, 0, 1000);
 #else
-       dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600, 
"dtrace/dtrace");
+       dtrace_dev = make_dev(&dtrace_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+           "dtrace/dtrace");
+       helper_dev = make_dev(&helper_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
+           "dtrace/helper");
 #endif
 
        return;

Modified: head/sys/cddl/dev/dtrace/i386/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/i386/dtrace_isa.c  Sun Aug 22 10:40:15 2010        
(r211607)
+++ head/sys/cddl/dev/dtrace/i386/dtrace_isa.c  Sun Aug 22 10:53:32 2010        
(r211608)
@@ -33,13 +33,17 @@
 #include <sys/stack.h>
 #include <sys/pcpu.h>
 
+#include <machine/frame.h>
 #include <machine/md_var.h>
+#include <machine/pcb.h>
 #include <machine/stack.h>
 
 #include <vm/vm.h>
 #include <vm/vm_param.h>
 #include <vm/pmap.h>
 
+#include "regset.h"
+
 extern uintptr_t kernbase;
 uintptr_t kernelbase = (uintptr_t) &kernbase;
 
@@ -100,21 +104,22 @@ dtrace_getpcstack(pc_t *pcstack, int pcs
        }
 }
 
-#ifdef notyet
 static int
 dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
     uintptr_t sp)
 {
-       klwp_t *lwp = ttolwp(curthread);
+#ifdef notyet
        proc_t *p = curproc;
-       uintptr_t oldcontext = lwp->lwp_oldcontext;
+       uintptr_t oldcontext = lwp->lwp_oldcontext; /* XXX signal stack. */
+       size_t s1, s2;
+#endif
        volatile uint16_t *flags =
            (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
-       size_t s1, s2;
        int ret = 0;
 
        ASSERT(pcstack == NULL || pcstack_limit > 0);
 
+#ifdef notyet /* XXX signal stack. */
        if (p->p_model == DATAMODEL_NATIVE) {
                s1 = sizeof (struct frame) + 2 * sizeof (long);
                s2 = s1 + sizeof (siginfo_t);
@@ -122,8 +127,9 @@ dtrace_getustack_common(uint64_t *pcstac
                s1 = sizeof (struct frame32) + 3 * sizeof (int);
                s2 = s1 + sizeof (siginfo32_t);
        }
+#endif
 
-       while (pc != 0 && sp != 0) {
+       while (pc != 0) {
                ret++;
                if (pcstack != NULL) {
                        *pcstack++ = (uint64_t)pc;
@@ -132,6 +138,10 @@ dtrace_getustack_common(uint64_t *pcstac
                                break;
                }
 
+               if (sp == 0)
+                       break;
+
+#ifdef notyet /* XXX signal stack. */ 
                if (oldcontext == sp + s1 || oldcontext == sp + s2) {
                        if (p->p_model == DATAMODEL_NATIVE) {
                                ucontext_t *ucp = (ucontext_t *)oldcontext;
@@ -163,6 +173,11 @@ dtrace_getustack_common(uint64_t *pcstac
                                sp = dtrace_fuword32(&fr->fr_savfp);
                        }
                }
+#else
+               pc = dtrace_fuword32((void *)(sp +
+                       offsetof(struct i386_frame, f_retaddr)));
+               sp = dtrace_fuword32((void *)sp);
+#endif /* ! notyet */
 
                /*
                 * This is totally bogus:  if we faulted, we're going to clear
@@ -181,10 +196,9 @@ dtrace_getustack_common(uint64_t *pcstac
 void
 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
 {
-       klwp_t *lwp = ttolwp(curthread);
        proc_t *p = curproc;
-       struct regs *rp;
-       uintptr_t pc, sp;
+       struct trapframe *tf;
+       uintptr_t pc, sp, fp;
        volatile uint16_t *flags =
            (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
        int n;
@@ -198,7 +212,7 @@ dtrace_getupcstack(uint64_t *pcstack, in
        /*
         * If there's no user context we still need to zero the stack.
         */
-       if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
+       if (p == NULL || (tf = curthread->td_frame) == NULL)
                goto zero;
 
        *pcstack++ = (uint64_t)p->p_pid;
@@ -207,19 +221,26 @@ dtrace_getupcstack(uint64_t *pcstack, in
        if (pcstack_limit <= 0)
                return;
 
-       pc = rp->r_pc;
-       sp = rp->r_fp;
+       pc = tf->tf_eip;
+       fp = tf->tf_ebp;
+       sp = tf->tf_esp;
 
        if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+               /*
+                * In an entry probe.  The frame pointer has not yet been
+                * pushed (that happens in the function prologue).  The
+                * best approach is to add the current pc as a missing top
+                * of stack and back the pc up to the caller, which is stored
+                * at the current stack pointer address since the call 
+                * instruction puts it there right before the branch.
+                */
+
                *pcstack++ = (uint64_t)pc;
                pcstack_limit--;
                if (pcstack_limit <= 0)
                        return;
 
-               if (p->p_model == DATAMODEL_NATIVE)
-                       pc = dtrace_fulword((void *)rp->r_sp);
-               else
-                       pc = dtrace_fuword32((void *)rp->r_sp);
+               pc = dtrace_fuword32((void *) sp);
        }
 
        n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
@@ -231,24 +252,58 @@ dtrace_getupcstack(uint64_t *pcstack, in
 
 zero:
        while (pcstack_limit-- > 0)
-               *pcstack++ = NULL;
+               *pcstack++ = 0;
 }
 
 int
 dtrace_getustackdepth(void)
 {
+       proc_t *p = curproc;
+       struct trapframe *tf;
+       uintptr_t pc, fp, sp;
+       int n = 0;
+
+       if (p == NULL || (tf = curthread->td_frame) == NULL)
+               return (0);
+
+       if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
+               return (-1);
+
+       pc = tf->tf_eip;
+       fp = tf->tf_ebp;
+       sp = tf->tf_esp;
+
+       if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+               /*
+                * In an entry probe.  The frame pointer has not yet been
+                * pushed (that happens in the function prologue).  The
+                * best approach is to add the current pc as a missing top
+                * of stack and back the pc up to the caller, which is stored
+                * at the current stack pointer address since the call 
+                * instruction puts it there right before the branch.
+                */
+
+               pc = dtrace_fuword32((void *) sp);
+               n++;
+       }
+
+       n += dtrace_getustack_common(NULL, 0, pc, fp);
+
+       return (n);
 }
 
 void

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***
_______________________________________________
svn-src-all@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to