]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
Additional action support (and bug fixes).
authorKris Van Hees <kris.van.hees@oracle.com>
Sun, 9 Sep 2012 21:34:48 +0000 (17:34 -0400)
committerKris Van Hees <kris.van.hees@oracle.com>
Sun, 9 Sep 2012 21:34:48 +0000 (17:34 -0400)
Removed ASSIST_* definitions because they are no longer necessary (though they
may come back in the future).

Changed the behaviour of DTrace in interrupt context to base it on in_irq()
rather than in_interrupt().

On Linux it is always safe to dereference current, so there is no need to do
special casing on various process-based DIF functions.  There is no need to
fake values coming from the 0-pid process.

Added curcpu variables.

Added d_path() function.  This takes a struct path and turns it into a string.

Renumbered the register IDs to match the xlator support at userspace, and to
also match the on-stack order of registers.

Have dtrace_getreg() operate on the task rather than just a set of registers,
because (in 64-bit mode) segment registers have their value stored in fields
in the process-specific task info.

Implemented the raise() action.

Changed the deadman interal to 10s, and timeout/user to 120s.

Signed-off-by: Kris Van Hees <kris.van.hees@oracle.com>
dtrace/dtrace.h
dtrace/dtrace_dif.c
dtrace/dtrace_isa.c
dtrace/dtrace_probe.c
dtrace/dtrace_state.c

index e6cbb332fdcc83c334e6309a1226f2975df525dd..7cfe731804a929aca33ddbba905b6d097ad49a8c 100644 (file)
@@ -3,6 +3,7 @@
 
 #include <linux/cred.h>
 #include <linux/cyclic.h>
+#include <linux/dtrace_cpu.h>
 #include <linux/dtrace_os.h>
 #include <linux/idr.h>
 #include <linux/ktime.h>
@@ -296,7 +297,6 @@ typedef uint32_t    dtrace_cacheid_t;
 typedef uint32_t       dtrace_epid_t;
 typedef uint32_t       dtrace_optid_t;
 typedef uint32_t       dtrace_specid_t;
-typedef uint32_t       processorid_t;
 
 typedef uint64_t       dtrace_aggvarid_t;
 typedef uint64_t       dtrace_genid_t;
@@ -1414,6 +1414,7 @@ extern void (*dtrace_modunload)(struct module *);
 #define DIF_VAR_UID            0x011e
 #define DIF_VAR_GID            0x011f
 #define DIF_VAR_ERRNO          0x0120
+#define DIF_VAR_CURCPU         0x0121
 
 #define DIF_SUBR_RAND                  0
 #define DIF_SUBR_MUTEX_OWNED           1
@@ -1459,8 +1460,9 @@ extern void (*dtrace_modunload)(struct module *);
 #define DIF_SUBR_INET_NTOP             41
 #define DIF_SUBR_INET_NTOA             42
 #define DIF_SUBR_INET_NTOA6            43
+#define DIF_SUBR_D_PATH                        44
 
-#define DIF_SUBR_MAX                   43
+#define DIF_SUBR_MAX                   44
 
 #define DIF_INSTR_OP(i)                        (((i) >> 24) & 0xff)
 #define DIF_INSTR_R1(i)                        (((i) >> 16) & 0xff)
@@ -2302,7 +2304,7 @@ extern uintptr_t dtrace_getfp(void);
 extern uint64_t dtrace_getarg(int, int);
 extern int dtrace_getstackdepth(int);
 extern int dtrace_getustackdepth(void);
