Skip site navigation (1)Skip section navigation (2)
Date:      Fri, 17 May 2019 19:57:09 +0000 (UTC)
From:      Justin Hibbits <jhibbits@FreeBSD.org>
To:        src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org
Subject:   svn commit: r347943 - head/sys/cddl/dev/dtrace/powerpc
Message-ID:  <201905171957.x4HJv9jw049477@repo.freebsd.org>

next in thread | raw e-mail | index | archive | help
Author: jhibbits
Date: Fri May 17 19:57:08 2019
New Revision: 347943
URL: https://svnweb.freebsd.org/changeset/base/347943

Log:
  powerpc/dtrace: Actually fix stack traces
  
  Fix stack unwinding such that requesting N stack frames in lockstat will
  actually give you N frames, not anywhere from 0-3 as had been before.
  
  lockstat prints the mutex function instead of the caller as the reported
  locker, but the stack frame is detailed enough to find the real caller.
  
  MFC after:	2 weeks

Modified:
  head/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
  head/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c

Modified: head/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
==============================================================================
--- head/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	Fri May 17 19:27:07 2019	(r347942)
+++ head/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	Fri May 17 19:57:08 2019	(r347943)
@@ -179,3 +179,13 @@ ASENTRY_NOPROF(dtrace_caller)
 	li	%r3, -1
 	blr
 END(dtrace_caller)
+
+/*
+greg_t
+dtrace_getfp(void)
+*/
+ASENTRY_NOPROF(dtrace_getfp)
+	mr	%r3,%r31
+	blr
+END(dtrace_getfp)
+

Modified: head/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
==============================================================================
--- head/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	Fri May 17 19:27:07 2019	(r347942)
+++ head/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	Fri May 17 19:57:08 2019	(r347943)
@@ -61,8 +61,10 @@
 #define	FRAME_OFFSET	8
 #endif
 
-#define INKERNEL(x)	((x) <= VM_MAX_KERNEL_ADDRESS && \
-		(x) >= VM_MIN_KERNEL_ADDRESS)
+#define INKERNEL(x)	(((x) <= VM_MAX_KERNEL_ADDRESS && \
+		(x) >= VM_MIN_KERNEL_ADDRESS) || \
+		(PMAP_HAS_DMAP && (x) >= DMAP_BASE_ADDRESS && \
+		 (x) <= DMAP_MAX_ADDRESS))
 
 static __inline int
 dtrace_sp_inkernel(uintptr_t sp)
@@ -70,6 +72,9 @@ dtrace_sp_inkernel(uintptr_t sp)
 	struct trapframe *frame;
 	vm_offset_t callpc;
 
+	/* Not within the kernel, or not aligned. */
+	if (!INKERNEL(sp) || (sp & 0xf) != 0)
+		return (0);
 #ifdef __powerpc64__
 	callpc = *(vm_offset_t *)(sp + RETURN_OFFSET64);
 #else
@@ -84,8 +89,6 @@ dtrace_sp_inkernel(uintptr_t sp)
 	 */
 	if (callpc + OFFSET == (vm_offset_t) &trapexit ||
 	    callpc + OFFSET == (vm_offset_t) &asttrapexit) {
-		if (sp == 0)
-			return (0);
 		frame = (struct trapframe *)(sp + FRAME_OFFSET);
 
 		return ((frame->srr1 & PSL_PR) == 0);
@@ -119,6 +122,7 @@ dtrace_next_sp_pc(uintptr_t sp, uintptr_t *nsp, uintpt
 			*nsp = frame->fixreg[1];
 		if (pc != NULL)
 			*pc = frame->srr0;
+		return;
 	}
 
 	if (nsp != NULL)
@@ -127,12 +131,6 @@ dtrace_next_sp_pc(uintptr_t sp, uintptr_t *nsp, uintpt
 		*pc = callpc;
 }
 
-greg_t
-dtrace_getfp(void)
-{
-	return (greg_t)__builtin_frame_address(0);
-}
-
 void
 dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
     uint32_t *intrpc)
@@ -148,7 +146,7 @@ dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, in
 
 	aframes++;
 
-	sp = dtrace_getfp();
+	sp = (uintptr_t)__builtin_frame_address(0);
 
 	while (depth < pcstack_limit) {
 		if (sp <= osp)
@@ -418,7 +416,7 @@ uint64_t
 dtrace_getarg(int arg, int aframes)
 {
 	uintptr_t val;
-	uintptr_t *fp = (uintptr_t *)dtrace_getfp();
+	uintptr_t *fp = (uintptr_t *)__builtin_frame_address(0);
 	uintptr_t *stack;
 	int i;
 
@@ -432,8 +430,8 @@ dtrace_getarg(int arg, int aframes)
 		fp = (uintptr_t *)*fp;
 
 		/*
-		 * On ppc32 AIM, and booke, trapexit() is the immediately following
-		 * label.  On ppc64 AIM trapexit() follows a nop.
+		 * On ppc32 trapexit() is the immediately following label.  On
+		 * ppc64 AIM trapexit() follows a nop.
 		 */
 #ifdef __powerpc64__
 		if ((long)(fp[2]) + 4 == (long)trapexit) {
@@ -506,9 +504,7 @@ dtrace_getstackdepth(int aframes)
 	vm_offset_t callpc;
 
 	osp = PAGE_SIZE;
-	aframes++;
-	sp = dtrace_getfp();
-	depth++;
+	sp = (uintptr_t)__builtin_frame_address(0);
 	for(;;) {
 		if (sp <= osp)
 			break;
@@ -516,17 +512,14 @@ dtrace_getstackdepth(int aframes)
 		if (!dtrace_sp_inkernel(sp))
 			break;
 
-		if (aframes == 0)
-			depth++;
-		else
-			aframes--;
+		depth++;
 		osp = sp;
 		dtrace_next_sp_pc(sp, &sp, NULL);
 	}
 	if (depth < aframes)
 		return (0);
 
-	return (depth);
+	return (depth - aframes);
 }
 
 ulong_t



Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201905171957.x4HJv9jw049477>