From e9aae3496e9cb06ce6fb9be571097053d530278e Mon Sep 17 00:00:00 2001 From: Justin Hibbits Date: Sat, 13 Apr 2019 03:32:21 +0000 Subject: [PATCH] powerpc/dtrace: Fix dtrace powerpc asm, and simplify stack walking Fix some execution bugs in the dtrace powerpc asm. addme pulls in the carry flag which we don't want, and the result wasn't recorded anyways, so the following beq to check for exit condition wasn't checking the right condition. Simplify the stack walking in dtrace_isa.c, so there's only a single walker that handles both pc and sp. This should make it easier to follow, and any bugfix that may be needed for walking only needs to be made in one place instead of two now. MFC after: 2 weeks --- sys/cddl/dev/dtrace/powerpc/dtrace_asm.S | 13 ++++-- sys/cddl/dev/dtrace/powerpc/dtrace_isa.c | 53 +++++++----------------- 2 files changed, 23 insertions(+), 43 deletions(-) diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S index 7a4d8c3af893..d5af4d11ca7d 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S @@ -148,14 +148,19 @@ dtrace_copystr(uintptr_t uaddr, uintptr_t kaddr, size_t size, volatile uint16_t *flags) */ ASENTRY_NOPROF(dtrace_copystr) - addme %r7,%r3 - addme %r8,%r4 + subi %r7,%r3,1 + subi %r8,%r4,1 1: lbzu %r3,1(%r7) stbu %r3,1(%r8) - addme %r5,%r5 + subi %r5,%r5,1 +#ifdef __powerpc64__ + cmpldi %r5,0 +#else + cmplwi %r5,0 +#endif beq 2f - or %r3,%r3,%r3 + cmplwi %r3,0 beq 2f andi. %r0,%r5,0x0fff beq 2f diff --git a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c index aef774095def..e3e93317f488 100644 --- a/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c +++ b/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c @@ -94,11 +94,10 @@ dtrace_sp_inkernel(uintptr_t sp) return (1); } -static __inline uintptr_t -dtrace_next_sp(uintptr_t sp) +static __inline void +dtrace_next_sp_pc(uintptr_t sp, uintptr_t *nsp, uintptr_t *pc) { vm_offset_t callpc; - uintptr_t *r1; struct trapframe *frame; #ifdef __powerpc64__ @@ -115,39 +114,17 @@ dtrace_next_sp(uintptr_t sp) callpc + OFFSET == (vm_offset_t) &asttrapexit)) { /* Access the trap frame */ frame = (struct trapframe *)(sp + FRAME_OFFSET); - r1 = (uintptr_t *)frame->fixreg[1]; - if (r1 == NULL) - return (0); - return (*r1); + + if (nsp != NULL) + *nsp = frame->fixreg[1]; + if (pc != NULL) + *pc = frame->srr0; } - return (*(uintptr_t*)sp); -} - -static __inline uintptr_t -dtrace_get_pc(uintptr_t sp) -{ - struct trapframe *frame; - vm_offset_t callpc; - -#ifdef __powerpc64__ - callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64); -#else - callpc = *(vm_offset_t *)(sp + RETURN_OFFSET); -#endif - - /* - * trapexit() and asttrapexit() are sentinels - * for kernel stack tracing. - */ - if ((callpc + OFFSET == (vm_offset_t) &trapexit || - callpc + OFFSET == (vm_offset_t) &asttrapexit)) { - /* Access the trap frame */ - frame = (struct trapframe *)(sp + FRAME_OFFSET); - return (frame->srr0); - } - - return (callpc); + if (nsp != NULL) + *nsp = *(uintptr_t *)sp; + if (pc != NULL) + *pc = callpc; } greg_t @@ -179,7 +156,8 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, if (!dtrace_sp_inkernel(sp)) break; - callpc = dtrace_get_pc(sp); + osp = sp; + dtrace_next_sp_pc(osp, &sp, &callpc); if (aframes > 0) { aframes--; @@ -190,9 +168,6 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, else { pcstack[depth++] = callpc; } - - osp = sp; - sp = dtrace_next_sp(sp); } for (; depth < pcstack_limit; depth++) { @@ -546,7 +521,7 @@ dtrace_getstackdepth(int aframes) else aframes--; osp = sp; - sp = dtrace_next_sp(sp); + dtrace_next_sp_pc(sp, &sp, NULL); } if (depth < aframes) return (0);