svn commit: r271602 - head/sys/dev/hwpmc

Justin Hibbits jhibbits at FreeBSD.org
Sun Sep 14 22:03:42 UTC 2014


Author: jhibbits
Date: Sun Sep 14 22:03:41 2014
New Revision: 271602
URL: http://svnweb.freebsd.org/changeset/base/271602

Log:
  Fix PowerPC backtraces.  Since kernel and user have completely separate address
  spaces, rather than a split address, we actually can't check for being within
  the kernel's address range.  Instead, do what other backtraces do, and use
  trapexit()/asttrapexit() as the stack sentinel.
  
  MFC after:	3 weeks

Modified:
  head/sys/dev/hwpmc/hwpmc_powerpc.c

Modified: head/sys/dev/hwpmc/hwpmc_powerpc.c
==============================================================================
--- head/sys/dev/hwpmc/hwpmc_powerpc.c	Sun Sep 14 21:21:03 2014	(r271601)
+++ head/sys/dev/hwpmc/hwpmc_powerpc.c	Sun Sep 14 22:03:41 2014	(r271602)
@@ -40,14 +40,15 @@ __FBSDID("$FreeBSD$");
 #include <machine/pte.h>
 #include <machine/sr.h>
 #include <machine/cpu.h>
-#include <machine/vmparam.h> /* For VM_MIN_KERNEL_ADDRESS/VM_MAX_KERNEL_ADDRESS */
+#include <machine/stack.h>
 
 #include "hwpmc_powerpc.h"
 
-#define INKERNEL(x)	(((vm_offset_t)(x)) <= VM_MAX_KERNEL_ADDRESS && \
-		((vm_offset_t)(x)) >= VM_MIN_KERNEL_ADDRESS)
-#define INUSER(x)	(((vm_offset_t)(x)) <= VM_MAXUSER_ADDRESS && \
-		((vm_offset_t)(x)) >= VM_MIN_ADDRESS)
+#ifdef __powerpc64__
+#define OFFSET 4 /* Account for the TOC reload slot */
+#else
+#define OFFSET 0
+#endif
 
 struct powerpc_cpu **powerpc_pcpu;
 
@@ -56,20 +57,33 @@ pmc_save_kernel_callchain(uintptr_t *cc,
     struct trapframe *tf)
 {
 	uintptr_t *osp, *sp;
+	uintptr_t pc;
 	int frames = 0;
 
 	cc[frames++] = PMC_TRAPFRAME_TO_PC(tf);
 	sp = (uintptr_t *)PMC_TRAPFRAME_TO_FP(tf);
-	osp = NULL;
+	osp = (uintptr_t *)PAGE_SIZE;
 
 	for (; frames < maxsamples; frames++) {
-		if (!INKERNEL(sp) || sp <= osp)
+		if (sp <= osp)
 			break;
-#ifdef __powerpc64__
-		cc[frames] = sp[2];
-#else
-		cc[frames] = sp[1];
-#endif
+	    #ifdef __powerpc64__
+		pc = sp[2];
+	    #else
+		pc = sp[1];
+	    #endif
+		if ((pc & 3) || (pc < 0x100))
+			break;
+
+		/*
+		 * trapexit() and asttrapexit() are sentinels
+		 * for kernel stack tracing.
+		 * */
+		if (pc + OFFSET == (uintptr_t) &trapexit ||
+		    pc + OFFSET == (uintptr_t) &asttrapexit)
+			break;
+
+		cc[frames] = pc;
 		osp = sp;
 		sp = (uintptr_t *)*sp;
 	}
@@ -194,7 +208,7 @@ pmc_save_user_callchain(uintptr_t *cc, i
 	osp = NULL;
 
 	for (; frames < maxsamples; frames++) {
-		if (!INUSER(sp) || sp <= osp)
+		if (sp <= osp)
 			break;
 		osp = sp;
 #ifdef __powerpc64__


More information about the svn-src-all mailing list