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__
_______________________________________________
svn-src-head@freebsd.org mailing list
http://lists.freebsd.org/mailman/listinfo/svn-src-head
To unsubscribe, send any mail to "svn-src-head-unsubscr...@freebsd.org"

Reply via email to