diff options
Diffstat (limited to 'sys/cddl/dev/dtrace/amd64/dtrace_isa.c')
-rw-r--r-- | sys/cddl/dev/dtrace/amd64/dtrace_isa.c | 198 |
1 files changed, 107 insertions, 91 deletions
diff --git a/sys/cddl/dev/dtrace/amd64/dtrace_isa.c b/sys/cddl/dev/dtrace/amd64/dtrace_isa.c index c58e88e..d9ed080 100644 --- a/sys/cddl/dev/dtrace/amd64/dtrace_isa.c +++ b/sys/cddl/dev/dtrace/amd64/dtrace_isa.c @@ -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 *pcstack, int pcstack_limit, uintptr_t pc, { 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 *pcstack, int pcstack_limit, uintptr_t pc, 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, int pcstack_limit) { 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, int pcstack_limit) 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, uint64_t *fpstack, int pcstack_limit) /* * 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, uint64_t *fpstack, int pcstack_limit) 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, uint64_t *fpstack, int 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_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, uint64_t *fpstack, int pcstack_limit) 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, uint64_t *fpstack, int pcstack_limit) 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 reg) 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) |