Skip site navigation (1)Skip section navigation (2)
Date:      Thu, 11 Oct 2012 18:52:59 -0400
From:      Justin Hibbits <chmeeedalf@gmail.com>
To:        Andreas Tobler <andreast-list@fgznet.ch>
Cc:        freebsd-ppc@freebsd.org
Subject:   Re: CFT: Dtrace on PowerPC
Message-ID:  <20121011185259.08cb2956@narn.knownspace>
In-Reply-To: <50773674.3050802@fgznet.ch>
References:  <20121009190838.283976e1@narn.knownspace> <507561A4.5040902@fgznet.ch> <CAHSQbTBv8H3o6g3ee8UG0xNwge2jaANahBoa8jyvrVxc04nWkg@mail.gmail.com> <50773674.3050802@fgznet.ch>

next in thread | previous in thread | raw e-mail | index | archive | help
--MP_/kq=KQQOav+pc79+hUczvDBG
Content-Type: text/plain; charset=US-ASCII
Content-Transfer-Encoding: 7bit
Content-Disposition: inline

On Thu, 11 Oct 2012 23:13:24 +0200
Andreas Tobler <andreast-list@fgznet.ch> wrote:

> Hi Justin,
> 
> On 10.10.12 16:50, Justin Hibbits wrote:
> 
> > On Wed, Oct 10, 2012 at 7:53 AM, Andreas Tobler
> > <andreast-list@fgznet.ch <mailto:andreast-list@fgznet.ch>> wrote:
> >
> >     Hi Justin!
> >
> >
> >     On 10.10.12 01:08, Justin Hibbits wrote:
> >
> >         After a few days of development, and a few weeks of
> > testing, here's Dtrace on PowerPC.  There is only one known issue
> > that I know of so far: dtruss kernel panics through an assertion.
> > I have to investigate
> >         this some more, but some dtrace -n "<probe>" testing works.
> >
> >
> >     Cool!!!
> >
> >     Three things, I have not tested this code yet but I did look
> > over it.
> >
> >     - powerpc64 support is not yet complete, right?
> >
> >
> > Nope, ppc64 is not complete.  It shouldn't be too much more work,
> > though.
> 
> Ok.
> 
> >     - sys/cddl/dev/dtrace/powerpc/__dtrace_asm.S and
> >     sys/cddl/dev/dtrace/powerpc/__dtrace_subr.c have some mips
> > leftovers or are they intentional? ($FreeBSD, _FBSDID)
> >
> >
> >   I believe these should change when actually committed (didn't set
> > the svn property when adding the code yet).
> 
> The FBSDID yes, but I guess the part in the comment not.
> 
> >     - what is the hid.h include for in sys/powerpc/aim/locore32.S?
> >
> >
> > This is from another task I've been working on for something else.
> > I'll remember to remove it when doing the actual commit.
> 
> Ok.
> 
> > Thanks for (future) testing.
> 
> One more thing, the patch for the binaries like dtrace etc. is also 
> available? Or is it meant as an exercise for the user ;)
> 
> Thanks,
> Andreas
> 

Woops, more leftovers in my previous patch.

- Justin
--MP_/kq=KQQOav+pc79+hUczvDBG
Content-Type: text/x-patch
Content-Transfer-Encoding: 7bit
Content-Disposition: attachment; filename=dtrace_ppc3.diff

Index: cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c
===================================================================
--- cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c	(revision 0)
+++ cddl/contrib/opensolaris/lib/libdtrace/powerpc/dt_isadep.c	(working copy)
@@ -0,0 +1,75 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <stdlib.h>
+#include <assert.h>
+#include <errno.h>
+#include <string.h>
+#include <libgen.h>
+
+#include <dt_impl.h>
+#include <dt_pid.h>
+
+/*ARGSUSED*/
+int
+dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
+{
+
+	dt_dprintf("%s: unimplemented\n", __func__);
+	return (DT_PROC_ERR);
+}
+
+int
+dt_pid_create_return_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, uint64_t *stret)
+{
+
+	dt_dprintf("%s: unimplemented\n", __func__);
+	return (DT_PROC_ERR);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, ulong_t off)
+{
+
+	dt_dprintf("%s: unimplemented\n", __func__);
+	return (DT_PROC_ERR);
+}
+
+/*ARGSUSED*/
+int
+dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
+    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp, const char *pattern)
+{
+
+	dt_dprintf("%s: unimplemented\n", __func__);
+	return (DT_PROC_ERR);
+}
Index: cddl/usr.sbin/Makefile
===================================================================
--- cddl/usr.sbin/Makefile	(revision 241450)
+++ cddl/usr.sbin/Makefile	(working copy)
@@ -25,4 +25,10 @@
 _dtrace=	dtrace
 .endif
 
