svn commit: r248463 - in user/attilio/vmcontention: contrib/binutils/gas/config lib/libc/stdlib sys/cddl/contrib/opensolaris/uts/common/sys sys/cddl/dev/dtrace/powerpc sys/cddl/dev/fbt sys/dev/ath ...

Attilio Rao attilio at FreeBSD.org
Mon Mar 18 11:06:35 UTC 2013


Author: attilio
Date: Mon Mar 18 09:45:10 2013
New Revision: 248463
URL: http://svnweb.freebsd.org/changeset/base/248463

Log:
  MFC

Added:
  user/attilio/vmcontention/sys/cddl/dev/fbt/fbt_powerpc.c
     - copied unchanged from r248462, head/sys/cddl/dev/fbt/fbt_powerpc.c
Modified:
  user/attilio/vmcontention/contrib/binutils/gas/config/tc-arm.c
  user/attilio/vmcontention/lib/libc/stdlib/realpath.3
  user/attilio/vmcontention/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
  user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
  user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
  user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
  user/attilio/vmcontention/sys/dev/ath/if_ath_rx_edma.c
  user/attilio/vmcontention/sys/dev/ath/if_ath_sysctl.c
  user/attilio/vmcontention/sys/dev/sis/if_sis.c
  user/attilio/vmcontention/sys/dev/sis/if_sisreg.h
  user/attilio/vmcontention/sys/dev/usb/usbdevs
  user/attilio/vmcontention/sys/dev/usb/wlan/if_run.c
  user/attilio/vmcontention/sys/modules/dtrace/Makefile
  user/attilio/vmcontention/sys/modules/dtrace/dtraceall/dtraceall.c
  user/attilio/vmcontention/sys/modules/dtrace/fbt/Makefile
  user/attilio/vmcontention/sys/powerpc/aim/trap.c
  user/attilio/vmcontention/sys/powerpc/aim/trap_subr32.S
  user/attilio/vmcontention/sys/powerpc/aim/trap_subr64.S
Directory Properties:
  user/attilio/vmcontention/   (props changed)
  user/attilio/vmcontention/contrib/binutils/   (props changed)
  user/attilio/vmcontention/lib/libc/   (props changed)
  user/attilio/vmcontention/sys/   (props changed)
  user/attilio/vmcontention/sys/cddl/contrib/opensolaris/   (props changed)
  user/attilio/vmcontention/sys/conf/   (props changed)

Modified: user/attilio/vmcontention/contrib/binutils/gas/config/tc-arm.c
==============================================================================
--- user/attilio/vmcontention/contrib/binutils/gas/config/tc-arm.c	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/contrib/binutils/gas/config/tc-arm.c	Mon Mar 18 09:45:10 2013	(r248463)
@@ -651,6 +651,7 @@ struct asm_opcode
 
 #define BAD_ARGS	_("bad arguments to instruction")
 #define BAD_PC		_("r15 not allowed here")
+#define BAD_SP		_("r13 not allowed here")
 #define BAD_COND	_("instruction cannot be conditional")
 #define BAD_OVERLAP	_("registers may not be the same")
 #define BAD_HIREG	_("lo register required")
@@ -659,6 +660,7 @@ struct asm_opcode
 #define BAD_BRANCH	_("branch must be last instruction in IT block")
 #define BAD_NOT_IT	_("instruction not allowed in IT block")
 #define BAD_FPU		_("selected FPU does not support instruction")
+#define BAD_VMRS	_("APSR_nzcv may only be used with fpscr")
 
 static struct hash_control *arm_ops_hsh;
 static struct hash_control *arm_cond_hsh;
