From: Kris Van Hees Date: Sun, 9 Sep 2012 21:34:48 +0000 (-0400) Subject: Additional action support (and bug fixes). X-Git-Tag: v4.1.12-111.0.20170907_2225~3^2~3^2~184 X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=8098ea9782ab37e66af2bd6b6db83ea4916738ad;p=users%2Fjedix%2Flinux-maple.git Additional action support (and bug fixes). 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 --- diff --git a/dtrace/dtrace.h b/dtrace/dtrace.h index e6cbb332fdcc8..7cfe731804a92 100644 --- a/dtrace/dtrace.h +++ b/dtrace/dtrace.h @@ -3,6 +3,7 @@ #include #include +#include #include #include #include @@ -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 diff --git a/dtrace/dtrace_dif.c b/dtrace/dtrace_dif.c index 40afbcd080360..b120ef54c95cc 100644 --- a/dtrace/dtrace_dif.c +++ b/dtrace/dtrace_dif.c @@ -34,6 +34,8 @@ #include #include +#include + #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; + } + } } diff --git a/dtrace/dtrace_isa.c b/dtrace/dtrace_isa.c index 1020009110c3a..4eca74d14f157 100644 --- a/dtrace/dtrace_isa.c +++ b/dtrace/dtrace_isa.c @@ -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; diff --git a/dtrace/dtrace_probe.c b/dtrace/dtrace_probe.c index f188058571c43..aa7bcdb2447d6 100644 --- a/dtrace/dtrace_probe.c +++ b/dtrace/dtrace_probe.c @@ -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(¤t->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); diff --git a/dtrace/dtrace_state.c b/dtrace/dtrace_state.c index 14035688af73a..5c690f7c229b1 100644 --- a/dtrace/dtrace_state.c +++ b/dtrace/dtrace_state.c @@ -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;