+.if ${MACHINE_CPUARCH} == "powerpc"
+_dtrace=	dtrace
+_dtruss=	dtruss
+_lockstat=	lockstat
+.endif
+
 .include <bsd.subdir.mk>
Index: cddl/lib/libdtrace/Makefile
===================================================================
--- cddl/lib/libdtrace/Makefile	(revision 241450)
+++ cddl/lib/libdtrace/Makefile	(working copy)
@@ -74,6 +74,10 @@
 CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
 .PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/mips
 .PATH:		${.CURDIR}/../../../sys/cddl/dev/dtrace/mips
+.elif ${MACHINE_CPUARCH} == "powerpc"
+CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/mips
+.PATH:		${.CURDIR}/../../../cddl/contrib/opensolaris/lib/libdtrace/powerpc
+.PATH:		${.CURDIR}/../../../sys/cddl/dev/dtrace/powerpc
 .else
 # temporary hack
 CFLAGS+=	-I${OPENSOLARIS_SYS_DISTDIR}/uts/intel
Index: cddl/lib/Makefile
===================================================================
--- cddl/lib/Makefile	(revision 241450)
+++ cddl/lib/Makefile	(working copy)
@@ -19,7 +19,8 @@
 .endif
 .endif
 
-.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" ||  ${MACHINE_CPUARCH} == "mips"
+.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "i386" || \
+	${MACHINE_CPUARCH} == "mips" || ${MACHINE_ARCH} == "powerpc"
 _drti=		drti
 _libdtrace=	libdtrace
 .endif
Index: sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c	(revision 0)
+++ sys/cddl/contrib/opensolaris/uts/powerpc/dtrace/fasttrap_isa.c	(working copy)
@@ -0,0 +1,30 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+/*
+ * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+
+/*
+ *	XXX: Placeholder for PowerPC fasttrap code
+ */
Index: sys/cddl/contrib/opensolaris/uts/powerpc/sys/fasttrap_isa.h
===================================================================
--- sys/cddl/contrib/opensolaris/uts/powerpc/sys/fasttrap_isa.h	(revision 0)
+++ sys/cddl/contrib/opensolaris/uts/powerpc/sys/fasttrap_isa.h	(working copy)
@@ -0,0 +1,49 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#ifndef	_FASTTRAP_ISA_H
+#define	_FASTTRAP_ISA_H
+
+#pragma ident	"%Z%%M%	%I%	%E% SMI"
+
+#include <sys/types.h>
+
+#ifdef	__cplusplus
+extern "C" {
+#endif
+/*
+ *  XXXDTRACE: placehodler for PowerPC fasttrap stuff
+ */
+
+typedef	uint32_t	fasttrap_instr_t;
+#define	FASTTRAP_SUNWDTRACE_SIZE	64
+#define FASTTRAP_INSTR 0x0FFFDDDD
+
+#ifdef	__cplusplus
+}
+#endif
+
+#endif	/* _FASTTRAP_ISA_H */
Index: sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c
===================================================================
--- sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c	(revision 241450)
+++ sys/cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c	(working copy)
@@ -235,7 +235,7 @@
 static struct mtx	dtrace_unr_mtx;
 MTX_SYSINIT(dtrace_unr_mtx, &dtrace_unr_mtx, "Unique resource identifier", MTX_DEF);
 int		dtrace_in_probe;	/* non-zero if executing a probe */
-#if defined(__i386__) || defined(__amd64__) || defined(__mips__)
+#if defined(__i386__) || defined(__amd64__) || defined(__mips__) || defined(__powerpc__)
 uintptr_t	dtrace_in_probe_addr;	/* Address of invop when already in probe */
 #endif
 #endif
@@ -10762,7 +10762,7 @@
 #else
 	int i;
 