@@ -5164,10 +5166,6 @@ parse_neon_mov (char **str, int *which_o
              Case 10: VMOV.F32 <Sd>, #<imm>
              Case 11: VMOV.F64 <Dd>, #<imm>  */
         inst.operands[i].immisfloat = 1;
-      else if (parse_big_immediate (&ptr, i) == SUCCESS)
-          /* Case 2: VMOV<c><q>.<dt> <Qd>, #<imm>
-             Case 3: VMOV<c><q>.<dt> <Dd>, #<imm>  */
-        ;
       else if ((val = arm_typed_reg_parse (&ptr, REG_TYPE_NSDQ, &rtype,
                                            &optype)) != FAIL)
         {
@@ -5207,6 +5205,10 @@ parse_neon_mov (char **str, int *which_o
               inst.operands[i++].present = 1;
             }
         }
+      else if (parse_big_immediate (&ptr, i) == SUCCESS)
+          /* Case 2: VMOV<c><q>.<dt> <Qd>, #<imm>
+             Case 3: VMOV<c><q>.<dt> <Dd>, #<imm>  */
+        ;
       else
         {
           first_error (_("expected <Rm> or <Dm> or <Qm> operand"));
@@ -7095,6 +7097,68 @@ do_vfp_nsyn_msr (void)
   return SUCCESS;
 }
 
+static int
+do_vfp_vmrs (void)
+{
+  int rt;
+
+  /* The destination register can be r0-r14 or APSR_nzcv */
+  if (inst.operands[0].reg > 14)
+    {
+      inst.error = BAD_PC;
+      return FAIL;
+    }
+
+  /* If the destination is r13 and not in ARM mode then unprefictable */
+  if (thumb_mode && inst.operands[0].reg == REG_SP)
+    {
+      inst.error = BAD_SP;
+      return FAIL;
+    }
+
+  /* If the destination is APSR_nzcv */
+  if (inst.operands[0].isvec && inst.operands[1].reg != 1)
+    {
+      inst.error = BAD_VMRS;
+      return FAIL;
+    }
+
+  if (inst.operands[0].isvec)
+    rt = 15;
+  else
+    rt = inst.operands[0].reg;
+
+  /* Or in the registers to use */
+  inst.instruction |= rt << 12;
+  inst.instruction |= inst.operands[1].reg << 16;
+
+  return SUCCESS;
+}
+
+static int
+do_vfp_vmsr (void)
+{
+  /* The destination register can be r0-r14 or APSR_nzcv */
+  if (inst.operands[1].reg > 14)
+    {
+      inst.error = BAD_PC;
+      return FAIL;
+    }
+
+  /* If the destination is r13 and not in ARM mode then unprefictable */
+  if (thumb_mode && inst.operands[0].reg == REG_SP)
+    {
+      inst.error = BAD_SP;
+      return FAIL;
+    }
+
+  /* Or in the registers to use */
+  inst.instruction |= inst.operands[1].reg << 12;
+  inst.instruction |= inst.operands[0].reg << 16;
+
+  return SUCCESS;
+}
+
 static void
 do_mrs (void)
 {
@@ -15726,6 +15790,8 @@ static const struct asm_opcode insns[] =
  cCE(ftouizs,	ebc0ac0, 2, (RVS, RVS),	      vfp_sp_monadic),
  cCE(fmrx,	ef00a10, 2, (RR, RVC),	      rd_rn),
  cCE(fmxr,	ee00a10, 2, (RVC, RR),	      rn_rd),
+ cCE(vmrs,	ef00a10, 2, (APSR_RR, RVC),   vfp_vmrs),
+ cCE(vmsr,	ee00a10, 2, (RVC, RR),        vfp_vmsr),
 
   /* Memory operations.	 */
  cCE(flds,	d100a00, 2, (RVS, ADDRGLDC),  vfp_sp_ldst),

Modified: user/attilio/vmcontention/lib/libc/stdlib/realpath.3
==============================================================================
--- user/attilio/vmcontention/lib/libc/stdlib/realpath.3	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/lib/libc/stdlib/realpath.3	Mon Mar 18 09:45:10 2013	(r248463)
@@ -42,7 +42,7 @@
 .Sh SYNOPSIS
 .In stdlib.h
 .Ft "char *"
-.Fn realpath "const char *pathname" "char *resolved_path"
+.Fn realpath "const char * restrict pathname" "char * restrict resolved_path"
 .Sh DESCRIPTION
 The
 .Fn realpath

Modified: user/attilio/vmcontention/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h
==============================================================================
--- user/attilio/vmcontention/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/sys/cddl/contrib/opensolaris/uts/common/sys/dtrace.h	Mon Mar 18 09:45:10 2013	(r248463)
@@ -2313,10 +2313,10 @@ extern int dtrace_mach_aframes(void);
 #if defined(__i386) || defined(__amd64)
 extern int dtrace_instr_size(uchar_t *instr);
 extern int dtrace_instr_size_isa(uchar_t *, model_t, int *);
-extern void dtrace_invop_add(int (*)(uintptr_t, uintptr_t *, uintptr_t));
-extern void dtrace_invop_remove(int (*)(uintptr_t, uintptr_t *, uintptr_t));
 extern void dtrace_invop_callsite(void);
 #endif
+extern void dtrace_invop_add(int (*)(uintptr_t, uintptr_t *, uintptr_t));
+extern void dtrace_invop_remove(int (*)(uintptr_t, uintptr_t *, uintptr_t));
 
 #ifdef __sparc
 extern int dtrace_blksuword32(uintptr_t, uint32_t *, int);
@@ -2349,6 +2349,15 @@ extern void dtrace_helpers_destroy(proc_
 #define	DTRACE_INVOP_NOP		4
 #define	DTRACE_INVOP_RET		5
 
+#elif defined(__powerpc__)
+
+#define DTRACE_INVOP_RET	1
+#define DTRACE_INVOP_BCTR	2
+#define DTRACE_INVOP_BLR	3
+#define DTRACE_INVOP_JUMP	4
+#define DTRACE_INVOP_MFLR_R0	5
+#define DTRACE_INVOP_NOP	6
+
 #endif
 
 #ifdef	__cplusplus

Modified: user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S
==============================================================================
--- user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_asm.S	Mon Mar 18 09:45:10 2013	(r248463)
@@ -85,10 +85,10 @@ ASENTRY_NOPROF(dtrace_cas32)
 1:
 	lwarx	%r0,0,%r3
 	cmpw	%r4,%r0
-	bne		2f
+	bne	2f
 	stwcx.	%r5,0,%r3
-	bne		1b
-2:	mr		%r3,%r0
+	bne	1b
+2:	mr	%r3,%r0
 	blr
 END(dtrace_cas32)
 
@@ -100,22 +100,15 @@ ASENTRY_NOPROF(dtrace_casptr)
 1:
 	lwarx	%r0,0,%r3
 	cmpw	%r4,%r0
-	bne		2f
+	bne	2f
 	stwcx.	%r5,0,%r3
-	bne		1b
-2:	mr		%r3,%r0
+	bne	1b
+2:	mr	%r3,%r0
 	blr
 END(dtrace_casptr)
 
 
 /*
-uintptr_t
-dtrace_fulword(void *addr)
-*/
-ASENTRY_NOPROF(dtrace_fulword)
-END(dtrace_fulword)
-
-/*
 XXX: unoptimized
 void
 dtrace_copy(uintptr_t src, uintptr_t dest, size_t size)
@@ -127,7 +120,7 @@ ASENTRY_NOPROF(dtrace_copy)
 	lbzu	%r3,1(%r7)
 	stbu	%r3,1(%r8)
 	addme	%r5,%r5
-	beq		2f
+	beq	2f
 2:
 	blr
 END(dtrace_copy)
@@ -144,42 +137,19 @@ ASENTRY_NOPROF(dtrace_copystr)
 	lbzu	%r3,1(%r7)
 	stbu	%r3,1(%r8)
 	addme	%r5,%r5
-	beq		2f
-	or		%r3,%r3,%r3
-	beq		2f
+	beq	2f
+	or	%r3,%r3,%r3
+	beq	2f
 	andi.	%r0,%r5,0x0fff
-	beq		2f
-	lwz		%r0,0(%r6)
+	beq	2f
+	lwz	%r0,0(%r6)
 	andi.	%r0,%r0,CPU_DTRACE_BADADDR
-	beq		1b
+	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 at l
-	addis	%r3,%r3,dtrace_invop_jump_addr at 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 at l
-	addis	%r3,%r3,dtrace_invop_jump_addr at 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

Modified: user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c
==============================================================================
--- user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_isa.c	Mon Mar 18 09:45:10 2013	(r248463)
@@ -567,3 +567,17 @@ dtrace_fuword64(void *uaddr)
 	}
 	return ret;
 }
+
+uintptr_t
+dtrace_fulword(void *uaddr)
+{
+	uintptr_t ret = 0;
+
+	if (dtrace_copycheck((uintptr_t)uaddr, (uintptr_t)&ret, sizeof(ret))) {
+		if (copyin((const void *)uaddr, (void *)&ret, sizeof(ret))) {
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+			cpu_core[curcpu].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		}
+	}
+	return ret;
+}

Modified: user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c
==============================================================================
--- user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c	Mon Mar 18 09:39:51 2013	(r248462)
+++ user/attilio/vmcontention/sys/cddl/dev/dtrace/powerpc/dtrace_subr.c	Mon Mar 18 09:45:10 2013	(r248463)
@@ -49,8 +49,11 @@ __FBSDID("$FreeBSD$");
 extern uintptr_t 	dtrace_in_probe_addr;
 extern int		dtrace_in_probe;
 extern dtrace_id_t	dtrace_probeid_error;
+extern int (*dtrace_invop_jump_addr)(struct trapframe *);
 
 int dtrace_invop(uintptr_t, uintptr_t *, uintptr_t);
+void dtrace_invop_init(void);
+void dtrace_invop_uninit(void);
 
 typedef struct dtrace_invop_hdlr {
 	int (*dtih_func)(uintptr_t, uintptr_t *, uintptr_t);
@@ -72,6 +75,44 @@ dtrace_invop(uintptr_t addr, uintptr_t *
 	return (0);
 }
 
+void
+dtrace_invop_add(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
+{
+	dtrace_invop_hdlr_t *hdlr;
+
+	hdlr = kmem_alloc(sizeof (dtrace_invop_hdlr_t), KM_SLEEP);
+	hdlr->dtih_func = func;
+	hdlr->dtih_next = dtrace_invop_hdlr;
+	dtrace_invop_hdlr = hdlr;
+}
+
+void
+dtrace_invop_remove(int (*func)(uintptr_t, uintptr_t *, uintptr_t))
+{
+	dtrace_invop_hdlr_t *hdlr = dtrace_invop_hdlr, *prev = NULL;
+
+	for (;;) {
+		if (hdlr == NULL)
+			panic("attempt to remove non-existent invop handler");
+
+		if (hdlr->dtih_func == func)
+			break;
+
+		prev = hdlr;
+		hdlr = hdlr->dtih_next;
+	}
+
+	if (prev == NULL) {
+		ASSERT(dtrace_invop_hdlr == hdlr);
+		dtrace_invop_hdlr = hdlr->dtih_next;
+	} else {
+		ASSERT(dtrace_invop_hdlr != hdlr);
+		prev->dtih_next = hdlr->dtih_next;
+	}
+
+	kmem_free(hdlr, 0);
+}
+
 
 /*ARGSUSED*/
 void
@@ -199,3 +240,36 @@ dtrace_probe_error(dtrace_state_t *state
 	    (uintptr_t)epid,
 	    (uintptr_t)which, (uintptr_t)fault, (uintptr_t)fltoffs);
 }
+
+static int
+dtrace_invop_start(struct trapframe *frame)
+{
+	switch (dtrace_invop(frame->srr0, (uintptr_t *)frame, frame->fixreg[3])) {
+	case DTRACE_INVOP_JUMP:
+		break;
+	case DTRACE_INVOP_BCTR:
+		frame->srr0 = frame->ctr;
+		break;
+	case DTRACE_INVOP_BLR:
+		frame->srr0 = frame->lr;
+		break;
+	case DTRACE_INVOP_MFLR_R0:
+		frame->fixreg[0] = frame->lr ;
+		break;
+	default:
+		return (-1);
+		break;
+	}
+
+	return (0);
+}
+
+void dtrace_invop_init(void)
+{
+	dtrace_invop_jump_addr = dtrace_invop_start;
+}
+
+void dtrace_invop_uninit(void)
+{
+	dtrace_invop_jump_addr = 0;
+}

Copied: user/attilio/vmcontention/sys/cddl/dev/fbt/fbt_powerpc.c (from r248462, head/sys/cddl/dev/fbt/fbt_powerpc.c)
==============================================================================
--- /dev/null	00:00:00 1970	(empty, because file is newly added)
+++ user/attilio/vmcontention/sys/cddl/dev/fbt/fbt_powerpc.c	Mon Mar 18 09:45:10 2013	(r248463, copy of r248462, head/sys/cddl/dev/fbt/fbt_powerpc.c)
@@ -0,0 +1,1321 @@
+/*
+ * 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
+ *
+ * Portions Copyright 2006-2008 John Birrell jb at freebsd.org
+ * Portions Copyright 2013 Justin Hibbits jhibbits at freebsd.org
+ *
+ * $FreeBSD$
+ *
+ */
+
+/*
+ * Copyright 2006 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/conf.h>
+#include <sys/cpuvar.h>
+#include <sys/fcntl.h>
+#include <sys/filio.h>
+#include <sys/kdb.h>
+#include <sys/kernel.h>
+#include <sys/kmem.h>
+#include <sys/kthread.h>
+#include <sys/limits.h>
+#include <sys/linker.h>
+#include <sys/lock.h>
+#include <sys/malloc.h>
+#include <sys/module.h>
+#include <sys/mutex.h>
+#include <sys/pcpu.h>
+#include <sys/poll.h>
+#include <sys/proc.h>
+#include <sys/selinfo.h>
+#include <sys/smp.h>
+#include <sys/syscall.h>
+#include <sys/sysent.h>
+#include <sys/sysproto.h>
+#include <sys/uio.h>
+#include <sys/unistd.h>
+#include <machine/stdarg.h>
+
+#include <sys/dtrace.h>
+#include <sys/dtrace_bsd.h>
+
+static MALLOC_DEFINE(M_FBT, "fbt", "Function Boundary Tracing");
+
+#define FBT_PATCHVAL		0x7c810808
+#define FBT_MFLR_R0		0x7c0802a6
+#define FBT_MTLR_R0		0x7c0803a6
+#define FBT_BLR			0x4e800020
+#define FBT_BCTR		0x4e800030
+#define FBT_BRANCH		0x48000000
+#define FBT_BR_MASK		0x03fffffc
+#define FBT_IS_JUMP(instr)	((instr & ~FBT_BR_MASK) == FBT_BRANCH)
+
+static d_open_t	fbt_open;
+static int	fbt_unload(void);
+static void	fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
+static void	fbt_provide_module(void *, modctl_t *);
+static void	fbt_destroy(void *, dtrace_id_t, void *);
+static void	fbt_enable(void *, dtrace_id_t, void *);
+static void	fbt_disable(void *, dtrace_id_t, void *);
+static void	fbt_load(void *);
+static void	fbt_suspend(void *, dtrace_id_t, void *);
+static void	fbt_resume(void *, dtrace_id_t, void *);
+
+#define	FBT_ENTRY	"entry"
+#define	FBT_RETURN	"return"
+#define	FBT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & fbt_probetab_mask)
+#define	FBT_PROBETAB_SIZE	0x8000		/* 32k entries -- 128K total */
+
+static struct cdevsw fbt_cdevsw = {
+	.d_version	= D_VERSION,
+	.d_open		= fbt_open,
+	.d_name		= "fbt",
+};
+
+static dtrace_pattr_t fbt_attr = {
+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
+{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_COMMON },
+{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
+};
+
+static dtrace_pops_t fbt_pops = {
+	NULL,
+	fbt_provide_module,
+	fbt_enable,
+	fbt_disable,
+	fbt_suspend,
+	fbt_resume,
+	fbt_getargdesc,
+	NULL,
+	NULL,
+	fbt_destroy
+};
+
+typedef struct fbt_probe {
+	struct fbt_probe *fbtp_hashnext;
+	uint32_t	*fbtp_patchpoint;
+	int8_t		fbtp_rval;
+	uint32_t	fbtp_patchval;
+	uint32_t	fbtp_savedval;
+	uintptr_t	fbtp_roffset;
+	dtrace_id_t	fbtp_id;
+	const char	*fbtp_name;
+	modctl_t	*fbtp_ctl;
+	int		fbtp_loadcnt;
+	int		fbtp_primary;
+	int		fbtp_invop_cnt;
+	int		fbtp_symindx;
+	struct fbt_probe *fbtp_next;
+} fbt_probe_t;
+
+static struct cdev		*fbt_cdev;
+static dtrace_provider_id_t	fbt_id;
+static fbt_probe_t		**fbt_probetab;
+static int			fbt_probetab_size;
+static int			fbt_probetab_mask;
+static int			fbt_verbose = 0;
+
+static int
+fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
+{
+	struct trapframe *frame = (struct trapframe *)stack;
+	solaris_cpu_t *cpu = &solaris_cpu[curcpu];
+	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
+	uintptr_t tmp;
+
+	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
+		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
+			fbt->fbtp_invop_cnt++;
+			if (fbt->fbtp_roffset == 0) {
+				cpu->cpu_dtrace_caller = addr;
+
+				dtrace_probe(fbt->fbtp_id, frame->fixreg[3],
+				    frame->fixreg[4], frame->fixreg[5],
+				    frame->fixreg[6], frame->fixreg[7]);
+
+				cpu->cpu_dtrace_caller = 0;
+			} else {
+
+				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
+				    rval, 0, 0, 0);
+				/*
+				 * The caller doesn't have the fbt item, so
+				 * fixup tail calls here.
+				 */
+				if (fbt->fbtp_rval == DTRACE_INVOP_JUMP) {
+					frame->srr0 = (uintptr_t)fbt->fbtp_patchpoint;
+					tmp = fbt->fbtp_savedval & FBT_BR_MASK;
+					/* Sign extend. */
+					if (tmp & 0x02000000)
+						tmp |= 0xFC000000;
+					frame->srr0 += tmp;
+				}
+				cpu->cpu_dtrace_caller = 0;
+			}
+
+			return (fbt->fbtp_rval);
+		}
+	}
+
+	return (0);
+}
+
+static int
+fbt_provide_module_function(linker_file_t lf, int symindx,
+    linker_symval_t *symval, void *opaque)
+{
+	char *modname = opaque;
+	const char *name = symval->name;
+	fbt_probe_t *fbt, *retfbt;
+	int j;
+	int size;
+	u_int32_t *instr, *limit;
+
+	if (strncmp(name, "dtrace_", 7) == 0 &&
+	    strncmp(name, "dtrace_safe_", 12) != 0) {
+		/*
+		 * Anything beginning with "dtrace_" may be called
+		 * from probe context unless it explicitly indicates
+		 * that it won't be called from probe context by
+		 * using the prefix "dtrace_safe_".
+		 */
+		return (0);
+	}
+
+	if (name[0] == '_' && name[1] == '_')
+		return (0);
+
+	size = symval->size;
+
+	instr = (u_int32_t *) symval->value;
+	limit = (u_int32_t *) symval->value + symval->size;
+
+	for (; instr < limit; instr++)
+		if (*instr == FBT_MFLR_R0)
+			break;
+
+	if (*instr != FBT_MFLR_R0);
+		return (0);
+
+	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
+	fbt->fbtp_name = name;
+	fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
+	    name, FBT_ENTRY, 3, fbt);
+	fbt->fbtp_patchpoint = instr;
+	fbt->fbtp_ctl = lf;
+	fbt->fbtp_loadcnt = lf->loadcnt;
+	fbt->fbtp_savedval = *instr;
+	fbt->fbtp_patchval = FBT_PATCHVAL;
+	fbt->fbtp_rval = DTRACE_INVOP_MFLR_R0;
+	fbt->fbtp_symindx = symindx;
+
+	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
+	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
+
+	lf->fbt_nentries++;
+
+	retfbt = NULL;
+again:
+	if (instr >= limit)
+		return (0);
+
+	/*
+	 * We (desperately) want to avoid erroneously instrumenting a
+	 * jump table To determine if we're looking at a true instruction
+	 * sequence or an inline jump table that happens to contain the same
+	 * byte sequences, we resort to some heuristic sleeze:  we treat this
+	 * instruction as being contained within a pointer, and see if that
+	 * pointer points to within the body of the function.  If it does, we
+	 * refuse to instrument it.
+	 */
+	{
+		uint32_t *ptr;
+
+		ptr = *(uint32_t **)instr;
+
+		if (ptr >= (uint32_t *) symval->value && ptr < limit) {
+			instr++;
+			goto again;
+		}
+	}
+
+	if (*instr == FBT_MFLR_R0)
+		return (0);
+
+	if (*instr != FBT_MTLR_R0) {
+		instr++;
+		goto again;
+	}
+
+	instr++;
+
+	for (j = 0; j < 12 && instr < limit; j++, instr++) {
+		if ((*instr == FBT_BCTR) || (*instr == FBT_BLR) |
+		    FBT_IS_JUMP(*instr))
+			break;
+	}
+
+	if (!(*instr == FBT_BCTR || *instr == FBT_BLR || FBT_IS_JUMP(*instr)))
+		goto again;
+
+	/*
+	 * We have a winner!
+	 */
+	fbt = malloc(sizeof (fbt_probe_t), M_FBT, M_WAITOK | M_ZERO);
+	fbt->fbtp_name = name;
+
+	if (retfbt == NULL) {
+		fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
+		    name, FBT_RETURN, 3, fbt);
+	} else {
+		retfbt->fbtp_next = fbt;
+		fbt->fbtp_id = retfbt->fbtp_id;
+	}
+
+	retfbt = fbt;
+	fbt->fbtp_patchpoint = instr;
+	fbt->fbtp_ctl = lf;
+	fbt->fbtp_loadcnt = lf->loadcnt;
+	fbt->fbtp_symindx = symindx;
+
+	if (*instr == FBT_BCTR)
+		fbt->fbtp_rval = DTRACE_INVOP_BCTR;
+	else if (*instr == FBT_BLR)
+		fbt->fbtp_rval = DTRACE_INVOP_RET;
+	else
+		fbt->fbtp_rval = DTRACE_INVOP_JUMP;
+
+	fbt->fbtp_savedval = *instr;
+	fbt->fbtp_patchval = FBT_PATCHVAL;
+	fbt->fbtp_hashnext = fbt_probetab[FBT_ADDR2NDX(instr)];
+	fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
+
+	lf->fbt_nentries++;
+
+	instr += size;
+	goto again;
+}
+
+static void
+fbt_provide_module(void *arg, modctl_t *lf)
+{
+	char modname[MAXPATHLEN];
+	int i;
+	size_t len;
+
+	strlcpy(modname, lf->filename, sizeof(modname));
+	len = strlen(modname);
+	if (len > 3 && strcmp(modname + len - 3, ".ko") == 0)
+		modname[len - 3] = '\0';
+
+	/*
+	 * Employees of dtrace and their families are ineligible.  Void
+	 * where prohibited.
+	 */
+	if (strcmp(modname, "dtrace") == 0)
+		return;
+
+	/*
+	 * The cyclic timer subsystem can be built as a module and DTrace
+	 * depends on that, so it is ineligible too.
+	 */
+	if (strcmp(modname, "cyclic") == 0)
+		return;
+
+	/*
+	 * To register with DTrace, a module must list 'dtrace' as a
+	 * dependency in order for the kernel linker to resolve
+	 * symbols like dtrace_register(). All modules with such a
+	 * dependency are ineligible for FBT tracing.
+	 */
+	for (i = 0; i < lf->ndeps; i++)
+		if (strncmp(lf->deps[i]->filename, "dtrace", 6) == 0)
+			return;
+
+	if (lf->fbt_nentries) {
+		/*
+		 * This module has some FBT entries allocated; we're afraid
+		 * to screw with it.
+		 */
+		return;
+	}
+
+	/*
+	 * List the functions in the module and the symbol values.
+	 */
+	(void) linker_file_function_listall(lf, fbt_provide_module_function, modname);
+}
+
+static void
+fbt_destroy(void *arg, dtrace_id_t id, void *parg)
+{
+	fbt_probe_t *fbt = parg, *next, *hash, *last;
+	modctl_t *ctl;
+	int ndx;
+
+	do {
+		ctl = fbt->fbtp_ctl;
+
+		ctl->fbt_nentries--;
+
+		/*
+		 * Now we need to remove this probe from the fbt_probetab.
+		 */
+		ndx = FBT_ADDR2NDX(fbt->fbtp_patchpoint);
+		last = NULL;
+		hash = fbt_probetab[ndx];
+
+		while (hash != fbt) {
+			ASSERT(hash != NULL);
+			last = hash;
+			hash = hash->fbtp_hashnext;
+		}
+
+		if (last != NULL) {
+			last->fbtp_hashnext = fbt->fbtp_hashnext;
+		} else {
+			fbt_probetab[ndx] = fbt->fbtp_hashnext;
+		}
+
+		next = fbt->fbtp_next;
+		free(fbt, M_FBT);
+
+		fbt = next;
+	} while (fbt != NULL);
+}
+
+static void
+fbt_enable(void *arg, dtrace_id_t id, void *parg)
+{
+	fbt_probe_t *fbt = parg;
+	modctl_t *ctl = fbt->fbtp_ctl;
+
+	ctl->nenabled++;
+
+	/*
+	 * Now check that our modctl has the expected load count.  If it
+	 * doesn't, this module must have been unloaded and reloaded -- and
+	 * we're not going to touch it.
+	 */
+	if (ctl->loadcnt != fbt->fbtp_loadcnt) {
+		if (fbt_verbose) {
+			printf("fbt is failing for probe %s "
+			    "(module %s reloaded)",
+			    fbt->fbtp_name, ctl->filename);
+		}
+
+		return;
+	}
+
+	for (; fbt != NULL; fbt = fbt->fbtp_next) {
+		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
+	}
+}
+
+static void
+fbt_disable(void *arg, dtrace_id_t id, void *parg)
+{
+	fbt_probe_t *fbt = parg;
+	modctl_t *ctl = fbt->fbtp_ctl;
+
+	ASSERT(ctl->nenabled > 0);
+	ctl->nenabled--;
+
+	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
+		return;
+
+	for (; fbt != NULL; fbt = fbt->fbtp_next)
+		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
+}
+
+static void
+fbt_suspend(void *arg, dtrace_id_t id, void *parg)
+{
+	fbt_probe_t *fbt = parg;
+	modctl_t *ctl = fbt->fbtp_ctl;
+
+	ASSERT(ctl->nenabled > 0);
+
+	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
+		return;
+
+	for (; fbt != NULL; fbt = fbt->fbtp_next)
+		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
+}
+
+static void
+fbt_resume(void *arg, dtrace_id_t id, void *parg)
+{
+	fbt_probe_t *fbt = parg;
+	modctl_t *ctl = fbt->fbtp_ctl;
+
+	ASSERT(ctl->nenabled > 0);
+
+	if ((ctl->loadcnt != fbt->fbtp_loadcnt))
+		return;
+
+	for (; fbt != NULL; fbt = fbt->fbtp_next)
+		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
+}
+
+static int
+fbt_ctfoff_init(modctl_t *lf, linker_ctf_t *lc)
+{
+	const Elf_Sym *symp = lc->symtab;;
+	const char *name;
+	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
+	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
+	int i;
+	uint32_t *ctfoff;
+	uint32_t objtoff = hp->cth_objtoff;
+	uint32_t funcoff = hp->cth_funcoff;
+	ushort_t info;
+	ushort_t vlen;
+
+	/* Sanity check. */
+	if (hp->cth_magic != CTF_MAGIC) {
+		printf("Bad magic value in CTF data of '%s'\n",lf->pathname);
+		return (EINVAL);
+	}
+
+	if (lc->symtab == NULL) {
+		printf("No symbol table in '%s'\n",lf->pathname);
+		return (EINVAL);
+	}
+
+	if ((ctfoff = malloc(sizeof(uint32_t) * lc->nsym, M_LINKER, M_WAITOK)) == NULL)
+		return (ENOMEM);
+
+	*lc->ctfoffp = ctfoff;
+
+	for (i = 0; i < lc->nsym; i++, ctfoff++, symp++) {
+		if (symp->st_name == 0 || symp->st_shndx == SHN_UNDEF) {
+			*ctfoff = 0xffffffff;
+			continue;
+		}
+
+		if (symp->st_name < lc->strcnt)
+			name = lc->strtab + symp->st_name;
+		else
+			name = "(?)";
+
+		switch (ELF_ST_TYPE(symp->st_info)) {
+		case STT_OBJECT:
+			if (objtoff >= hp->cth_funcoff ||
+                            (symp->st_shndx == SHN_ABS && symp->st_value == 0)) {
+				*ctfoff = 0xffffffff;
+                                break;
+                        }
+
+                        *ctfoff = objtoff;
+                        objtoff += sizeof (ushort_t);
+			break;
+
+		case STT_FUNC:
+			if (funcoff >= hp->cth_typeoff) {
+				*ctfoff = 0xffffffff;
+				break;
+			}
+
+			*ctfoff = funcoff;
+
+			info = *((const ushort_t *)(ctfdata + funcoff));
+			vlen = CTF_INFO_VLEN(info);
+
+			/*
+			 * If we encounter a zero pad at the end, just skip it.
+			 * Otherwise skip over the function and its return type
+			 * (+2) and the argument list (vlen).
+			 */
+			if (CTF_INFO_KIND(info) == CTF_K_UNKNOWN && vlen == 0)
+				funcoff += sizeof (ushort_t); /* skip pad */
+			else
+				funcoff += sizeof (ushort_t) * (vlen + 2);
+			break;
+
+		default:
+			*ctfoff = 0xffffffff;
+			break;
+		}
+	}
+
+	return (0);
+}
+
+static ssize_t
+fbt_get_ctt_size(uint8_t version, const ctf_type_t *tp, ssize_t *sizep,
+    ssize_t *incrementp)
+{
+	ssize_t size, increment;
+
+	if (version > CTF_VERSION_1 &&
+	    tp->ctt_size == CTF_LSIZE_SENT) {
+		size = CTF_TYPE_LSIZE(tp);
+		increment = sizeof (ctf_type_t);
+	} else {
+		size = tp->ctt_size;
+		increment = sizeof (ctf_stype_t);
+	}
+
+	if (sizep)
+		*sizep = size;
+	if (incrementp)
+		*incrementp = increment;
+
+	return (size);
+}
+
+static int
+fbt_typoff_init(linker_ctf_t *lc)
+{
+	const ctf_header_t *hp = (const ctf_header_t *) lc->ctftab;
+	const ctf_type_t *tbuf;
+	const ctf_type_t *tend;
+	const ctf_type_t *tp;
+	const uint8_t *ctfdata = lc->ctftab + sizeof(ctf_header_t);
+	int ctf_typemax = 0;
+	uint32_t *xp;
+	ulong_t pop[CTF_K_MAX + 1] = { 0 };
+
+
+	/* Sanity check. */
+	if (hp->cth_magic != CTF_MAGIC)
+		return (EINVAL);
+
+	tbuf = (const ctf_type_t *) (ctfdata + hp->cth_typeoff);
+	tend = (const ctf_type_t *) (ctfdata + hp->cth_stroff);
+
+	int child = hp->cth_parname != 0;
+
+	/*
+	 * We make two passes through the entire type section.  In this first
+	 * pass, we count the number of each type and the total number of types.
+	 */
+	for (tp = tbuf; tp < tend; ctf_typemax++) {
+		ushort_t kind = CTF_INFO_KIND(tp->ctt_info);
+		ulong_t vlen = CTF_INFO_VLEN(tp->ctt_info);

*** DIFF OUTPUT TRUNCATED AT 1000 LINES ***


More information about the svn-src-user mailing list