-extern ulong_t dtrace_getreg(struct pt_regs *, uint_t);
+extern ulong_t dtrace_getreg(struct task_struct *, uint_t);
 extern void dtrace_copyin(uintptr_t, uintptr_t, size_t, volatile uint16_t *);
 extern void dtrace_copyout(uintptr_t, uintptr_t, size_t, volatile uint16_t *);
 extern void dtrace_copyinstr(uintptr_t, uintptr_t, size_t,
@@ -2339,28 +2341,28 @@ extern void debug_enter(char *);
 # define REG_FS                1
 # define REG_GS                0
 #else
-# 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_GS                24
+# define REG_FS                23
+# define REG_ES                22
+# define REG_DS                21
+# define REG_SS                20
+# define REG_RSP       19
+# define REG_RFL       18
+# define REG_CS                17
+# define REG_RIP       16
+# define REG_ERR       15
 # define REG_TRAPNO    15
-# define REG_RAX       14
-# define REG_RCX       13
+# define REG_RDI       14
+# define REG_RSI       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_RCX       11
+# define REG_RAX       10
+# define REG_R8                9
+# define REG_R9                8
+# define REG_R10       7
+# define REG_R11       6
+# define REG_RBX       5
+# define REG_RBP       4
 # define REG_R12       3
 # define REG_R13       2
 # define REG_R14       1
index 40afbcd080360b1bcfc418544e24b7f482ed4a5d..b120ef54c95cc61e222456d8b22fbe3ee44132e1 100644 (file)
@@ -34,6 +34,8 @@
 #include <linux/socket.h>
 #include <net/ipv6.h>
 
+#include <linux/mount.h>
+
 #include "dtrace.h"
 
 size_t                         dtrace_global_maxsize = 16 * 1024;
@@ -882,7 +884,7 @@ void dtrace_difo_release(dtrace_difo_t *dp, dtrace_vstate_t *vstate)
  */
 #define DTRACE_TLS_THRKEY(where)                                       \
        {                                                               \
-               uint_t  intr = in_interrupt() ? 1 : 0;                  \
+               uint_t  intr = in_irq() ? 1 : 0;                        \
                                                                        \
                (where) = ((current->pid + DIF_VARIABLE_MAX) &          \
                           (((uint64_t)1 << 63) - 1)) |                 \
@@ -1087,7 +1089,7 @@ static int dtrace_canstore(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
  */
 static int
 dtrace_canload(uint64_t addr, size_t sz, dtrace_mstate_t *mstate,
-    dtrace_vstate_t *vstate)
+              dtrace_vstate_t *vstate)
 {
        volatile uintptr_t      *illval = &this_cpu_core->cpuc_dtrace_illval;
 
@@ -1857,12 +1859,10 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                return mstate->dtms_arg[ndx];
 
        case DIF_VAR_UREGS: {
-               struct pt_regs  *regs = task_pt_regs(current);
-
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               return dtrace_getreg(regs, ndx);
+               return dtrace_getreg(current, ndx);
        }
 
        case DIF_VAR_CURTHREAD:
@@ -2036,14 +2036,6 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * Note that we are assuming that an unanchored probe is
-                * always due to a high-level interrupt.  (And we're assuming
-                * that there is only a single high level interrupt.)
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return init_task.pid;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
@@ -2054,12 +2046,6 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return init_task.real_parent->pid;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
@@ -2070,24 +2056,12 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                return (uint64_t)current->real_parent->pid;
 
        case DIF_VAR_TID:
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return init_task.pid;
-
                return (uint64_t)current->pid;
 
        case DIF_VAR_EXECNAME:
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return (uint64_t)(uintptr_t)init_task.comm;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
@@ -2102,12 +2076,6 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return (uint64_t)init_task.real_cred->uid;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
@@ -2121,12 +2089,6 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return (uint64_t)init_task.real_cred->gid;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
@@ -2140,18 +2102,15 @@ static uint64_t dtrace_dif_variable(dtrace_mstate_t *mstate,
                if (!dtrace_priv_proc(state))
                        return 0;
 
-               /*
-                * See comment in DIF_VAR_PID.
-                */
-               if (DTRACE_ANCHORED(mstate->dtms_probe) && in_interrupt())
-                       return 0;
-
                /*
                 * It is always safe to dereference current, it always points
                 * to a valid task_struct.
                 */
                return (uint64_t)current->thread.error_code;
 
+       case DIF_VAR_CURCPU:
+               return (uint64_t)(uintptr_t)this_cpu_info;
+
        default:
                DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
                return 0;
@@ -3644,6 +3603,36 @@ inetout:
                break;
        }
 
+       case DIF_SUBR_D_PATH: {
+               struct path     *path = (struct path *)tupregs[0].dttk_value;
+               char            *dest = (char *)mstate->dtms_scratch_ptr;
+               char            *ptr;
+               uint64_t        size = state->dts_options[DTRACEOPT_STRSIZE];
+
+               if (!dtrace_canload((uintptr_t)path, sizeof(struct path),
+                                   mstate, vstate)) {
+                       regs[rd] = 0;
+                       break;
+               }
+
+               if (!DTRACE_INSCRATCH(mstate, size)) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+                       regs[rd] = 0;
+                       break;
+               }
+
+               ptr = d_path(path, dest, size);
+               if (ptr < 0) {
+                       DTRACE_CPUFLAG_SET(CPU_DTRACE_NOSCRATCH);
+                       regs[rd] = 0;
+                       break;
+               }
+
+               regs[rd] = (uintptr_t)ptr;
+               mstate->dtms_scratch_ptr += size;
+               break;
+       }
+
        }
 }
 
