Skip site navigation (1)Skip section navigation (2)
Date:      Sun, 14 Sep 2014 22:03:41 +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: r271602 - head/sys/dev/hwpmc
Message-ID:  <201409142203.s8EM3fo5060209@svn.freebsd.org>

next in thread | raw e-mail | index | archive | help
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__



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