-#if defined(__amd64__) || defined(__mips__)
+#if defined(__amd64__) || defined(__mips__) || defined(__powerpc__)
 	/*
 	 * FreeBSD isn't good at limiting the amount of memory we
 	 * ask to malloc, so let's place a limit here before trying
Index: sys/cddl/dev/dtrace/powerpc/regset.h
===================================================================
Index: sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
===================================================================
--- sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	(revision 0)
+++ sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	(working copy)
@@ -0,0 +1,510 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD: head/sys/cddl/dev/dtrace/amd64/dtrace_isa.c 211608 2010-08-22 10:53:32Z rpaulo $
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+#include <sys/cdefs.h>
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/stack.h>
+#include <sys/pcpu.h>
+
+#include <machine/frame.h>
+#include <machine/md_var.h>
+#include <machine/reg.h>
+#include <machine/stack.h>
+
+#include <vm/vm.h>
+#include <vm/vm_param.h>
+#include <vm/pmap.h>
+
+#include "regset.h"
+
+uint8_t dtrace_fuword8_nocheck(void *);
+uint16_t dtrace_fuword16_nocheck(void *);
+uint32_t dtrace_fuword32_nocheck(void *);
+uint64_t dtrace_fuword64_nocheck(void *);
+
+/* Offset to the LR Save word (ppc32) */
+#define RETURN_OFFSET	4
+
+#define INKERNEL(x)	((x) <= VM_MAX_KERNEL_ADDRESS && \
+		(x) >= VM_MIN_KERNEL_ADDRESS)
+
+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)
+{
+	int depth = 0;
+	register_t sp;
+	vm_offset_t callpc;
+	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
+
+	if (intrpc != 0)
+		pcstack[depth++] = (pc_t) intrpc;
+
+	aframes++;
+
+	sp = dtrace_getfp();
+
+	while (depth < pcstack_limit) {
+		if (!INKERNEL((long) sp))
+			break;
+
+		callpc = *(uintptr_t *)(sp + RETURN_OFFSET);
+
+		if (!INKERNEL(callpc))
+			break;
+
+		if (aframes > 0) {
+			aframes--;
+			if ((aframes == 0) && (caller != 0)) {
+				pcstack[depth++] = caller;
+			}
+		}
+		else {
+			pcstack[depth++] = callpc;
+		}
+
+		sp = *(uintptr_t*)sp;
+	}
+
+	for (; depth < pcstack_limit; depth++) {
+		pcstack[depth] = 0;
+	}
+}
+
+static int
+dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
+    uintptr_t sp)
+{
+	int ret = 0;
+
+	ASSERT(pcstack == NULL || pcstack_limit > 0);
+
+	while (pc != 0) {
+		ret++;
+		if (pcstack != NULL) {
+			*pcstack++ = (uint64_t)pc;
+			pcstack_limit--;
+			if (pcstack_limit <= 0)
+				break;
+		}
+
+		if (sp == 0)
+			break;
+
+		pc = dtrace_fuword64((void *)(sp + RETURN_OFFSET));
+		sp = dtrace_fuword64((void *)sp);
+	}
+
+	return (ret);
+}
+
+void
+dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
+{
+	proc_t *p = curproc;
+	struct trapframe *tf;
+	uintptr_t pc, sp;
+	volatile uint16_t *flags =
+	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+	int n;
+
+	if (*flags & CPU_DTRACE_FAULT)
+		return;
+
+	if (pcstack_limit <= 0)
+		return;
+
+	/*
+	 * If there's no user context we still need to zero the stack.
+	 */
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
+		goto zero;
+
+	*pcstack++ = (uint64_t)p->p_pid;
+	pcstack_limit--;
+
+	if (pcstack_limit <= 0)
+		return;
+
+	pc = tf->srr0;
+	sp = tf->fixreg[1];
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		/* 
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
+
+		*pcstack++ = (uint64_t)pc;
+		pcstack_limit--;
+		if (pcstack_limit <= 0)
+			return;
+
+		pc = dtrace_fuword32((void *) sp);
+	}
+
+	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
+	ASSERT(n >= 0);
+	ASSERT(n <= pcstack_limit);
+
+	pcstack += n;
+	pcstack_limit -= n;
+
+zero:
+	while (pcstack_limit-- > 0)
+		*pcstack++ = 0;
+}
+
+int
+dtrace_getustackdepth(void)
+{
+	proc_t *p = curproc;
+	struct trapframe *tf;
+	uintptr_t pc, sp;
+	int n = 0;
+
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
+		return (0);
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
+		return (-1);
+
+	pc = tf->srr0;
+	sp = tf->fixreg[1];
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		/* 
+		 * In an entry probe.  The frame pointer has not yet been
+		 * pushed (that happens in the function prologue).  The
+		 * best approach is to add the current pc as a missing top
+		 * of stack and back the pc up to the caller, which is stored
+		 * at the current stack pointer address since the call 
+		 * instruction puts it there right before the branch.
+		 */
+
+		pc = dtrace_fuword64((void *) sp);
+		n++;
+	}
+
+	n += dtrace_getustack_common(NULL, 0, pc, sp);
+
+	return (n);
+}
+
+void
+dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
+{
+	proc_t *p = curproc;
+	struct trapframe *tf;
+	uintptr_t pc, sp;
+	volatile uint16_t *flags =
+	    (volatile uint16_t *)&cpu_core[curcpu].cpuc_dtrace_flags;
+#ifdef notyet	/* XXX signal stack */
+	uintptr_t oldcontext;
+	size_t s1, s2;
+#endif
+
+	if (*flags & CPU_DTRACE_FAULT)
+		return;
+
+	if (pcstack_limit <= 0)
+		return;
+
+	/*
+	 * If there's no user context we still need to zero the stack.
+	 */
+	if (p == NULL || (tf = curthread->td_frame) == NULL)
+		goto zero;
+
+	*pcstack++ = (uint64_t)p->p_pid;
+	pcstack_limit--;
+
+	if (pcstack_limit <= 0)
+		return;
+
+	pc = tf->srr0;
+	sp = tf->fixreg[1];
+
+#ifdef notyet /* XXX signal stack */
+	oldcontext = lwp->lwp_oldcontext;
+	s1 = sizeof (struct xframe) + 2 * sizeof (long);
+	s2 = s1 + sizeof (siginfo_t);
+#endif
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		*pcstack++ = (uint64_t)pc;
+		*fpstack++ = 0;
+		pcstack_limit--;
+		if (pcstack_limit <= 0)
+			return;
+
+		pc = dtrace_fuword64((void *)sp);
+	}
+
+	while (pc != 0) {
+		*pcstack++ = (uint64_t)pc;
+		*fpstack++ = sp;
+		pcstack_limit--;
+		if (pcstack_limit <= 0)
+			break;
+
+		if (sp == 0)
+			break;
+
+#ifdef notyet /* XXX signal stack */
+		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
+			ucontext_t *ucp = (ucontext_t *)oldcontext;
+			greg_t *gregs = ucp->uc_mcontext.gregs;
+
+			sp = dtrace_fulword(&gregs[REG_FP]);
+			pc = dtrace_fulword(&gregs[REG_PC]);
+
+			oldcontext = dtrace_fulword(&ucp->uc_link);
+		} else
+#endif /* XXX */
+		{
+			pc = dtrace_fuword32((void *)(sp + RETURN_OFFSET));
+			sp = dtrace_fuword32((void *)sp);
+		}
+
+		/*
+		 * This is totally bogus:  if we faulted, we're going to clear
+		 * the fault and break.  This is to deal with the apparently
+		 * broken Java stacks on x86.
+		 */
+		if (*flags & CPU_DTRACE_FAULT) {
+			*flags &= ~CPU_DTRACE_FAULT;
+			break;
+		}
+	}
+
+zero:
+	while (pcstack_limit-- > 0)
+		*pcstack++ = 0;
+}
+
+/*ARGSUSED*/
+uint64_t
+dtrace_getarg(int arg, int aframes)
+{
+	return (0);
+}
+
+#ifdef notyet
+{
+	int depth = 0;
+	register_t sp;
+	vm_offset_t callpc;
+	pc_t caller = (pc_t) solaris_cpu[curcpu].cpu_dtrace_caller;
+
+	if (intrpc != 0)
+		pcstack[depth++] = (pc_t) intrpc;
+
+	aframes++;
+
+	sp = dtrace_getfp();
+
+	while (depth < pcstack_limit) {
+		if (!INKERNEL((long) frame))
+			break;
+
+		callpc = *(void **)(sp + RETURN_OFFSET);
+
+		if (!INKERNEL(callpc))
+			break;
+
+		if (aframes > 0) {
+			aframes--;
+			if ((aframes == 0) && (caller != 0)) {
+				pcstack[depth++] = caller;
+			}
+		}
+		else {
+			pcstack[depth++] = callpc;
+		}
+
+		sp = *(void **)sp;
+	}
+
+	for (; depth < pcstack_limit; depth++) {
+		pcstack[depth] = 0;
+	}
+}
+#endif
+
+int
+dtrace_getstackdepth(int aframes)
+{
+	int depth = 0;
+	register_t sp;
+
+	aframes++;
+	sp = dtrace_getfp();
+	depth++;
+	for(;;) {
+		if (!INKERNEL((long) sp))
+			break;
+		if (!INKERNEL((long) *(void **)sp))
+			break;
+		depth++;
+		sp = *(uintptr_t *)sp;
+	}
+	if (depth < aframes)
+		return 0;
+	else
+		return depth - aframes;
+}
+
+ulong_t
+dtrace_getreg(struct trapframe *rp, uint_t reg)
+{
+	if (reg < 32)
+		return (rp->fixreg[reg]);
+
+	switch (reg) {
+	case 33:
+		return (rp->lr);
+	case 34:
+		return (rp->cr);
+	case 35:
+		return (rp->xer);
+	case 36:
+		return (rp->ctr);
+	case 37:
+		return (rp->srr0);
+	case 38:
+		return (rp->srr1);
+	case 39:
+		return (rp->exc);
+	default:
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
+		return (0);
+	}
+}
+
+static int
+dtrace_copycheck(uintptr_t uaddr, uintptr_t kaddr, size_t size)
+{
+	ASSERT(INKERNEL(kaddr) && kaddr + size >= kaddr);
+
+	if (uaddr + size > VM_MAXUSER_ADDRESS || uaddr + size < uaddr) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[curcpu].cpuc_dtrace_illval = uaddr;
+		return (0);
+	}
+
+	return (1);
+}
+
+void
+dtrace_copyin(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+    volatile uint16_t *flags)
+{
+	if (dtrace_copycheck(uaddr, kaddr, size))
+		dtrace_copy(uaddr, kaddr, size);
+}
+
+void
+dtrace_copyout(uintptr_t kaddr, uintptr_t uaddr, size_t size,
+    volatile uint16_t *flags)
+{
+	if (dtrace_copycheck(uaddr, kaddr, size))
+		dtrace_copy(kaddr, uaddr, size);
+}
+
+void
+dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
+    volatile uint16_t *flags)
+{
+	if (dtrace_copycheck(uaddr, kaddr, size))
+		dtrace_copystr(uaddr, kaddr, size, flags);
+}
+
+void
+dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
+    volatile uint16_t *flags)
+{
+	if (dtrace_copycheck(uaddr, kaddr, size))
+		dtrace_copystr(kaddr, uaddr, size, flags);
+}
+
+uint8_t
+dtrace_fuword8(void *uaddr)
+{
+	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword8_nocheck(uaddr));
+}
+
+uint16_t
+dtrace_fuword16(void *uaddr)
+{
+	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword16_nocheck(uaddr));
+}
+
+uint32_t
+dtrace_fuword32(void *uaddr)
+{
+	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword32_nocheck(uaddr));
+}
+
+uint64_t
+dtrace_fuword64(void *uaddr)
+{
+	if ((uintptr_t)uaddr > VM_MAXUSER_ADDRESS) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword64_nocheck(uaddr));
+}
Index: sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
===================================================================
--- sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	(revision 0)
+++ sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	(working copy)
@@ -0,0 +1,269 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD: head/sys/cddl/dev/dtrace/mips/dtrace_asm.S 233484 2012-03-26 01:26:33Z gonzo $
+ */
+/*
+ * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include "assym.s"
+
+#define _ASM
+
+#include <sys/cpuvar_defs.h>
+#include <sys/dtrace.h>
+
+#include <machine/asm.h>
+/*
+#include <machine/cpu.h>
+*/
+
+/*
+ * Primitives
+ */
+
+        .text
+
+/*
+void dtrace_membar_producer(void)
+*/
+ASENTRY_NOPROF(dtrace_membar_producer)
+	blr
+END(dtrace_membar_producer)
+
+/*
+void dtrace_membar_consumer(void)
+*/
+ASENTRY_NOPROF(dtrace_membar_consumer)
+	blr
+END(dtrace_membar_consumer)
+
+/*
+dtrace_icookie_t dtrace_interrupt_disable(void)
+*/
+ASENTRY_NOPROF(dtrace_interrupt_disable)
+	mfmsr	%r3
+	andi.	%r0,%r3,~PSL_EE@l
+	mtmsr	%r0
+	blr
+END(dtrace_interrupt_disable)
+
+/*
+void dtrace_interrupt_enable(dtrace_icookie_t cookie)
+*/
+ASENTRY_NOPROF(dtrace_interrupt_enable)
+	mtmsr	%r3
+	blr
+END(dtrace_interrupt_enable)
+
+/*
+uint32_t dtrace_cas32(uint32_t *target, uint32_t cmp, uint32_t new)
+*/
+ASENTRY_NOPROF(dtrace_cas32)
+1:
+	lwarx	%r0,0,%r3
+	cmpw	%r4,%r6
+	bne		2f
+	stwcx.	%r5,0,%r3
+	bne		1b
+2:	mr		%r3,%r0
+	blr
+END(dtrace_cas32)
+
+/*
+void *
+dtrace_casptr(void *target, void *cmp, void *new)
+*/
+ASENTRY_NOPROF(dtrace_casptr)
+1:
+	lwarx	%r0,0,%r3
+	cmpw	%r4,%r6
+	bne		2f
+	stwcx.	%r5,0,%r3
+	bne		1b
+2:	mr		%r3,%r0
+	blr
+END(dtrace_casptr)
+
+
+/*
+uintptr_t
+dtrace_fulword(void *addr)
+*/
+ASENTRY_NOPROF(dtrace_fulword)
+END(dtrace_fulword)
+
+/*
+uint8_t
+dtrace_fuword8_nocheck(void *addr)
+*/
+ASENTRY_NOPROF(dtrace_fuword8_nocheck)
+	lbz	%r3,0(%r3)
+	blr
+END(dtrace_fuword8_nocheck)
+
+/*
+uint16_t
+dtrace_fuword16_nocheck(void *addr)
+*/
+ASENTRY_NOPROF(dtrace_fuword16_nocheck)
+	lhz	%r3,0(%r3)
+	blr
+END(dtrace_fuword16_nocheck)
+
+/*
+uint32_t
+dtrace_fuword32_nocheck(void *addr)
+*/
+ASENTRY_NOPROF(dtrace_fuword32_nocheck)
+	lwz	%r3,0(%r3)
+	blr
+END(dtrace_fuword32_nocheck)
+
+/*
+uint64_t
+dtrace_fuword64_nocheck(void *addr)
+*/
+ASENTRY_NOPROF(dtrace_fuword64_nocheck)
+#if defined(__powerpc64__)
+	ld	%r3,0(%r3)
+#else
+	lwz	%r5,0(%r3)
+	lwz	%r4,4(%r3)
+	mr	%r3,%r5
+#endif
+	blr
+END(dtrace_fuword64_nocheck)
+
+/*
+XXX: unoptimized
+void
+dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
+*/
+ASENTRY_NOPROF(dtrace_copy)
+	addme	%r7,%r3
+	addme	%r8,%r4
+1:
+	lbzu	%r3,1(%r7)
+	stbu	%r3,1(%r8)
+	addme	%r5,%r5
+	beq		2f
+2:
+	blr
+END(dtrace_copy)
+
+/*
+void
+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
+1:
+	lbzu	%r3,1(%r7)
+	stbu	%r3,1(%r8)
+	addme	%r5,%r5
+	beq		2f
+	or		%r3,%r3,%r3
+	beq		2f
+	andi.	%r0,%r5,0x0fff
+	beq		2f
+	lwz		%r0,0(%r6)
+	andi.	%r0,%r0,CPU_DTRACE_BADADDR
+	beq		1b
+2:
+	blr
+END(dtrace_copystr)
+
+/*
+void dtrace_invop_init(void)
+*/
+ASENTRY_NOPROF(dtrace_invop_init)
+	/* XXX: impement it properly -- implement dtrace_invop_start */
+	li		%r0,0
+	li		%r3,dtrace_invop_jump_addr@l
+	addis	%r3,%r3,dtrace_invop_jump_addr@ha
+	stw		%r0,0(%r3)
+	blr
+END(dtrace_invop_init)
+
+/*
+void dtrace_invop_uninit(void)
+*/
+ASENTRY_NOPROF(dtrace_invop_uninit)
+	li		%r0,0
+	li		%r3,dtrace_invop_jump_addr@l
+	addis	%r3,%r3,dtrace_invop_jump_addr@ha
+	stw		%r0,0(%r3)
+	blr
+END(dtrace_invop_uninit)
+
+/*
+ * The panic() and cmn_err() functions invoke vpanic() as a common entry point
+ * into the panic code implemented in panicsys().  vpanic() is responsible
+ * for passing through the format string and arguments, and constructing a
+ * regs structure on the stack into which it saves the current register
+ * values.  If we are not dying due to a fatal trap, these registers will
+ * then be preserved in panicbuf as the current processor state.  Before
+ * invoking panicsys(), vpanic() activates the first panic trigger (see
+ * common/os/panic.c) and switches to the panic_stack if successful.  Note that
+ * DTrace takes a slightly different panic path if it must panic from probe
+ * context.  Instead of calling panic, it calls into dtrace_vpanic(), which
+ * sets up the initial stack as vpanic does, calls dtrace_panic_trigger(), and
+ * branches back into vpanic().
+ */
+
+/*
+void
+vpanic(const char *format, va_list alist)
+*/
+ASENTRY_NOPROF(vpanic)				/* Initial stack layout: */
+	
+vpanic_common:
+	blr
+END(vpanic)
+
+
+
+/*
+void
+dtrace_vpanic(const char *format, va_list alist)
+*/
+ASENTRY_NOPROF(dtrace_vpanic)			/* Initial stack layout: */
+
+#if 0
+	bl	dtrace_panic_trigger	/* %eax = dtrace_panic_trigger() */
+#endif
+	b	vpanic_common
+END(dtrace_vpanic)
+
+/*
+uintptr_t
+dtrace_caller(int aframes)
+*/
+ASENTRY_NOPROF(dtrace_caller)
+	li	%r3, -1
+	blr
+END(dtrace_caller)
+
Index: sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
===================================================================
--- sys/cddl/dev/dtrace/powerpc/dtrace_subr.c	(revision 0)
+++ sys/cddl/dev/dtrace/powerpc/dtrace_subr.c	(working copy)
@@ -0,0 +1,201 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License, Version 1.0 only
+ * (the "License").  You may not use this file except in compliance
+ * with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ *
+ * $FreeBSD: head/sys/cddl/dev/dtrace/mips/dtrace_subr.c 233409 2012-03-24 05:14:37Z gonzo $
+ *
+ */
+/*
+ * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
+ * Use is subject to license terms.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD: head/sys/cddl/dev/dtrace/mips/dtrace_subr.c 233409 2012-03-24 05:14:37Z gonzo $");
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/types.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/kmem.h>
+#include <sys/smp.h>
+#include <sys/dtrace_impl.h>
+#include <sys/dtrace_bsd.h>
+#include <machine/clock.h>
+#include <machine/frame.h>
+#include <machine/trap.h>
+#include <vm/pmap.h>
+
+#define	DELAYBRANCH(x)	((int)(x) < 0)
+		
+extern uintptr_t 	dtrace_in_probe_addr;
+extern int		dtrace_in_probe;
+extern dtrace_id_t	dtrace_probeid_error;
+
+int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
+
+typedef struct dtrace_invop_hdlr {
+	int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
+	struct dtrace_invop_hdlr *dtih_next;
+} dtrace_invop_hdlr_t;
+
+dtrace_invop_hdlr_t *dtrace_invop_hdlr;
+
+int
+dtrace_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
+{
+	dtrace_invop_hdlr_t *hdlr;
+	int rval;
+
+	for (hdlr = dtrace_invop_hdlr; hdlr != NULL; hdlr = hdlr->dtih_next)
+		if ((rval = hdlr->dtih_func(addr, stack, eax)) != 0)
+			return (rval);
+
+	return (0);
+}
+
+
+/*ARGSUSED*/
+void
+dtrace_toxic_ranges(void (*func)(uintptr_t base, uintptr_t limit))
+{
+	/*
+	 * No toxic regions?
+	 */
+}
+
+void
+dtrace_xcall(processorid_t cpu, dtrace_xcall_t func, void *arg)
+{
+	cpuset_t cpus;
+
+	if (cpu == DTRACE_CPUALL)
+		cpus = all_cpus;
+	else
+		CPU_SETOF(cpu, &cpus);
+
+	smp_rendezvous_cpus(cpus, smp_no_rendevous_barrier, func,
+	    smp_no_rendevous_barrier, arg);
+}
+
+static void
+dtrace_sync_func(void)
+{
+}
+
+void
+dtrace_sync(void)
+{
+        dtrace_xcall(DTRACE_CPUALL, (dtrace_xcall_t)dtrace_sync_func, NULL);
+}
+
+/*
+ * DTrace needs a high resolution time function which can
+ * be called from a probe context and guaranteed not to have
+ * instrumented with probes itself.
+ *
+ * Returns nanoseconds since boot.
+ */
+uint64_t
+dtrace_gethrtime()
+{
+	struct      timespec curtime;
+
+	nanouptime(&curtime);
+
+	return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
+
+}
+
+uint64_t
+dtrace_gethrestime(void)
+{
+	struct      timespec curtime;
+
+	getnanotime(&curtime);
+
+	return (curtime.tv_sec * 1000000000UL + curtime.tv_nsec);
+}
+
+/* Function to handle DTrace traps during probes. See amd64/amd64/trap.c */
+int
+dtrace_trap(struct trapframe *frame, u_int type)
+{
+	/*
+	 * A trap can occur while DTrace executes a probe. Before
+	 * executing the probe, DTrace blocks re-scheduling and sets
+	 * a flag in it's per-cpu flags to indicate that it doesn't
+	 * want to fault. On returning from the probe, the no-fault
+	 * flag is cleared and finally re-scheduling is enabled.
+	 *
+	 * Check if DTrace has enabled 'no-fault' mode:
+	 *
+	 */
+	if ((cpu_core[curcpu].cpuc_dtrace_flags & CPU_DTRACE_NOFAULT) != 0) {
+		/*
+		 * There are only a couple of trap types that are expected.
+		 * All the rest will be handled in the usual way.
+		 */
+		switch (type) {
+		/* Page fault. */
+		case EXC_DSI:
+		case EXC_DSE:
+			/* Flag a bad address. */
+			cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
+			cpu_core[curcpu].cpuc_dtrace_illval = frame->cpu.aim.dar;
+
+			/*
+			 * Offset the instruction pointer to the instruction
+			 * following the one causing the fault.
+			 */
+			frame->srr0 += sizeof(int);
+			return (1);
+		case EXC_ISI:
+		case EXC_ISE:
+			/* Flag a bad address. */
+			cpu_core[curcpu].cpuc_dtrace_flags |= CPU_DTRACE_BADADDR;
+			cpu_core[curcpu].cpuc_dtrace_illval = frame->srr0;
+
+			/*
+			 * Offset the instruction pointer to the instruction
+			 * following the one causing the fault.
+			 */
+			frame->srr0 += sizeof(int);
+			return (1);
+		default:
+			/* Handle all other traps in the usual way. */
+			break;
+		}
+	}
+
+	/* Handle the trap in the usual way. */
+	return (0);
+}
+
+void
+dtrace_probe_error(dtrace_state_t *state, dtrace_epid_t epid, int which,
+    int fault, int fltoffs, uintptr_t illval)
+{
+
+	dtrace_probe(dtrace_probeid_error, (uint64_t)(uintptr_t)state,
+	    (uintptr_t)epid,
+	    (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
+}
Index: sys/modules/Makefile
===================================================================
--- sys/modules/Makefile	(revision 241450)
+++ sys/modules/Makefile	(working copy)
@@ -803,6 +803,9 @@
 _pccard=	pccard
 _smbfs=		smbfs
 _sound=		sound
+_cyclic=	cyclic
+_dtrace=	dtrace
+_opensolaris=	opensolaris
 .endif
 
 .if ${MACHINE_ARCH} == "powerpc64"
Index: sys/powerpc/aim/locore32.S
===================================================================
--- sys/powerpc/aim/locore32.S	(revision 241450)
+++ sys/powerpc/aim/locore32.S	(working copy)
@@ -65,6 +65,8 @@
 #include <machine/spr.h>
 #include <machine/asm.h>
 
+#include "opt_kdtrace.h"
+
 /* Locate the per-CPU data structure */
 #define GET_CPUINFO(r)  \
         mfsprg0  r
Index: lib/Makefile
===================================================================
--- lib/Makefile	(revision 241450)
+++ lib/Makefile	(working copy)
@@ -209,6 +209,8 @@
 .endif
 
 .if ${MACHINE_CPUARCH} == "powerpc"
+_libproc=	libproc
+_librtld_db=	librtld_db
 _libsmb=	libsmb
 .endif
 
Index: lib/libproc/proc_regs.c
===================================================================
--- lib/libproc/proc_regs.c	(revision 241450)
+++ lib/libproc/proc_regs.c	(working copy)
@@ -60,6 +60,8 @@
 		*regvalue = regs.r_eip;
 #elif defined(__mips__)
 		*regvalue = regs.r_regs[PC];
+#elif defined(__powerpc__)
+		*regvalue = regs.pc;
 #endif
 		break;
 	case REG_SP:
@@ -69,6 +71,8 @@
 		*regvalue = regs.r_esp;
 #elif defined(__mips__)
 		*regvalue = regs.r_regs[SP];
+#elif defined(__powerpc__)
+		*regvalue = regs.fixreg[1];
 #endif
 		break;
 	default:
@@ -99,6 +103,8 @@
 		regs.r_eip = regvalue;
 #elif defined(__mips__)
 		regs.r_regs[PC] = regvalue;
+#elif defined(__powerpc__)
+		regs.pc = regvalue;
 #endif
 		break;
 	case REG_SP:
@@ -108,6 +114,8 @@
 		regs.r_esp = regvalue;
 #elif defined(__mips__)
 		regs.r_regs[PC] = regvalue;
+#elif defined(__powerpc__)
+		regs.fixreg[1] = regvalue;
 #endif
 		break;
 	default:
Index: lib/libproc/proc_bkpt.c
===================================================================
--- lib/libproc/proc_bkpt.c	(revision 241450)
+++ lib/libproc/proc_bkpt.c	(working copy)
@@ -47,6 +47,9 @@
 #elif defined(__mips__)
 #define BREAKPOINT_INSTR	0xd	/* break */
 #define	BREAKPOINT_INSTR_SZ	4
+#elif defined(__powerpc__)
+#define BREAKPOINT_INSTR	0x7fe00008	/* trap */
+#define BREAKPOINT_INSTR_SZ 4
 #else
 #error "Add support for your architecture"
 #endif

--MP_/kq=KQQOav+pc79+hUczvDBG--



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