index 1020009110c3a53c4395ac27a04f08b5ce25e27b..4eca74d14f157504176cff0544caf6c6a52ae37e 100644 (file)
@@ -197,8 +197,10 @@ int dtrace_getipl(void)
        return in_interrupt();
 }
 
-ulong_t dtrace_getreg(struct pt_regs *rp, uint_t reg)
+ulong_t dtrace_getreg(struct task_struct *task, uint_t reg)
 {
+       struct pt_regs  *rp = task_pt_regs(task);
+
 #ifdef __i386__
        if (reg > REG_SS) {
                DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
@@ -245,86 +247,53 @@ ulong_t dtrace_getreg(struct pt_regs *rp, uint_t reg)
        }
 #else
        int     regmap[] = {
-                               REG_GS,         /*  0 -> GS */
-                               REG_FS,         /*  1 -> FS */
-                               REG_ES,         /*  2 -> ES */
-                               REG_DS,         /*  3 -> DS */
+                               REG_RBX,        /*  0 -> EBX */
+                               REG_RCX,        /*  1 -> ECX */
+                               REG_RDX,        /*  2 -> EDX */
+                               REG_RSI,        /*  3 -> ESI */
                                REG_RDI,        /*  4 -> EDI */
-                               REG_RSI,        /*  5 -> ESI */
-                               REG_RBP,        /*  6 -> EBP */
-                               REG_RSP,        /*  7 -> ESP */
-                               REG_RBX,        /*  8 -> EBX */
-                               REG_RDX,        /*  9 -> EDX */
-                               REG_RCX,        /* 10 -> ECX */
-                               REG_RAX,        /* 11 -> EAX */
-                               REG_TRAPNO,     /* 12 -> TRAPNO */
-                               REG_ERR,        /* 13 -> ERR */
-                               REG_RIP,        /* 14 -> EIP */
-                               REG_CS,         /* 15 -> CS */
-                               REG_RFL,        /* 16 -> EFL */
-                               REG_RSP,        /* 17 -> UESP */
-                               REG_SS,         /* 18 -> SS */
+                               REG_RBP,        /*  5 -> EBP */
+                               REG_RAX,        /*  6 -> EAX */
+                               REG_DS,         /*  7 -> DS */
+                               REG_ES,         /*  8 -> ES */
+                               REG_FS,         /*  9 -> FS */
+                               REG_GS,         /* 10 -> GS */
+                               REG_TRAPNO,     /* 11 -> TRAPNO */
+                               REG_RIP,        /* 12 -> EIP */
+                               REG_CS,         /* 13 -> CS */
+                               REG_RFL,        /* 14 -> EFL */
+                               REG_RSP,        /* 15 -> UESP */
+                               REG_SS,         /* 16 -> SS */
                           };
+       if (reg > REG_GS) {
+               /*
+                * Convert register alias index into register mapping index.
+                */
+               reg -= REG_GS + 1;
 
-       if (reg <= REG_SS) {
                if (reg >= sizeof(regmap) / sizeof(int)) {
                        DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
                        return 0;
                }
 
                reg = regmap[reg];
-       } else
-               reg -= REG_SS + 1;
+       }
+
+       /*
+        * Most common case: direct index into pt_regs structure.
+        */
+       if (reg <= REG_SS)
+               return (&rp->r15)[reg];
 
        switch (reg) {
-       case REG_RDI:
-               return rp->di;
-       case REG_RSI:
-               return rp->si;
-       case REG_RDX:
-               return rp->dx;
-       case REG_RCX:
-               return rp->cx;
-       case REG_R8:
-               return rp->r8;
-       case REG_R9:
-               return rp->r9;
-       case REG_RAX:
-               return rp->ax;
-       case REG_RBX:
-               return rp->bx;
-       case REG_RBP:
-               return rp->bp;
-       case REG_R10:
-               return rp->r10;
-       case REG_R11:
-               return rp->r11;
-       case REG_R12:
-               return rp->r12;
-       case REG_R13:
-               return rp->r13;
-       case REG_R14:
-               return rp->r14;
-       case REG_R15:
-               return rp->r15;
-       case REG_CS:
        case REG_DS:
+               return task->thread.ds;
        case REG_ES:
+               return task->thread.es;
        case REG_FS:
+               return task->thread.fs;
        case REG_GS:
-               return rp->cs;
-       case REG_TRAPNO:
-               return rp->orig_ax;
-       case REG_ERR:
-               return rp->di;
-       case REG_RIP:
-               return rp->ip;
-       case REG_SS:
-               return rp->ss;
-       case REG_RFL:
-               return rp->flags;
-       case REG_RSP:
-               return rp->sp;
+               return task->thread.gs;
        default:
                DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
                return 0;
index f188058571c431ea2469f8049db2fe2bbd7c6b21..aa7bcdb2447d68dd1d0c84a7d268791bd44bed68 100644 (file)
@@ -353,11 +353,14 @@ static void dtrace_action_raise(uint64_t sig)
         * raise() has a queue depth of 1 -- we ignore all subsequent
         * invocations of the raise() action.
         */
+#if 0
+
+       sigaddset(&current->pending.signal, sig);
+       set_thread_flag(TIF_SIGPENDING);
+#else
        if (current->dtrace_sig == 0)
                current->dtrace_sig = (uint8_t)sig;
-
-//     current->sig_check = 1; /* FIXME */
-//     aston(current);         /* FIXME */
+#endif
 }
 
 static void dtrace_action_stop(void)
@@ -1151,6 +1154,14 @@ void dtrace_probe(dtrace_id_t id, uintptr_t arg0, uintptr_t arg1,
                current->dtrace_start = dtrace_gethrtime();
 
        local_irq_restore(cookie);
+
+       if (current->dtrace_sig != 0) {
+               int     sig = current->dtrace_sig;
+
+               current->dtrace_sig = 0;
+
+               send_sig(sig, current, 0);
+       }
 }
 EXPORT_SYMBOL(dtrace_probe);
 
index 14035688af73a28ca4ac47b01e8923cceae0d4c9..5c690f7c229b1e2763e8d96b342a2d80390acf9d 100644 (file)
@@ -52,9 +52,15 @@ dtrace_optval_t              dtrace_statusrate_default = NANOSEC;
 dtrace_optval_t                dtrace_statusrate_max = (uint64_t)10 * NANOSEC;
 dtrace_optval_t                dtrace_jstackframes_default = 50;
 dtrace_optval_t                dtrace_jstackstrsize_default = 512;
+#if 1
+ktime_t                        dtrace_deadman_interval = KTIME_INIT(10, 0);
+ktime_t                        dtrace_deadman_timeout = KTIME_INIT(120, 0);
+ktime_t                        dtrace_deadman_user = KTIME_INIT(120, 0);
+#else
 ktime_t                        dtrace_deadman_interval = KTIME_INIT(1, 0);
 ktime_t                        dtrace_deadman_timeout = KTIME_INIT(10, 0);
 ktime_t                        dtrace_deadman_user = KTIME_INIT(30, 0);
+#endif
 
 dtrace_id_t            dtrace_probeid_begin;
 dtrace_id_t            dtrace_probeid_end;