changeset 10887:697142fd7740

First pass at enabling Dtrace on System z
author tide@localhost
date Thu, 08 Oct 2009 12:44:34 -0400
parents c5d0bf73c406
children 5e421a707c93
files usr/src/common/dis/s390/dis_tables.c usr/src/common/dis/s390/dis_tables.h usr/src/common/dis/s390x/dis_tables.c usr/src/common/dis/s390x/dis_tables.h usr/src/lib/libc/inc/thr_uberdata.h usr/src/lib/libdisasm/Makefile.com usr/src/lib/libdisasm/Makefile.targ usr/src/lib/libdisasm/s390/Makefile usr/src/lib/libdisasm/s390/dis_s390.c usr/src/lib/libdisasm/s390x/Makefile usr/src/lib/libdtrace/Makefile usr/src/lib/libdtrace/s390/Makefile usr/src/lib/libdtrace/s390/dt_asmsubr.s usr/src/lib/libdtrace/s390/dt_isadep.c usr/src/lib/libdtrace/s390/regs.d usr/src/lib/libdtrace/s390x/Makefile usr/src/lib/libdtrace/s390x/dt_isadep.c usr/src/lib/libdtrace/s390x/regs.d usr/src/uts/common/dtrace/profile.c usr/src/uts/common/sys/dtrace.h usr/src/uts/s390x/Makefile.rules usr/src/uts/s390x/ml/interrupt.s usr/src/uts/s390x/os/lgrpplat.c usr/src/uts/s390x/unix/Makefile usr/src/uts/zSeries/Makefile.files usr/src/uts/zSeries/Makefile.rules usr/src/uts/zSeries/Makefile.zSeries.shared usr/src/uts/zSeries/dtrace/Makefile usr/src/uts/zSeries/dtrace/dtrace_asm.s usr/src/uts/zSeries/dtrace/dtrace_isa.c usr/src/uts/zSeries/dtrace/fasttrap.conf usr/src/uts/zSeries/dtrace/fasttrap_isa.c usr/src/uts/zSeries/dtrace/fbt.c usr/src/uts/zSeries/dtrace/fbt.conf usr/src/uts/zSeries/dtrace/sdt.c usr/src/uts/zSeries/dtrace/sdt.conf usr/src/uts/zSeries/fasttrap/Makefile usr/src/uts/zSeries/fbt/Makefile usr/src/uts/zSeries/sdt/Makefile usr/src/uts/zSeries/sys/fasttrap_isa.h usr/src/uts/zSeries/sys/procfs_isa.h
diffstat 41 files changed, 3076 insertions(+), 4938 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/common/dis/s390/dis_tables.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/common/dis/s390/dis_tables.c	Thu Oct 08 12:44:34 2009 -0400
@@ -44,40 +44,6 @@
 /*                 D e f i n e s                                    */
 /*------------------------------------------------------------------*/
 
-#define IFMT_E		0
-#define IFMT_I		1
-#define IFMT_RI1	2
-#define IFMT_RI2	3
-#define IFMT_RIE	4
-#define IFMT_RIL1	5
-#define IFMT_RIL2	6
-#define IFMT_RR		7
-#define IFMT_RRE	8
-#define IFMT_RRF1	9
-#define IFMT_RRF2	10
-#define IFMT_RRF3	11
-#define IFMT_RRR	12
-#define IFMT_RS1	13
-#define IFMT_RS2	14
-#define IFMT_RSI	15
-#define IFMT_RSL	16
-#define IFMT_RSY1	17
-#define IFMT_RSY2	18
-#define IFMT_RX		19
-#define IFMT_RXE	20
-#define IFMT_RXF	21
-#define IFMT_RXY	22
-#define IFMT_S		23
-#define IFMT_SI		24
-#define IFMT_SIY	25
-#define IFMT_SS1	26
-#define IFMT_SS2	27
-#define IFMT_SS3	28
-#define IFMT_SS4	29
-#define IFMT_SS5	30
-#define IFMT_SSE	31
-#define IFMT_SSF	32
-
 #define TBL_INV		-1
 #define TBL_01		-2
 #define TBL_A5		-3
@@ -100,8 +66,6 @@
 /*                 I n c l u d e s                                  */
 /*------------------------------------------------------------------*/
 
-#pragma ident   "%Z%%M% %I%     %E% NAF"
-
 #include <sys/types.h>
 #include <sys/asm_linkage.h>
 #include "dis_tables.h"
@@ -119,278 +83,6 @@
 	int8_t	 type;		/* Entry type: IFMT_xxx, TBL_xxx    */
 } opCode_t;
 
-typedef struct _E_t {
-	uint16_t opcode;
-} __attribute__ ((packed)) E_t;
-
-typedef struct _I_t {
-	uint8_t	opcode;
-	uint8_t i1;
-} __attribute__ ((packed)) I_t;
-
-typedef struct _RI1_t {
-	uint8_t	op1;
-	uint8_t r1  : 4;
-	uint8_t op2 : 4;
-	int16_t i2;
-} __attribute__ ((packed)) RI1_t ;
-
-typedef struct _RI2_t {
-	uint8_t	op1;
-	uint8_t m1  : 4;
-	uint8_t op2 : 4;
-	int16_t i2;
-} __attribute__ ((packed)) RI2_t;
-
-typedef struct _RIE_t {
-	uint8_t	op1;
-	uint8_t r1 : 4;
-	uint8_t r3 : 4;
-	int16_t i2;
-	uint8_t xxx;
-	uint8_t op2;
-} __attribute__ ((packed)) RIE_t;
-
-typedef struct _RIL1_t {
-	uint8_t	op1;
-	uint8_t r1  : 4;
-	uint8_t op2 : 4;
-	int32_t i2;
-} __attribute__ ((packed)) RIL1_t;
-
-typedef struct _RIL2_t {
-	uint8_t	op1;
-	uint8_t m1  : 4;
-	uint8_t op2 : 4;
-	int32_t i2;
-} __attribute__ ((packed)) RIL2_t;
-
-typedef struct _RR_t {
-	uint8_t	opcode;
-	uint8_t r1 : 4;
-	uint8_t r2 : 4;
-} __attribute__ ((packed)) RR_t;
-
-typedef struct _RRE_t {
-	uint16_t opcode;
-	uint8_t  xxx;
-	uint8_t  r1 : 4;
-	uint8_t  r2 : 4;
-} __attribute__ ((packed)) RRE_t;
-
-typedef struct _RRF1_t {
-	uint16_t opcode;
-	uint8_t  r1 : 4;
-	uint8_t  xx : 4;
-	uint8_t  r3 : 4;
-	uint8_t  r2 : 4;
-} __attribute__ ((packed)) RRF1_t;
-
-typedef struct _RRF2_t {
-	uint16_t opcode;
-	uint8_t  m3 : 4;
-	uint8_t  xx : 4;
-	uint8_t  r1 : 4;
-	uint8_t  r2 : 4;
-} __attribute__ ((packed)) RRF2_t;
-
-typedef struct _RRF3_t {
-	uint16_t opcode;
-	uint8_t  r3 : 4;
-	uint8_t  m4 : 4;
-	uint8_t  r1 : 4;
-	uint8_t  r2 : 4;
-} __attribute__ ((packed)) RRF3_t;
-
-typedef struct _RRR_t {
-	uint16_t opcode;
-	uint8_t  r3 : 4;
-	uint8_t  xx : 4;
-	uint8_t  r1 : 4;
-	uint8_t  r2 : 4;
-} __attribute__ ((packed)) RRR_t;
-
-typedef struct _RS1_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  r3 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) RS1_t;
-
-typedef struct _RS2_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  m3 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) RS2_t;
-
-typedef struct _RSI_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  r3 : 4;
-	int16_t  i2;
-} __attribute__ ((packed)) RSI_t;
-
-typedef struct _RSL_t {
-	uint8_t  op1;
-	uint8_t  l1 : 4;
-	uint8_t  xx : 4;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint8_t  zz;
-	uint8_t  op2;
-} __attribute__ ((packed)) RSL_t;
-
-typedef struct _RSY1_t {
-	uint8_t  op1;
-	uint8_t  r1 : 4;
-	uint8_t  r3 : 4;
-	uint16_t b2 : 4;
-	uint16_t dl : 12;
-	uint8_t  dh;
-	uint8_t  op2;
-} __attribute__ ((packed)) RSY1_t;
-
-typedef struct _RSY2_t {
-	uint8_t  op1;
-	uint8_t  r1 : 4;
-	uint8_t  m3 : 4;
-	uint16_t b2 : 4;
-	uint16_t dl : 12;
-	uint8_t  dh;
-	uint8_t  op2;
-} __attribute__ ((packed)) RSY2_t;
-
-typedef struct _RX_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  x2 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) RX_t;
-
-typedef struct _RXE_t {
-	uint8_t  op1;
-	uint8_t  r1 : 4;
-	uint8_t  x2 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-	uint8_t  xx;
-	uint8_t  op2;
-} __attribute__ ((packed)) RXE_t;
-
-typedef struct _RXF_t {
-	uint8_t  op1;
-	uint8_t  r3 : 4;
-	uint8_t  x2 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-	uint8_t  r1 : 4;
-	uint8_t  xx : 4;
-	uint8_t  op2;
-} __attribute__ ((packed)) RXF_t;
-
-typedef struct _RXY_t {
-	uint8_t  op1;
-	uint8_t  r1 : 4;
-	uint8_t  x2 : 4;
-	uint16_t b2 : 4;
-	uint16_t dl : 12;
-	uint8_t  dh;
-	uint8_t  op2;
-} __attribute__ ((packed)) RXY_t;
-
-typedef struct _S_t {
-	uint16_t opcode;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) S_t;
-
-typedef struct _SI_t {
-	uint8_t  opcode;
-	uint8_t  i2;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-} __attribute__ ((packed)) SI_t;
-
-typedef struct _SIY_t {
-	uint8_t  opcode;
-	uint8_t  i2;
-	uint16_t b1 : 4;
-	uint16_t dl : 12;
-	uint8_t  dh;
-	uint8_t  op2;
-} __attribute__ ((packed)) SIY_t;
-
-typedef struct _SS1_t {
-	uint8_t  opcode;
-	uint8_t  l;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) SS1_t;
-
-typedef struct _SS2_t {
-	uint8_t  opcode;
-	uint8_t  l1 : 4;
-	uint8_t  l2 : 4;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) SS2_t;
-
-typedef struct _SS3_t {
-	uint8_t  opcode;
-	uint8_t  l1 : 4;
-	uint8_t  i3 : 4;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) SS3_t;
-
-typedef struct _SS4_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  r3 : 4;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) SS4_t;
-
-typedef struct _SS5_t {
-	uint8_t  opcode;
-	uint8_t  r1 : 4;
-	uint8_t  r3 : 4;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-	uint16_t b4 : 4;
-	uint16_t d4 : 12;
-} __attribute__ ((packed)) SS5_t;
-
-typedef struct _SSE_t {
-	uint16_t opcode;
-	uint16_t b1 : 4;
-	uint16_t d1 : 12;
-	uint16_t b2 : 4;
-	uint16_t d2 : 12;
-} __attribute__ ((packed)) SSE_t;
-
-typedef struct _SSF_t {
-	uint8_t  op1;
-	uint8_t  r3  : 4;
-	uint8_t  op2 : 4;
-	uint16_t b1  : 4;
-	uint16_t d1  : 12;
-	uint16_t b2  : 4;
-	uint16_t d2  : 12;
-} __attribute__ ((packed)) SSF_t;
-
 /*========================= End of Typedefs ========================*/
 
 /*------------------------------------------------------------------*/
@@ -543,8 +235,8 @@
 	{0x80, "SET SYSTEM MASK", "SSM", IFMT_S},
 	{0x82, "LOAD PSW", "LPSW", IFMT_S},
 	{0x83, "DIAGNOSE", "DIAG", IFMT_RSI},
-	{0x84, "BRANCH RELATIVE ON INDEX HIGH (32)", "BRXH", IFMT_RSI},
-	{0x85, "BRANCH RELATIVE ON INDEX LOW OR EQ. (32)", "BRXLE", IFMT_RSI},
+	{0x84, "BRANCH RELATIVE ON INDEX HIGH (32)", "BRXH", IFMT_RSI|IFMT_PCREL},
+	{0x85, "BRANCH RELATIVE ON INDEX LOW OR EQ. (32)", "BRXLE", IFMT_RSI|IFMT_RSI},
 	{0x86, "BRANCH ON INDEX HIGH (32)", "BXH", IFMT_RS1},
 	{0x87, "BRANCH ON INDEX LOW OR EQUAL (32)", "BXLE", IFMT_RS1},
 	{0x88, "SHIFT RIGHT SINGLE LOGICAL (32)", "SRL", IFMT_RS1},
@@ -683,7 +375,7 @@
 	{0x00, "", "", TBL_INV}
 };
 
-opCode_t opc_a5[] = {
+static opCode_t opc_a5[] = {
 	{0x00, "INSERT IMMEDIATE (high high)", "IIHH", IFMT_RI1},
 	{0x01, "INSERT IMMEDIATE (high low)", "IIHL", IFMT_RI1},
 	{0x02, "INSERT IMMEDIATE (low high)", "IILH", IFMT_RI1},
@@ -708,10 +400,10 @@
 	{0x01, "TEST UNDER MASK (low low)", "TMLL", IFMT_RI1},
 	{0x02, "TEST UNDER MASK (high high)", "TMHH", IFMT_RI1},
 	{0x03, "TEST UNDER MASK (high low)", "TMHL", IFMT_RI1},
-	{0x04, "BRANCH RELATIVE ON CONDITION", "BRC", IFMT_RI2},
-	{0x05, "BRANCH RELATIVE AND SAVE", "BRAS", IFMT_RI1},
-	{0x06, "BRANCH RELATIVE ON COUNT (32)", "BRCT", IFMT_RI1},
-	{0x07, "BRANCH RELATIVE ON COUNT (64)", "BRCTG", IFMT_RI1},
+	{0x04, "BRANCH RELATIVE ON CONDITION", "BRC", IFMT_RI2|IFMT_PCREL},
+	{0x05, "BRANCH RELATIVE AND SAVE", "BRAS", IFMT_RI1|IFMT_PCREL},
+	{0x06, "BRANCH RELATIVE ON COUNT (32)", "BRCT", IFMT_RI1|IFMT_PCREL},
+	{0x07, "BRANCH RELATIVE ON COUNT (64)", "BRCTG", IFMT_RI1|IFMT_PCREL},
 	{0x08, "LOAD HALFWORD IMMEDIATE (32)", "LHI", IFMT_RI1},
 	{0x09, "LOAD HALFWORD IMMEDIATE (64)", "LGHI", IFMT_RI1},
 	{0x0A, "ADD HALFWORD IMMEDIATE (32)", "AHI", IFMT_RI1},
@@ -1320,10 +1012,10 @@
 };
 
 static opCode_t opc_c0[] = {
-	{0x00, "LOAD ADDRESS RELATIVE LONG", "LARL", IFMT_RIL1},
-	{0x01, "LOAD IMMEDIATE (64 32)", "LGFI", IFMT_RIL1},
-	{0x04, "BRANCH RELATIVE ON CONDITION LONG", "BRCL", IFMT_RIL2},
-	{0x05, "BRANCH RELATIVE AND SAVE LONG", "BRASL", IFMT_RIL1},
+	{0x00, "LOAD ADDRESS RELATIVE LONG", "LARL", IFMT_RIL1|IFMT_PCREL},
+	{0x01, "LOAD IMMEDIATE (64 32)", "LGFI", IFMT_RIL1|IFMT_PCREL},
+	{0x04, "BRANCH RELATIVE ON CONDITION LONG", "BRCL", IFMT_RIL2|IFMT_PCREL},
+	{0x05, "BRANCH RELATIVE AND SAVE LONG", "BRASL", IFMT_RIL1|IFMT_PCREL},
 	{0x06, "EXCLUSIVE OR IMMEDIATE (high)", "XIHF", IFMT_RIL1},
 	{0x07, "EXCLUSIVE OR IMMEDIATE (low)", "XILF", IFMT_RIL1},
 	{0x08, "INSERT IMMEDIATE (high)", "IIHF", IFMT_RIL1},
@@ -1489,8 +1181,10 @@
 };
 
 static opCode_t opc_ec[] = {
-	{0x44, "BRANCH RELATIVE ON INDEX HIGH (64)", "BRXHG", IFMT_RIE},
-	{0x45, "BRANCH RELATIVE ON INDEX LOW OR EQ. (64)", "BRXLG", IFMT_RIE},
+	{0x44, "BRANCH RELATIVE ON INDEX HIGH (64)", "BRXHG", IFMT_RIE1|IFMT_PCREL},
+	{0x45, "BRANCH RELATIVE ON INDEX LOW OR EQ. (64)", "BRXLG", IFMT_RIE1|IFMT_PCREL},
+	{0x64, "COMPARE AND BRANCH RELATIVE (32)", "CRJ", IFMT_RIE2|IFMT_PCREL},
+	{0x76, "COMPARE AND BRANCH RELATIVE (64)", "CRGJ", IFMT_RIE2|IFMT_PCREL},
 	{0x00, "", "", TBL_INV}
 };
 
@@ -1554,6 +1248,13 @@
 	{0x00, "", "", TBL_INV}
 };
 
+/*
+ *	The 1st two bits of the opcode describe the length of the
+ *	instruction (in halfwords). 00 - one; 01/10 - two; 11 - three
+ *	This table allows for a quick lookup and returns value in bytes
+ */
+static int lenTab[4] = {2, 4, 4, 6};
+
 /*====================== End of Global Variables ===================*/
 
 /*------------------------------------------------------------------*/
@@ -1582,7 +1283,92 @@
 
 /*------------------------------------------------------------------*/
 /*                                                                  */
-/* Name		- dtrace_dis390x.				    */
+/* Name		- dtrace_getfmtlen.				    */
+/*                                                                  */
+/* Function	- Get the format of the instruction and its length. */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+int
+dtrace_getfmtlen(char *instr, uint8_t *fmt)
+{
+	opCode_t *op;
+
+	switch(opCodes[instr[0]].type) {
+	case TBL_INV:
+		return(-1);
+		break;
+	case TBL_01 :
+		op = findOpCode(opc_01, instr[1], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_A5 :
+		op = findOpCode(opc_a5, instr[1], 0x0f);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_A7 :
+		op = findOpCode(opc_a7, instr[1], 0x0f);
+		if (op->type == TBL_INV)
+			return(-1);
+	case TBL_B2 :
+		op = &opc_b2[instr[1]];
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_B3 :
+		op = &opc_b3[instr[1]];
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_C0 :
+		op = findOpCode(opc_c0, instr[1], 0x0f);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_C2 :
+		op = findOpCode(opc_c2, instr[1], 0x0f);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_E3 :
+		op = findOpCode(opc_e3, instr[5], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_E5 :
+		op = findOpCode(opc_e5, instr[1], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_EB :
+		op = findOpCode(opc_eb, instr[5], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_EC :
+		op = findOpCode(opc_ec, instr[5], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	case TBL_ED :
+		op = findOpCode(opc_ed, instr[5], 0xff);
+		if (op->type == TBL_INV)
+			return(-1);
+		break;
+	default :
+		op = &opCodes[instr[0]];
+	}
+	*fmt = op->type;
+	return(lenTab[((instr[0] & 0xc0) >> 6)]);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_dis390.				    */
 /*                                                                  */
 /* Function	- Disassemble a single s390x instruction. Returns   */
 /*		  non-zero for a bad opcode.   		 	    */
@@ -1590,18 +1376,22 @@
 /*------------------------------------------------------------------*/
 
 int
-dtrace_dis390x(dis390x_t *x, uint64_t pc, char *buf, size_t buflen)
+dtrace_dis390(dis390_t *x, uint64_t pc, char *buf, size_t buflen)
 {
 	uchar_t instr[8];
 	int	size,
 		iOp,
+		opLen,
 		fmt;
 	opCode_t *op;
 	
-	size = x->d390x_get_bytes(x->d390x_data, &instr[0], 2);
+	size = x->d390_get_bytes(x->d390_data, &instr[0], 2);
 	if (size == -1)
 		return (-1);
 
+	opLen       = (instr[0] & 0xc0) >> 6;
+	x->d390_len = lenTab[opLen];
+
 	switch(opCodes[instr[0]].type) {
 	case TBL_INV:
 		return(-1);
@@ -1641,7 +1431,7 @@
 			return(-1);
 		break;
 	case TBL_E3 :
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 		op = findOpCode(opc_e3, instr[5], 0xff);
 		if (op->type == TBL_INV)
@@ -1653,22 +1443,22 @@
 			return(-1);
 		break;
 	case TBL_EB :
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 		op = findOpCode(opc_eb, instr[5], 0xff);
 		if (op->type == TBL_INV)
 			return(-1);
 		break;
 	case TBL_EC :
-		x->d390x_data = &instr[2];
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		x->d390_data = &instr[2];
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 		op = findOpCode(opc_ec, instr[5], 0xff);
 		if (op->type == TBL_INV)
 			return(-1);
 		break;
 	case TBL_ED :
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 		op = findOpCode(opc_ed, instr[5], 0xff);
 		if (op->type == TBL_INV)
@@ -1684,78 +1474,99 @@
 	/* SIY formats we've read in 6 bytes because the 2nd part of*/
 	/* the op code is in bits 44-47.			    */
 	/*----------------------------------------------------------*/
-	switch(op->type) {
+	x->d390_fmt = op->type;
+	switch((op->type & ~IFMT_PCREL)) {
 	case IFMT_E : 
 		if (buf != NULL) {
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\n", 
 					     pc, op->mnemonic);
 		} 
 		break;
 	case IFMT_I : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			I_t *tInstr = (I_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%d\n", 
 					     pc, op->mnemonic, tInstr->i1);
 		} 
 		break;
 	case IFMT_RI1 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RI1_t *ri1Instr = (RI1_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%d\n", 
 					     pc, op->mnemonic, ri1Instr->r1,
 					     ri1Instr->i2);
 		} 
 		break;
 	case IFMT_RI2 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RI2_t *ri2Instr = (RI2_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t0x%x,%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t0x%x,%d\n", 
 					     pc, op->mnemonic, ri2Instr->m1,
 					     ri2Instr->i2);
 		} 
 		break;
-	case IFMT_RIE : 
+	case IFMT_RIE1 : 
 		if (buf != NULL) {
-			RIE_t *rieInstr = (RIE_t *) &instr[0];
+			RIE1_t *rieInstr = (RIE1_t *) &instr[0];
 			void  *br = (void *) (pc + rieInstr->i2 * 2);
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%p\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%p\n", 
 					     pc, op->mnemonic, rieInstr->r1,
 					     rieInstr->r3, br);
 		} 
 		break;
+	case IFMT_RIE2 : 
+		if (buf != NULL) {
+			RIE2_t *rieInstr = (RIE2_t *) &instr[0];
+			void  *br = (void *) (pc + rieInstr->i4 * 2);
+
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d,%p\n", 
+					     pc, op->mnemonic, rieInstr->r1,
+					     rieInstr->r2, rieInstr->m3, br);
+		} 
+		break;
+	case IFMT_RIE3 : 
+		if (buf != NULL) {
+			RIE3_t *rieInstr = (RIE3_t *) &instr[0];
+
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d,%d\n", 
+					     pc, op->mnemonic, rieInstr->r1,
+					     rieInstr->r2, rieInstr->i3, rieInstr->i4,
+					     rieInstr->i5);
+		} 
+		break;
 	case IFMT_RIL1 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RIL1_t *ril1Instr = (RIL1_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%x,%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%x,%d\n", 
 					     pc, op->mnemonic, ril1Instr->r1,
 					     ril1Instr->i2);
 		} 
 		break;
 	case IFMT_RIL2 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RIL2_t *ril2Instr = (RIL2_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%x,%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%x,%d\n", 
 					     pc, op->mnemonic, ril2Instr->m1,
 					     ril2Instr->i2);
 		} 
@@ -1764,106 +1575,106 @@
 		if (buf != NULL) {
 			RR_t *rrInstr = (RR_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d\n", 
 					     pc, op->mnemonic, rrInstr->r1,
 					     rrInstr->r2);
 		} 
 		break;
 	case IFMT_RRE : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RRE_t *rreInstr = (RRE_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%%d\n", 
 					     pc, op->mnemonic, rreInstr->r1,
 					     rreInstr->r2);
 		} 
 		break;
 	case IFMT_RRF1 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RRF1_t *rrf1Instr = (RRF1_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d\n", 
 					     pc, op->mnemonic, rrf1Instr->r1,
 					     rrf1Instr->r3, rrf1Instr->r2);
 		} 
 		break;
 	case IFMT_RRF2 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RRF2_t *rrf2Instr = (RRF2_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,0x%x\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,0x%x\n", 
 					     pc, op->mnemonic, rrf2Instr->r1,
 					     rrf2Instr->r2, rrf2Instr->m3);
 		} 
 		break;
 	case IFMT_RRF3 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RRF3_t *rrf3Instr = (RRF3_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d,0x%x\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d,0x%x\n", 
 					     pc, op->mnemonic, rrf3Instr->r1,
 					     rrf3Instr->r3, rrf3Instr->r2,
 					     rrf3Instr->m4);
 		} 
 		break;
 	case IFMT_RRR : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RRR_t *rrrInstr = (RRR_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d,%d\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,R%d,%d\n", 
 					     pc, op->mnemonic, rrrInstr->r1,
 					     rrrInstr->r2, rrrInstr->r3);
 		} 
 		break;
 	case IFMT_RS1 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RS1_t *rs1Instr = (RS1_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d)\n", 
 					     pc, op->mnemonic, rs1Instr->r1,
 					     rs1Instr->r3, rs1Instr->d2,
 					     rs1Instr->b2);
 		} 
 		break;
 	case IFMT_RS2 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RS2_t *rs2Instr = (RS2_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,0x%x,%u(R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,0x%x,%u(R%d)\n", 
 					     pc, op->mnemonic, rs2Instr->r1,
 					     rs2Instr->m3, rs2Instr->d2,
 					     rs2Instr->b2);
 		} 
 		break;
 	case IFMT_RSI : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RSI_t *rsiInstr = (RSI_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d\n",
 					     pc, op->mnemonic, rsiInstr->r1,
 					     rsiInstr->r3, rsiInstr->i2);
 		} 
@@ -1872,7 +1683,7 @@
 		if (buf != NULL) {
 			RSL_t *rslInstr = (RSL_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d)\n",
 					     pc, op->mnemonic, rslInstr->d1,
 					     rslInstr->l1+1, rslInstr->b1);
 		} 
@@ -1882,7 +1693,7 @@
 			RSY1_t *rsy1Instr = (RSY1_t *) &instr[0];
 			int   disp = (rsy1Instr->dh << 12) + rsy1Instr->dl;
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%d(R%d)\n",
 					     pc, op->mnemonic, rsy1Instr->r1,
 					     rsy1Instr->r3, disp, rsy1Instr->b2);
 		} 
@@ -1892,19 +1703,19 @@
 			RSY2_t *rsy2Instr = (RSY2_t *) &instr[0];
 			int   disp = (rsy2Instr->dh << 12) + rsy2Instr->dl;
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,0x%x,%d(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,0x%x,%d(R%d)\n",
 					     pc, op->mnemonic, rsy2Instr->r1,
 					     rsy2Instr->m3, disp, rsy2Instr->b2);
 		} 
 		break;
 	case IFMT_RX : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			RX_t *rxInstr = (RX_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d,R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d,R%d)\n", 
 					     pc, op->mnemonic, rxInstr->r1,
 					     rxInstr->d2, rxInstr->x2,
 					     rxInstr->b2);
@@ -1914,7 +1725,7 @@
 		if (buf != NULL) {
 			RXE_t *rxeInstr = (RXE_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d,R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d,R%d)\n", 
 					     pc, op->mnemonic, rxeInstr->r1,
 					     rxeInstr->d2, rxeInstr->x2, rxeInstr->b2);
 		} 
@@ -1923,7 +1734,7 @@
 		if (buf != NULL) {
 			RXF_t *rxfInstr = (RXF_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d,R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d,R%d)\n", 
 					     pc, op->mnemonic, rxfInstr->r1,
 					     rxfInstr->r3, rxfInstr->d2, rxfInstr->x2, 
 					     rxfInstr->b2);
@@ -1934,31 +1745,31 @@
 			RXY_t *rxfInstr = (RXY_t *) &instr[0];
 			int   disp = (rxfInstr->dh << 12) + rxfInstr->dl;
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%d(R%d,R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%d(R%d,R%d)\n", 
 					     pc, op->mnemonic, rxfInstr->r1,
 					     disp, rxfInstr->x2, rxfInstr->b2);
 		} 
 		break;
 	case IFMT_S : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			S_t *sInstr = (S_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d)\n", 
 					     pc, op->mnemonic, sInstr->d2,
 					     sInstr->b2);
 		} 
 		break;
 	case IFMT_SI : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 2) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 2) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SI_t *siInstr = (SI_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d),0x%x\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d),0x%x\n", 
 					     pc, op->mnemonic, siInstr->d1,
 					     siInstr->b1, siInstr->i2);
 		} 
@@ -1968,32 +1779,32 @@
 			SIY_t *siyInstr = (SIY_t *) &instr[0];
 			int   disp = (siyInstr->dh << 12) + siyInstr->dl;
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%d(R%d),0x%x\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%d(R%d),0x%x\n", 
 					     pc, op->mnemonic, disp,
 					     siyInstr->b1, siyInstr->i2);
 		} 
 		break;
 	case IFMT_SS1 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SS1_t *ss1Instr = (SS1_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(R%d)\n", 
 					     pc, op->mnemonic, ss1Instr->d1,
 					     ss1Instr->l+1, ss1Instr->b1,
 					     ss1Instr->d2, ss1Instr->b2);
 		} 
 		break;
 	case IFMT_SS2 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SS2_t *ss2Instr = (SS2_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(%d,R%d)\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(%d,R%d)\n", 
 					     pc, op->mnemonic, ss2Instr->d1,
 					     ss2Instr->l1+1, ss2Instr->b1,
 					     ss2Instr->d2, ss2Instr->l2+1, 
@@ -2001,65 +1812,65 @@
 		} 
 		break;
 	case IFMT_SS3 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SS3_t *ss3Instr = (SS3_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(R%d),0x%x\n", 
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(%d,R%d),%u(R%d),0x%x\n", 
 					     pc, op->mnemonic, ss3Instr->d1,
 					     ss3Instr->l1+1, ss3Instr->b1,
 					     ss3Instr->d2, ss3Instr->b2, ss3Instr->i3);
 		} 
 		break;
 	case IFMT_SS4 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SS4_t *ss4Instr = (SS4_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d),%u(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d),%u(R%d)\n",
 					     pc, op->mnemonic, ss4Instr->r1,
 					     ss4Instr->r3, ss4Instr->d1,
 					     ss4Instr->b1, ss4Instr->d2, ss4Instr->b2);
 		} 
 		break;
 	case IFMT_SS5 : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SS5_t *ss5Instr = (SS5_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d),%u(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,R%d,%u(R%d),%u(R%d)\n",
 					     pc, op->mnemonic, ss5Instr->r1,
 					     ss5Instr->r3, ss5Instr->d2,
 					     ss5Instr->b2, ss5Instr->d4, ss5Instr->b4);
 		} 
 		break;
 	case IFMT_SSE : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SSE_t *sseInstr = (SSE_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d),%u(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\t%u(R%d),%u(R%d)\n",
 					     pc, op->mnemonic, sseInstr->d1,
 					     sseInstr->b1, sseInstr->d2,
 					     sseInstr->b2);
 		} 
 		break;
 	case IFMT_SSF : 
-		if (x->d390x_get_bytes(x->d390x_data, &instr[2], 4) == -1)
+		if (x->d390_get_bytes(x->d390_data, &instr[2], 4) == -1)
 			return (-1);
 
 		if (buf != NULL) {
 			SSF_t *ssfInstr = (SSF_t *) &instr[0];
 
-			x->d390x_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d),%u(R%d)\n",
+			x->d390_sprintf_func(buf, buflen, "%p\t%s\tR%d,%u(R%d),%u(R%d)\n",
 					     pc, op->mnemonic, ssfInstr->r3,
 					     ssfInstr->d1, ssfInstr->b1,
 					     ssfInstr->d2, ssfInstr->b2);
--- a/usr/src/common/dis/s390/dis_tables.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/common/dis/s390/dis_tables.h	Thu Oct 08 12:44:34 2009 -0400
@@ -46,23 +46,355 @@
 #include <sys/inttypes.h>
 #include <sys/param.h>
 
+#define IFMT_E		0
+#define IFMT_I		1
+#define IFMT_RI1	2
+#define IFMT_RI2	3
+#define IFMT_RIE1	4
+#define IFMT_RIE2	5
+#define IFMT_RIE3	6
+#define IFMT_RIL1	7
+#define IFMT_RIL2	8
+#define IFMT_RR		9
+#define IFMT_RRE	10
+#define IFMT_RRF1	11
+#define IFMT_RRF2	12
+#define IFMT_RRF3	13
+#define IFMT_RRR	14
+#define IFMT_RS1	15
+#define IFMT_RS2	16
+#define IFMT_RSI	17
+#define IFMT_RSL	18
+#define IFMT_RSY1	19
+#define IFMT_RSY2	20
+#define IFMT_RX		21
+#define IFMT_RXE	22
+#define IFMT_RXF	23
+#define IFMT_RXY	24
+#define IFMT_S		25
+#define IFMT_SI		26
+#define IFMT_SIY	27
+#define IFMT_SS1	28
+#define IFMT_SS2	29
+#define IFMT_SS3	30
+#define IFMT_SS4	31
+#define IFMT_SS5	32
+#define IFMT_SSE	33
+#define IFMT_SSF	34
+
+#define IFMT_PCREL	0x80	/* Instruction has PC relative operand */
+
+typedef struct _E_t {
+	uint16_t opcode;
+} __attribute__ ((packed)) E_t;
+
+typedef struct _I_t {
+	uint8_t	opcode;
+	uint8_t i1;
+} __attribute__ ((packed)) I_t;
+
+typedef struct _RI1_t {
+	uint8_t	op1;
+	uint8_t r1  : 4;
+	uint8_t op2 : 4;
+	int16_t i2;
+} __attribute__ ((packed)) RI1_t ;
+
+typedef struct _RI2_t {
+	uint8_t	op1;
+	uint8_t m1  : 4;
+	uint8_t op2 : 4;
+	int16_t i2;
+} __attribute__ ((packed)) RI2_t;
+
+typedef struct _RIE1_t {
+	uint8_t	op1;
+	uint8_t r1 : 4;
+	uint8_t r3 : 4;
+	int16_t i2;
+	uint8_t xxx;
+	uint8_t op2;
+} __attribute__ ((packed)) RIE1_t;
+
+typedef struct _RIE2_t {
+	uint8_t	op1;
+	uint8_t r1 : 4;
+	uint8_t r2 : 4;
+	int16_t i4;
+	uint8_t m3 : 4;
+	uint8_t xx : 4;
+	uint8_t op2;
+} __attribute__ ((packed)) RIE2_t;
+
+typedef struct _RIE3_t {
+	uint8_t	op1;
+	uint8_t r1 : 4;
+	uint8_t r2 : 4;
+	int16_t i3;
+	int16_t i4;
+	int16_t i5;
+	uint8_t op2;
+} __attribute__ ((packed)) RIE3_t;
+
+typedef struct _RIL1_t {
+	uint8_t	op1;
+	uint8_t r1  : 4;
+	uint8_t op2 : 4;
+	int32_t i2;
+} __attribute__ ((packed)) RIL1_t;
+
+typedef struct _RIL2_t {
+	uint8_t	op1;
+	uint8_t m1  : 4;
+	uint8_t op2 : 4;
+	int32_t i2;
+} __attribute__ ((packed)) RIL2_t;
+
+typedef struct _RR_t {
+	uint8_t	opcode;
+	uint8_t r1 : 4;
+	uint8_t r2 : 4;
+} __attribute__ ((packed)) RR_t;
+
+typedef struct _RRE_t {
+	uint16_t opcode;
+	uint8_t  xxx;
+	uint8_t  r1 : 4;
+	uint8_t  r2 : 4;
+} __attribute__ ((packed)) RRE_t;
+
+typedef struct _RRF1_t {
+	uint16_t opcode;
+	uint8_t  r1 : 4;
+	uint8_t  xx : 4;
+	uint8_t  r3 : 4;
+	uint8_t  r2 : 4;
+} __attribute__ ((packed)) RRF1_t;
+
+typedef struct _RRF2_t {
+	uint16_t opcode;
+	uint8_t  m3 : 4;
+	uint8_t  xx : 4;
+	uint8_t  r1 : 4;
+	uint8_t  r2 : 4;
+} __attribute__ ((packed)) RRF2_t;
+
+typedef struct _RRF3_t {
+	uint16_t opcode;
+	uint8_t  r3 : 4;
+	uint8_t  m4 : 4;
+	uint8_t  r1 : 4;
+	uint8_t  r2 : 4;
+} __attribute__ ((packed)) RRF3_t;
+
+typedef struct _RRR_t {
+	uint16_t opcode;
+	uint8_t  r3 : 4;
+	uint8_t  xx : 4;
+	uint8_t  r1 : 4;
+	uint8_t  r2 : 4;
+} __attribute__ ((packed)) RRR_t;
+
+typedef struct _RS1_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  r3 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) RS1_t;
+
+typedef struct _RS2_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  m3 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) RS2_t;
+
+typedef struct _RSI_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  r3 : 4;
+	int16_t  i2;
+} __attribute__ ((packed)) RSI_t;
+
+typedef struct _RSL_t {
+	uint8_t  op1;
+	uint8_t  l1 : 4;
+	uint8_t  xx : 4;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint8_t  zz;
+	uint8_t  op2;
+} __attribute__ ((packed)) RSL_t;
+
+typedef struct _RSY1_t {
+	uint8_t  op1;
+	uint8_t  r1 : 4;
+	uint8_t  r3 : 4;
+	uint16_t b2 : 4;
+	uint16_t dl : 12;
+	uint8_t  dh;
+	uint8_t  op2;
+} __attribute__ ((packed)) RSY1_t;
+
+typedef struct _RSY2_t {
+	uint8_t  op1;
+	uint8_t  r1 : 4;
+	uint8_t  m3 : 4;
+	uint16_t b2 : 4;
+	uint16_t dl : 12;
+	uint8_t  dh;
+	uint8_t  op2;
+} __attribute__ ((packed)) RSY2_t;
+
+typedef struct _RX_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  x2 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) RX_t;
+
+typedef struct _RXE_t {
+	uint8_t  op1;
+	uint8_t  r1 : 4;
+	uint8_t  x2 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+	uint8_t  xx;
+	uint8_t  op2;
+} __attribute__ ((packed)) RXE_t;
+
+typedef struct _RXF_t {
+	uint8_t  op1;
+	uint8_t  r3 : 4;
+	uint8_t  x2 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+	uint8_t  r1 : 4;
+	uint8_t  xx : 4;
+	uint8_t  op2;
+} __attribute__ ((packed)) RXF_t;
+
+typedef struct _RXY_t {
+	uint8_t  op1;
+	uint8_t  r1 : 4;
+	uint8_t  x2 : 4;
+	uint16_t b2 : 4;
+	uint16_t dl : 12;
+	uint8_t  dh;
+	uint8_t  op2;
+} __attribute__ ((packed)) RXY_t;
+
+typedef struct _S_t {
+	uint16_t opcode;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) S_t;
+
+typedef struct _SI_t {
+	uint8_t  opcode;
+	uint8_t  i2;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+} __attribute__ ((packed)) SI_t;
+
+typedef struct _SIY_t {
+	uint8_t  opcode;
+	uint8_t  i2;
+	uint16_t b1 : 4;
+	uint16_t dl : 12;
+	uint8_t  dh;
+	uint8_t  op2;
+} __attribute__ ((packed)) SIY_t;
+
+typedef struct _SS1_t {
+	uint8_t  opcode;
+	uint8_t  l;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) SS1_t;
+
+typedef struct _SS2_t {
+	uint8_t  opcode;
+	uint8_t  l1 : 4;
+	uint8_t  l2 : 4;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) SS2_t;
+
+typedef struct _SS3_t {
+	uint8_t  opcode;
+	uint8_t  l1 : 4;
+	uint8_t  i3 : 4;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) SS3_t;
+
+typedef struct _SS4_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  r3 : 4;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) SS4_t;
+
+typedef struct _SS5_t {
+	uint8_t  opcode;
+	uint8_t  r1 : 4;
+	uint8_t  r3 : 4;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+	uint16_t b4 : 4;
+	uint16_t d4 : 12;
+} __attribute__ ((packed)) SS5_t;
+
+typedef struct _SSE_t {
+	uint16_t opcode;
+	uint16_t b1 : 4;
+	uint16_t d1 : 12;
+	uint16_t b2 : 4;
+	uint16_t d2 : 12;
+} __attribute__ ((packed)) SSE_t;
+
+typedef struct _SSF_t {
+	uint8_t  op1;
+	uint8_t  r3  : 4;
+	uint8_t  op2 : 4;
+	uint16_t b1  : 4;
+	uint16_t d1  : 12;
+	uint16_t b2  : 4;
+	uint16_t d2  : 12;
+} __attribute__ ((packed)) SSF_t;
+
 #define	OPLEN	256
-#define	PFIXLEN	  8
-#define	NCPS	12	/* number of chars per symbol	*/
 
 /*
  * data structures that must be provided to dtrace_dis390x()
  */
-typedef struct dis390x {
-	int		d390x_flags;
-	int		(*d390x_check_func)(void *);
-	int		(*d390x_get_bytes)(void *, uchar_t *, int);
-	int		(*d390x_sym_lookup)(void *, uint64_t, char *, size_t);
-	int		(*d390x_sprintf_func)(char *, size_t, const char *, ...);
-	void		*d390x_data;
-} dis390x_t;
+typedef struct dis390 {
+	int		(*d390_check_func)(void *);
+	int		(*d390_get_bytes)(void *, uchar_t *, int);
+	int		(*d390_sym_lookup)(void *, uint64_t, char *, size_t);
+	int		(*d390_sprintf_func)(char *, size_t, const char *, ...);
+	void		*d390_data;
+	int		d390_flags;
+	uint_t		d390_len;		/* instruction length */
+	int		d390_fmt;		/* instruction format */
+	char		d390_mnem[OPLEN];
+} dis390_t;
 
-extern int dtrace_dis390x(dis390x_t *, uint64_t, char *, size_t);
+extern int dtrace_dis390(dis390_t *, uint64_t, char *, size_t);
+extern int dtrace_getfmtlen(char *, uint8_t *);
 
 #define	DIS_F_OCTAL	0x1	/* Print all numbers in octal */
 #define	DIS_F_NOIMMSYM	0x2	/* Don't print symbols for immediates (.o) */
--- a/usr/src/common/dis/s390x/dis_tables.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/common/dis/s390x/dis_tables.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1600,7 +1600,7 @@
 		fmt;
 	opCode_t *op;
 	
-	size = x->d390x_get_bytes(x->d390x_data, &instr[0], 2);
+	x->d390x_len = size = x->d390x_get_bytes(x->d390x_data, &instr[0], 2);
 	if (size == -1)
 		return (-1);
 
--- a/usr/src/common/dis/s390x/dis_tables.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/common/dis/s390x/dis_tables.h	Thu Oct 08 12:44:34 2009 -0400
@@ -48,19 +48,19 @@
 #include <sys/param.h>
 
 #define	OPLEN	256
-#define	PFIXLEN	  8
-#define	NCPS	12	/* number of chars per symbol	*/
 
 /*
  * data structures that must be provided to dtrace_dis390x()
  */
 typedef struct dis390x {
 	int		d390x_flags;
+	uint_t		d390x_len;		/* instruction length */
 	int		(*d390x_check_func)(void *);
 	int		(*d390x_get_bytes)(void *, uchar_t *, int);
 	int		(*d390x_sym_lookup)(void *, uint64_t, char *, size_t);
 	int		(*d390x_sprintf_func)(char *, size_t, const char *, ...);
 	void		*d390x_data;
+	char		d390x_mnem[OPLEN];
 } dis390x_t;
 
 extern int dtrace_dis390x(dis390x_t *, uint64_t, char *, size_t);
--- a/usr/src/lib/libc/inc/thr_uberdata.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libc/inc/thr_uberdata.h	Thu Oct 08 12:44:34 2009 -0400
@@ -538,6 +538,8 @@
 	uint32_t	ul_drestore;	/* dtrace: restore %g0, %g0, %g0 */
 	uint32_t	ul_dftret;	/* dtrace: return probe fasttrap */
 	uint32_t	ul_dreturn;	/* dtrace: return %o0 */
+#elif defined(__s390)
+	uint8_t		ul_dinstr[24];	/* scratch space for dtrace */
 #endif
 	struct ulwp	*ul_self;	/* pointer to self */
 #if defined(__i386)
--- a/usr/src/lib/libdisasm/Makefile.com	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdisasm/Makefile.com	Thu Oct 08 12:44:34 2009 -0400
@@ -124,7 +124,7 @@
 #
 CPPFLAGS_dis_i386 = -I$(SRC)/common/dis/i386 -DDIS_TEXT
 CPPFLAGS_dis_sparc =
-CPPFLAGS_dis_s390 = -I$(SRC)/common/dis/s390x
+CPPFLAGS_dis_s390 = -I$(SRC)/common/dis/s390
 CPPFLAGS +=	$(CPPFLAGS_dis_$(MACH))
 
 CFLAGS_standalone = $(STAND_FLAGS_32)
--- a/usr/src/lib/libdisasm/Makefile.targ	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdisasm/Makefile.targ	Thu Oct 08 12:44:34 2009 -0400
@@ -92,6 +92,6 @@
 	$(INS.file)
 
 # install rule for x86 common source
-objs/%.o pics/%.o: $(SRC)/common/dis/i386/%.c
+objs/%.o pics/%.o: $(SRC)/common/dis/$(MACH)/%.c
 	$(COMPILE.c) -o $@ $<
 	$(POST_PROCESS_O)
--- a/usr/src/lib/libdisasm/s390/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdisasm/s390/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -37,8 +37,3 @@
 include ../Makefile.targ
 
 C99MODE = $(C99_ENABLE)
-
-# install rule for s390 common source
-objs/dis_tables.o pics/dis_tables.o: $(SRC)/common/dis/s390/dis_tables.c
-	$(COMPILE.c) -o $@ $(SRC)/common/dis/s390/dis_tables.c
-	$(POST_PROCESS_O)
--- a/usr/src/lib/libdisasm/s390/dis_s390.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdisasm/s390/dis_s390.c	Thu Oct 08 12:44:34 2009 -0400
@@ -83,7 +83,7 @@
 	int		dh_flags;
 	dis_lookup_f	dh_lookup;
 	dis_read_f	dh_read;
-	dis390x_t	dh_dis;
+	dis390_t	dh_dis;
 	uint64_t	dh_addr;
 	uint64_t	dh_end;
 };
@@ -217,10 +217,10 @@
 	dhp->dh_flags  = flags;
 	dhp->dh_data   = data;
 
-	dhp->dh_dis.d390x_sprintf_func = snprintf;
-	dhp->dh_dis.d390x_get_bytes    = get_bytes;
-	dhp->dh_dis.d390x_sym_lookup   = do_lookup;
-	dhp->dh_dis.d390x_check_func   = check_func;
+	dhp->dh_dis.d390_sprintf_func = snprintf;
+	dhp->dh_dis.d390_get_bytes    = get_bytes;
+	dhp->dh_dis.d390_sym_lookup   = do_lookup;
+	dhp->dh_dis.d390_check_func   = check_func;
 
 	return (dhp);
 }
@@ -375,7 +375,7 @@
 int
 dis_disassemble(dis_handle_t *dhp, uint64_t addr, char *buf, size_t buflen)
 {
-	return(dtrace_dis390x(&dhp->dh_dis, addr, buf, buflen));
+	return(dtrace_dis390(&dhp->dh_dis, addr, buf, buflen));
 }
 
 /*========================= End of Function ========================*/
--- a/usr/src/lib/libdisasm/s390x/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdisasm/s390x/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -18,13 +18,11 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sine Nomine Associates. All rights reserved.
+#
+# Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#
-# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
-# Use is subject to license terms.
-#
+
 ISASRCDIR=../$(MACH)/
 
 include ../Makefile.com
@@ -38,8 +36,3 @@
 include ../Makefile.targ
 
 C99MODE = $(C99_ENABLE)
-
-# install rule for s390x common source
-objs/dis_tables.o pics/dis_tables.o: $(SRC)/common/dis/s390x/dis_tables.c
-	$(COMPILE.c) -o $@ $(SRC)/common/dis/s390x/dis_tables.c
-	$(POST_PROCESS_O)
--- a/usr/src/lib/libdtrace/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -59,5 +59,5 @@
 # Cross-reference customization: build the cross-reference only over the
 # source directories, and ignore Makefiles and machine-generated source.
 #
-XRDIRS = common i386 sparc sparcv9
+XRDIRS = common i386 sparc sparcv9 s390 s390x
 XRDEL = dt_lex.c dt_grammar.c Makefile*
--- a/usr/src/lib/libdtrace/s390/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/s390/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -28,12 +28,23 @@
 #
 ASFLAGS += -D_ASM
 
-MAPDIR = ../spec/s390x
+MACHOBJS = dis_tables.o
+
 include ../Makefile.com
+
+SRCS += $(SRC)/common/dis/s390/dis_tables.c
+CPPFLAGS += -I$(SRC)/common/dis/s390
+
 LDLIBS += -lgcc_s
 
 SRCS += dt_asmsubr.s
 OBJECTS += dt_asmsubr.o
 
+LINTFLAGS += -erroff=E_BAD_PTR_CAST_ALIGN
+
+pics/%.o: $(SRC)/common/dis/s390/%.c
+	$(COMPILE.c) -o $@ $<
+	$(POST_PROCESS_O)
+
 install yydebug: all $(ROOTLIBS) $(ROOTLINKS) $(ROOTLINT) \
 	$(ROOTDLIBS) $(ROOTDOBJS)
--- a/usr/src/lib/libdtrace/s390/dt_asmsubr.s	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/s390/dt_asmsubr.s	Thu Oct 08 12:44:34 2009 -0400
@@ -42,7 +42,6 @@
 #else
 
 	ENTRY(dtrace_probe)
-	lhi	%r2,0
 	svc	ST_DTRACE_PROBE
 	br	%r14
 	SET_SIZE(dtrace_probe)
--- a/usr/src/lib/libdtrace/s390/dt_isadep.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/s390/dt_isadep.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1,62 +1,127 @@
-/*
- * 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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
+/*------------------------------------------------------------------*/
+/* 								    */
+/* Name        - dt_isadep. 					    */
+/* 								    */
+/* Function    - ISA dependent code for System z (64-bit)           */
+/* 								    */
+/* Name	       - Neale Ferguson					    */
+/* 								    */
+/* Date        - October, 2009   				    */
+/* 								    */
+/*------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------*/
+/*                   L I C E N S E                                  */
+/*------------------------------------------------------------------*/
 
-#pragma ident	"@(#)dt_isadep.c	1.6	05/06/08 SMI"
+/*==================================================================*/
+/* 								    */
+/* 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 the 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 2008 Sine Nomine Associates.                           */
+/* All rights reserved.                                             */
+/* Use is subject to license terms.                                 */
+/*								    */
+/* Copyright 2005 Sun Microsystems, Inc.  All rights reserved.	    */
+/* Use is subject to license terms.				    */
+/* 								    */
+/*==================================================================*/
+
+/*------------------------------------------------------------------*/
+/*                 D e f i n e s                                    */
+/*------------------------------------------------------------------*/
+
+#define BUCR	0x07f0		/* Branch unconditional register    */
+
+/*========================= End of Defines =========================*/
+
+/*------------------------------------------------------------------*/
+/*                 I n c l u d e s                                  */
+/*------------------------------------------------------------------*/
 
 #include <stdlib.h>
 #include <assert.h>
 #include <errno.h>
 #include <string.h>
 #include <libgen.h>
-
+#include <dis_tables.h>
 #include <dt_impl.h>
 #include <dt_pid.h>
 
-#define	OP(x)		((x) >> 30)
-#define	OP2(x)		(((x) >> 22) & 0x07)
-#define	COND(x)		(((x) >> 25) & 0x0f)
-#define	A(x)		(((x) >> 29) & 0x01)
+/*========================= End of Includes ========================*/
+
+/*------------------------------------------------------------------*/
+/*                 T y p e d e f s                                  */
+/*------------------------------------------------------------------*/
+
+
+/*========================= End of Typedefs ========================*/
+
+/*------------------------------------------------------------------*/
+/*                E x t e r n a l   R e f e r e n c e s             */
+/*------------------------------------------------------------------*/
+
+typedef struct dtrace_dis {
+	uchar_t	*instr;
+	dtrace_hdl_t *dtp;
+	pid_t pid;
+	uintptr_t addr;
+} dtrace_dis_t;
+
+/*=================== End of External References ===================*/
 
-#define	OP_BRANCH	0
+/*------------------------------------------------------------------*/
+/*                   P r o t o t y p e s                            */
+/*------------------------------------------------------------------*/
+
+static int dt_getbyte(void *, uchar_t *, int);
+static int dt_instr_size(uchar_t *, dtrace_hdl_t *, pid_t, 
+			 uintptr_t, char);
+
+/*========================= End of Prototypes ======================*/
 
-#define	OP2_BPcc	0x1
-#define	OP2_Bicc	0x2
-#define	OP2_BPr		0x3
-#define	OP2_FBPfcc	0x5
-#define	OP2_FBfcc	0x6
+/*------------------------------------------------------------------*/
+/*                 G l o b a l   V a r i a b l e s                  */
+/*------------------------------------------------------------------*/
+
+/*====================== End of Global Variables ===================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_pid_create_entry_probe.                        */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 /*ARGSUSED*/
 int
 dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
     fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
 {
-	ftp->ftps_type = DTFTP_ENTRY;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
-	ftp->ftps_noffs = 1;
+	ftp->ftps_type    = DTFTP_ENTRY;
+	ftp->ftps_pc	  = (uintptr_t)symp->st_value;
+	ftp->ftps_size	  = (size_t)symp->st_size;
+	ftp->ftps_noffs   = 1;
 	ftp->ftps_offs[0] = 0;
 
 	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
@@ -68,14 +133,25 @@
 	return (1);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_pid_create_return_probe.                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 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)
 {
-
-	uint32_t *text;
-	int i;
+	uint8_t *text;
+	int i, size;
 	int srdepth = 0;
+	pid_t pid   = Pstatus(P)->pr_pid;
+	char dmodel = Pstatus(P)->pr_dmodel;
 
 	if ((text = malloc(symp->st_size + 4)) == NULL) {
 		dt_dprintf("mr sparkle: malloc() failed\n");
@@ -92,172 +168,25 @@
 	 * Leave a dummy instruction in the last slot to simplify edge
 	 * conditions.
 	 */
-	text[symp->st_size / 4] = 0;
+	text[symp->st_size] = 0;
 
-	ftp->ftps_type = DTFTP_RETURN;
-	ftp->ftps_pc = symp->st_value;
-	ftp->ftps_size = symp->st_size;
+	ftp->ftps_type  = DTFTP_RETURN;
+	ftp->ftps_pc    = symp->st_value;
+	ftp->ftps_size  = symp->st_size;
 	ftp->ftps_noffs = 0;
 
-	for (i = 0; i < symp->st_size / 4; i++) {
-		/*
-		 * If we encounter an existing tracepoint, query the
-		 * kernel to find out the instruction that was
-		 * replaced at this spot.
-		 */
-		while (text[i] == FASTTRAP_INSTR) {
-			fasttrap_instr_query_t instr;
-
-			instr.ftiq_pid = Pstatus(P)->pr_pid;
-			instr.ftiq_pc = symp->st_value + i * 4;
-
-			if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_GETINSTR,
-			    &instr) != 0) {
-
-				if (errno == ESRCH || errno == ENOENT) {
-					if (Pread(P, &text[i], 4,
-					    instr.ftiq_pc) != 4) {
-						dt_dprintf("mr sparkle: "
-						    "Pread() failed\n");
-						free(text);
-						return (DT_PROC_ERR);
-					}
-					continue;
-				}
-
-				free(text);
-				dt_dprintf("mr sparkle: getinstr query "
-				    "failed: %s\n", strerror(errno));
-				return (DT_PROC_ERR);
-			}
-
-			text[i] = instr.ftiq_instr;
-			break;
-		}
-
-		/* save */
-		if ((text[i] & 0xc1f80000) == 0x81e00000) {
-			srdepth++;
-			continue;
-		}
-
-		/* restore */
-		if ((text[i] & 0xc1f80000) == 0x81e80000) {
-			srdepth--;
-			continue;
-		}
-
-		if (srdepth > 0) {
-			/* ret */
-			if (text[i] == 0x81c7e008)
-				goto is_ret;
-
-			/* return */
-			if (text[i] == 0x81cfe008)
-				goto is_ret;
-
-			/* call or jmpl w/ restore in the slot */
-			if (((text[i] & 0xc0000000) == 0x40000000 ||
-			    (text[i] & 0xc1f80000) == 0x81c00000) &&
-			    (text[i + 1] & 0xc1f80000) == 0x81e80000)
-				goto is_ret;
-
-			/* call to one of the stret routines */
-			if ((text[i] & 0xc0000000) == 0x40000000) {
-				int32_t	disp = text[i] << 2;
-				uint64_t dest = ftp->ftps_pc + i * 4 + disp;
-
-				dt_dprintf("dest = %llx\n", (u_longlong_t)dest);
-
-				if (dest == stret[0] || dest == stret[1] ||
-				    dest == stret[2] || dest == stret[3])
-					goto is_ret;
-			}
-		} else {
-			/* external call */
-			if ((text[i] & 0xc0000000) == 0x40000000) {
-				int32_t dst = text[i] << 2;
+	for (i = 0; i < symp->st_size; i += size) {
+		uint16_t *br = (uint16_t *) text;
 
-				dst += i * 4;
-
-				if ((uintptr_t)dst >= (uintptr_t)symp->st_size)
-					goto is_ret;
-			}
-
-			/* jmpl into %g0 -- this includes the retl pseudo op */
-			if ((text[i] & 0xfff80000) == 0x81c00000)
-				goto is_ret;
-
-			/* external branch -- possible return site */
-			if (OP(text[i]) == OP_BRANCH) {
-				int32_t dst;
-				int baa;
-
-				switch (OP2(text[i])) {
-				case OP2_BPcc:
-					dst = text[i] & 0x7ffff;
-					dst <<= 13;
-					dst >>= 11;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_Bicc:
-					dst = text[i] & 0x3fffff;
-					dst <<= 10;
-					dst >>= 8;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_BPr:
-					dst = (((text[i]) >> 6) & 0xc000) |
-					    ((text[i]) & 0x3fff);
-					dst <<= 16;
-					dst >>= 14;
+		size = dt_instr_size(&text[i], dtp, pid, symp->st_value + i, dmodel);
+		if (size < 0)
+			break;
 
-					baa = 0;
-					break;
-				case OP2_FBPfcc:
-					dst = text[i] & 0x7ffff;
-					dst <<= 13;
-					dst >>= 11;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_FBfcc:
-					dst = text[i] & 0x3fffff;
-					dst <<= 10;
-					dst >>= 8;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				default:
-					continue;
-				}
-
-				dst += i * 4;
+		if ((*br & 0xfff0) != BUCR)
+			continue;
 
-				/*
-				 * Interpret branches outside of the function's
-				 * bounds as potential return sites. If the
-				 * branch is a ba,a don't skip the instruction
-				 * in the delay slot.
-				 */
-				if ((uintptr_t)dst >=
-				    (uintptr_t)symp->st_size) {
-					if (baa)
-						goto is_ret_baa;
-					else
-						goto is_ret;
-				}
-			}
-		}
-
-		continue;
-is_ret:
-		i++;
-is_ret_baa:
-		dt_dprintf("return at offset %x\n", i * 4);
-		ftp->ftps_offs[ftp->ftps_noffs++] = i * 4;
+		dt_dprintf("return at offset %x\n", i);
+		ftp->ftps_offs[ftp->ftps_noffs++] = i;
 	}
 
 	free(text);
@@ -273,6 +202,16 @@
 	return (ftp->ftps_noffs);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_pid_create_offset_probe.                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 int
 dt_pid_create_offset_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
@@ -281,10 +220,10 @@
 	if (off & 0x3)
 		return (DT_PROC_ALIGN);
 
-	ftp->ftps_type = DTFTP_OFFSETS;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
-	ftp->ftps_noffs = 1;
+	ftp->ftps_type    = DTFTP_OFFSETS;
+	ftp->ftps_pc	  = (uintptr_t)symp->st_value;
+	ftp->ftps_size    = (size_t)symp->st_size;
+	ftp->ftps_noffs   = 1;
 	ftp->ftps_offs[0] = off;
 
 	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
@@ -296,6 +235,16 @@
 	return (1);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_pid_create_glob_offset_probes.                 */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 int
 dt_pid_create_glob_offset_probes(struct ps_prochandle *P, dtrace_hdl_t *dtp,
@@ -303,9 +252,9 @@
 {
 	ulong_t i;
 
-	ftp->ftps_type = DTFTP_OFFSETS;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
+	ftp->ftps_type  = DTFTP_OFFSETS;
+	ftp->ftps_pc    = (uintptr_t)symp->st_value;
+	ftp->ftps_size  = (size_t)symp->st_size;
 	ftp->ftps_noffs = 0;
 
 	/*
@@ -336,3 +285,88 @@
 
 	return (ftp->ftps_noffs);
 }
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_getbyte.   				    */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+static int
+dt_getbyte(void *data, uchar_t *inst, int len)
+{
+	dtrace_dis_t	*dis = data;
+	uint16_t ret = *(uint16_t *) dis->instr;
+
+	if (ret == FASTTRAP_INSTR) {
+		fasttrap_instr_query_t instr;
+
+		instr.ftiq_pid = dis->pid;
+		instr.ftiq_pc  = dis->addr;
+
+		/*
+		 * If we hit a byte that looks like the fasttrap provider's
+		 * trap instruction (which doubles as the breakpoint
+		 * instruction for debuggers) we need to query the kernel
+		 * for the real value. This may just be part of an immediate
+		 * value so there's no need to return an error if the
+		 * kernel doesn't know about this address.
+		 */
+		if (ioctl(dis->dtp->dt_ftfd, FASTTRAPIOC_GETINSTR, &instr) == 0)
+			ret = instr.ftiq_instr;
+	}
+
+	dis->addr  += len;
+	dis->instr += len;
+
+	return ((int)ret);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dt_instr_size.				    */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+static int
+dt_instr_size(uchar_t *instr, dtrace_hdl_t *dtp, pid_t pid, uintptr_t addr,
+    char dmodel)
+{
+	dtrace_dis_t data;
+	dis390_t s390dis;
+	uint_t cpu_mode;
+	uint16_t *opcode = (uint16_t *) instr;
+
+	data.instr = instr;
+	data.dtp   = dtp;
+	data.pid   = pid;
+	data.addr  = addr;
+
+	s390dis.d390_data       = &data;
+	s390dis.d390_get_bytes  = dt_getbyte;
+	s390dis.d390_check_func = NULL;
+
+	if (dtrace_dis390(&s390dis, addr, NULL, 0) != 0)
+		return (-1);
+
+	/*
+	 * If the instruction was a single-byte breakpoint, there may be
+	 * another debugger attached to this process. The original instruction
+	 * can't be recovered so this must fail.
+	 */
+	if (s390dis.d390_len == 2 && *opcode == FASTTRAP_INSTR)
+		return (-1);
+
+	return (s390dis.d390_len);
+
+}
+
+/*========================= End of Function ========================*/
--- a/usr/src/lib/libdtrace/s390/regs.d	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/s390/regs.d	Thu Oct 08 12:44:34 2009 -0400
@@ -20,101 +20,120 @@
  * CDDL HEADER END
  */
 /*
+ * Copyright 2009 Sine Nomine Associates. All rights reserved.
+ * Use is subject to license terms.
+ */
+/*
  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
  * Use is subject to license terms.
  */
 
-#pragma ident	"@(#)regs.d	1.2	05/06/08 SMI"
-
-inline int R_G0	= 0;
+inline int R_PSWM = 0;
+#pragma D binding "1.0" R_PSWM
+inline int R_PSWA = 1;
+#pragma D binding "1.0" R_PSWA
+inline int R_PC = 1;
+#pragma D binding "1.0" R_PC
+inline int R_G0	= 2;
 #pragma D binding "1.0" R_G0
-inline int R_G1	= 1;
+inline int R_G1	= 3;
 #pragma D binding "1.0" R_G1
-inline int R_G2	= 2;
+inline int R_G2	= 4;
 #pragma D binding "1.0" R_G2
-inline int R_G3	= 3;
+inline int R_G3	= 5;
 #pragma D binding "1.0" R_G3
-inline int R_G4	= 4;
+inline int R_G4	= 6;
 #pragma D binding "1.0" R_G4
-inline int R_G5	= 5;
+inline int R_G5	= 7;
 #pragma D binding "1.0" R_G5
-inline int R_G6	= 6;
+inline int R_G6	= 8;
 #pragma D binding "1.0" R_G6
-inline int R_G7	= 7;
+inline int R_G7	= 9;
 #pragma D binding "1.0" R_G7
+inline int R_G8	= 10;
+#pragma D binding "1.0" R_G8
+inline int R_G9	= 11;
+#pragma D binding "1.0" R_G9
+inline int R_G10 = 12;
+#pragma D binding "1.0" R_G10
+inline int R_G11 = 13;
+#pragma D binding "1.0" R_G11
+inline int R_G12 = 14;
+#pragma D binding "1.0" R_G12
+inline int R_G13 = 15;
+#pragma D binding "1.0" R_G13
+inline int R_G14 = 16;
+#pragma D binding "1.0" R_G14
+inline int R_G15 = 17;
+#pragma D binding "1.0" R_G15
 
-inline int R_O0	= 8;
-#pragma D binding "1.0" R_O0
-inline int R_O1	= 9;
-#pragma D binding "1.0" R_O1
-inline int R_O2	= 10;
-#pragma D binding "1.0" R_O2
-inline int R_O3	= 11;
-#pragma D binding "1.0" R_O3
-inline int R_O4	= 12;
-#pragma D binding "1.0" R_O4
-inline int R_O5	= 13;
-#pragma D binding "1.0" R_O5
-inline int R_O6	= 14;
-#pragma D binding "1.0" R_O6
-inline int R_O7	= 15;
-#pragma D binding "1.0" R_O7
+inline int R_ILC = 18;
+#pragma D binding "1.0" R_ILC
 
-inline int R_L0	= 16;
-#pragma D binding "1.0" R_L0
-inline int R_L1	= 17;
-#pragma D binding "1.0" R_L1
-inline int R_L2	= 18;
-#pragma D binding "1.0" R_L2
-inline int R_L3	= 19;
-#pragma D binding "1.0" R_L3
-inline int R_L4	= 20;
-#pragma D binding "1.0" R_L4
-inline int R_L5	= 21;
-#pragma D binding "1.0" R_L5
-inline int R_L6	= 22;
-#pragma D binding "1.0" R_L6
-inline int R_L7	= 23;
-#pragma D binding "1.0" R_L7
+inline int R_A0	= 19;
+#pragma D binding "1.0" R_A0
+inline int R_A1	= 20;
+#pragma D binding "1.0" R_A1
+inline int R_A2	= 21;
+#pragma D binding "1.0" R_A2
+inline int R_A3	= 22;
+#pragma D binding "1.0" R_A3
+inline int R_A4	= 23;
+#pragma D binding "1.0" R_A4
+inline int R_A5	= 24;
+#pragma D binding "1.0" R_A5
+inline int R_A6	= 25;
+#pragma D binding "1.0" R_A6
+inline int R_A7	= 26;
+#pragma D binding "1.0" R_A7
+inline int R_A8	= 27;
+#pragma D binding "1.0" R_A8
+inline int R_A9	= 28;
+#pragma D binding "1.0" R_A9
+inline int R_A10 = 29;
+#pragma D binding "1.0" R_A10
+inline int R_A11 = 30;
+#pragma D binding "1.0" R_A11
+inline int R_A12 = 31;
+#pragma D binding "1.0" R_A12
+inline int R_A13 = 32;
+#pragma D binding "1.0" R_A13
+inline int R_A14 = 33;
+#pragma D binding "1.0" R_A14
+inline int R_A15 = 34;
+#pragma D binding "1.0" R_A15
 
-inline int R_I0	= 24;
-#pragma D binding "1.0" R_I0
-inline int R_I1	= 25;
-#pragma D binding "1.0" R_I1
-inline int R_I2	= 26;
-#pragma D binding "1.0" R_I2
-inline int R_I3	= 27;
-#pragma D binding "1.0" R_I3
-inline int R_I4	= 28;
-#pragma D binding "1.0" R_I4
-inline int R_I5	= 29;
-#pragma D binding "1.0" R_I5
-inline int R_I6	= 30;
-#pragma D binding "1.0" R_I6
-inline int R_I7	= 31;
-#pragma D binding "1.0" R_I7
-
-inline int R_CCR = 32;
-#pragma D binding "1.0" R_CCR
-inline int R_PC = 33;
-#pragma D binding "1.0" R_PC
-inline int R_nPC = 34;
-#pragma D binding "1.0" R_nPC
-inline int R_NPC = R_nPC;
-#pragma D binding "1.0" R_NPC
-inline int R_Y = 35;
-#pragma D binding "1.0" R_Y
-inline int R_ASI = 36;
-#pragma D binding "1.0" R_ASI
-inline int R_FPRS = 37;
-#pragma D binding "1.0" R_FPRS
-inline int R_PS = R_CCR;
-#pragma D binding "1.0" R_PS
-inline int R_SP = R_O6;
-#pragma D binding "1.0" R_SP
-inline int R_FP = R_I6;
-#pragma D binding "1.0" R_FP
-inline int R_R0 = R_O0;
-#pragma D binding "1.0" R_R0
-inline int R_R1 = R_O1;
-#pragma D binding "1.0" R_R1
+inline int R_FPC = 35;
+#pragma D binding "1.0" R_FPC
+inline int R_F0	= 36;
+#pragma D binding "1.0" R_F0
+inline int R_F1	= 37;
+#pragma D binding "1.0" R_F1
+inline int R_F2	= 38;
+#pragma D binding "1.0" R_F2
+inline int R_F3	= 39;
+#pragma D binding "1.0" R_F3
+inline int R_F4	= 40;
+#pragma D binding "1.0" R_F4
+inline int R_F5	= 41;
+#pragma D binding "1.0" R_F5
+inline int R_F6	= 42;
+#pragma D binding "1.0" R_F6
+inline int R_F7	= 43;
+#pragma D binding "1.0" R_F7
+inline int R_F8	= 44;
+#pragma D binding "1.0" R_F8
+inline int R_F9	= 45;
+#pragma D binding "1.0" R_F9
+inline int R_F10 = 46;
+#pragma D binding "1.0" R_F10
+inline int R_F11 = 47;
+#pragma D binding "1.0" R_F11
+inline int R_F12 = 48;
+#pragma D binding "1.0" R_F12
+inline int R_F13 = 49;
+#pragma D binding "1.0" R_F13
+inline int R_F14 = 50;
+#pragma D binding "1.0" R_F14
+inline int R_F15 = 51;
+#pragma D binding "1.0" R_F15
--- a/usr/src/lib/libdtrace/s390x/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/lib/libdtrace/s390x/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -2,9 +2,8 @@
 # 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.
+# 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.
@@ -19,22 +18,30 @@
 #
 # CDDL HEADER END
 #
-# Copyright 2008 Sine Nomine Associates. All rights reserved.
+#
+# Copyright 2009 Sine Nomine Associates. All rights reserved.
 # Use is subject to license terms.
 #
-#
-# Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
+# Copyright 2006 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-ASFLAGS += -D_ASM
+
+ASFLAGS += -D_ASM -K PIC -P
 
-MAPDIR = ../spec/s390x
+MACHOBJS = dis_tables.o
+
 include ../Makefile.com
 include ../../Makefile.lib.64
 
-SRCS += dt_asmsubr.s
-OBJECTS += dt_asmsubr.o
-LDFLAGS += -lgcc_s
+SRCS += $(SRC)/common/dis/s390/dis_tables.c
+CPPFLAGS += -I$(SRC)/common/dis/s390
+CPPFLAGS += -D_ELF64
+
+LINTFLAGS64 += -erroff=E_BAD_PTR_CAST_ALIGN
+
+pics/%.o: $(SRC)/common/dis/s390/%.c
+	$(COMPILE.c) -o $@ $<
+	$(POST_PROCESS_O)
 
 install yydebug: all $(ROOTLIBS64) $(ROOTLINKS64) $(ROOTLINT64) \
 	$(ROOTDLIBS) $(ROOTDOBJS64)
--- a/usr/src/lib/libdtrace/s390x/dt_isadep.c	Mon Oct 05 12:49:41 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,338 +0,0 @@
-/*
- * 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 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"@(#)dt_isadep.c	1.6	05/06/08 SMI"
-
-#include <stdlib.h>
-#include <assert.h>
-#include <errno.h>
-#include <string.h>
-#include <libgen.h>
-
-#include <dt_impl.h>
-#include <dt_pid.h>
-
-#define	OP(x)		((x) >> 30)
-#define	OP2(x)		(((x) >> 22) & 0x07)
-#define	COND(x)		(((x) >> 25) & 0x0f)
-#define	A(x)		(((x) >> 29) & 0x01)
-
-#define	OP_BRANCH	0
-
-#define	OP2_BPcc	0x1
-#define	OP2_Bicc	0x2
-#define	OP2_BPr		0x3
-#define	OP2_FBPfcc	0x5
-#define	OP2_FBfcc	0x6
-
-/*ARGSUSED*/
-int
-dt_pid_create_entry_probe(struct ps_prochandle *P, dtrace_hdl_t *dtp,
-    fasttrap_probe_spec_t *ftp, const GElf_Sym *symp)
-{
-	ftp->ftps_type = DTFTP_ENTRY;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
-	ftp->ftps_noffs = 1;
-	ftp->ftps_offs[0] = 0;
-
-	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
-		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
-		    strerror(errno));
-		return (dt_set_errno(dtp, errno));
-	}
-
-	return (1);
-}
-
-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)
-{
-
-	uint32_t *text;
-	int i;
-	int srdepth = 0;
-
-	if ((text = malloc(symp->st_size + 4)) == NULL) {
-		dt_dprintf("mr sparkle: malloc() failed\n");
-		return (DT_PROC_ERR);
-	}
-
-	if (Pread(P, text, symp->st_size, symp->st_value) != symp->st_size) {
-		dt_dprintf("mr sparkle: Pread() failed\n");
-		free(text);
-		return (DT_PROC_ERR);
-	}
-
-	/*
-	 * Leave a dummy instruction in the last slot to simplify edge
-	 * conditions.
-	 */
-	text[symp->st_size / 4] = 0;
-
-	ftp->ftps_type = DTFTP_RETURN;
-	ftp->ftps_pc = symp->st_value;
-	ftp->ftps_size = symp->st_size;
-	ftp->ftps_noffs = 0;
-
-	for (i = 0; i < symp->st_size / 4; i++) {
-		/*
-		 * If we encounter an existing tracepoint, query the
-		 * kernel to find out the instruction that was
-		 * replaced at this spot.
-		 */
-		while (text[i] == FASTTRAP_INSTR) {
-			fasttrap_instr_query_t instr;
-
-			instr.ftiq_pid = Pstatus(P)->pr_pid;
-			instr.ftiq_pc = symp->st_value + i * 4;
-
-			if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_GETINSTR,
-			    &instr) != 0) {
-
-				if (errno == ESRCH || errno == ENOENT) {
-					if (Pread(P, &text[i], 4,
-					    instr.ftiq_pc) != 4) {
-						dt_dprintf("mr sparkle: "
-						    "Pread() failed\n");
-						free(text);
-						return (DT_PROC_ERR);
-					}
-					continue;
-				}
-
-				free(text);
-				dt_dprintf("mr sparkle: getinstr query "
-				    "failed: %s\n", strerror(errno));
-				return (DT_PROC_ERR);
-			}
-
-			text[i] = instr.ftiq_instr;
-			break;
-		}
-
-		/* save */
-		if ((text[i] & 0xc1f80000) == 0x81e00000) {
-			srdepth++;
-			continue;
-		}
-
-		/* restore */
-		if ((text[i] & 0xc1f80000) == 0x81e80000) {
-			srdepth--;
-			continue;
-		}
-
-		if (srdepth > 0) {
-			/* ret */
-			if (text[i] == 0x81c7e008)
-				goto is_ret;
-
-			/* return */
-			if (text[i] == 0x81cfe008)
-				goto is_ret;
-
-			/* call or jmpl w/ restore in the slot */
-			if (((text[i] & 0xc0000000) == 0x40000000 ||
-			    (text[i] & 0xc1f80000) == 0x81c00000) &&
-			    (text[i + 1] & 0xc1f80000) == 0x81e80000)
-				goto is_ret;
-
-			/* call to one of the stret routines */
-			if ((text[i] & 0xc0000000) == 0x40000000) {
-				int32_t	disp = text[i] << 2;
-				uint64_t dest = ftp->ftps_pc + i * 4 + disp;
-
-				dt_dprintf("dest = %llx\n", (u_longlong_t)dest);
-
-				if (dest == stret[0] || dest == stret[1] ||
-				    dest == stret[2] || dest == stret[3])
-					goto is_ret;
-			}
-		} else {
-			/* external call */
-			if ((text[i] & 0xc0000000) == 0x40000000) {
-				int32_t dst = text[i] << 2;
-
-				dst += i * 4;
-
-				if ((uintptr_t)dst >= (uintptr_t)symp->st_size)
-					goto is_ret;
-			}
-
-			/* jmpl into %g0 -- this includes the retl pseudo op */
-			if ((text[i] & 0xfff80000) == 0x81c00000)
-				goto is_ret;
-
-			/* external branch -- possible return site */
-			if (OP(text[i]) == OP_BRANCH) {
-				int32_t dst;
-				int baa;
-
-				switch (OP2(text[i])) {
-				case OP2_BPcc:
-					dst = text[i] & 0x7ffff;
-					dst <<= 13;
-					dst >>= 11;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_Bicc:
-					dst = text[i] & 0x3fffff;
-					dst <<= 10;
-					dst >>= 8;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_BPr:
-					dst = (((text[i]) >> 6) & 0xc000) |
-					    ((text[i]) & 0x3fff);
-					dst <<= 16;
-					dst >>= 14;
-
-					baa = 0;
-					break;
-				case OP2_FBPfcc:
-					dst = text[i] & 0x7ffff;
-					dst <<= 13;
-					dst >>= 11;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				case OP2_FBfcc:
-					dst = text[i] & 0x3fffff;
-					dst <<= 10;
-					dst >>= 8;
-
-					baa = COND(text[i]) == 8 && A(text[i]);
-					break;
-				default:
-					continue;
-				}
-
-				dst += i * 4;
-
-				/*
-				 * Interpret branches outside of the function's
-				 * bounds as potential return sites. If the
-				 * branch is a ba,a don't skip the instruction
-				 * in the delay slot.
-				 */
-				if ((uintptr_t)dst >=
-				    (uintptr_t)symp->st_size) {
-					if (baa)
-						goto is_ret_baa;
-					else
-						goto is_ret;
-				}
-			}
-		}
-
-		continue;
-is_ret:
-		i++;
-is_ret_baa:
-		dt_dprintf("return at offset %x\n", i * 4);
-		ftp->ftps_offs[ftp->ftps_noffs++] = i * 4;
-	}
-
-	free(text);
-	if (ftp->ftps_noffs > 0) {
-		if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
-			dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
-			    strerror(errno));
-			return (dt_set_errno(dtp, errno));
-		}
-	}
-
-
-	return (ftp->ftps_noffs);
-}
-
-/*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)
-{
-	if (off & 0x3)
-		return (DT_PROC_ALIGN);
-
-	ftp->ftps_type = DTFTP_OFFSETS;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
-	ftp->ftps_noffs = 1;
-	ftp->ftps_offs[0] = off;
-
-	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
-		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
-		    strerror(errno));
-		return (dt_set_errno(dtp, errno));
-	}
-
-	return (1);
-}
-
-/*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)
-{
-	ulong_t i;
-
-	ftp->ftps_type = DTFTP_OFFSETS;
-	ftp->ftps_pc = (uintptr_t)symp->st_value;
-	ftp->ftps_size = (size_t)symp->st_size;
-	ftp->ftps_noffs = 0;
-
-	/*
-	 * If we're matching against everything, just iterate through each
-	 * instruction in the function, otherwise look for matching offset
-	 * names by constructing the string and comparing it against the
-	 * pattern.
-	 */
-	if (strcmp("*", pattern) == 0) {
-		for (i = 0; i < symp->st_size; i += 4) {
-			ftp->ftps_offs[ftp->ftps_noffs++] = i;
-		}
-	} else {
-		char name[sizeof (i) * 2 + 1];
-
-		for (i = 0; i < symp->st_size; i += 4) {
-			(void) sprintf(name, "%lx", i);
-			if (gmatch(name, pattern))
-				ftp->ftps_offs[ftp->ftps_noffs++] = i;
-		}
-	}
-
-	if (ioctl(dtp->dt_ftfd, FASTTRAPIOC_MAKEPROBE, ftp) != 0) {
-		dt_dprintf("fasttrap probe creation ioctl failed: %s\n",
-		    strerror(errno));
-		return (dt_set_errno(dtp, errno));
-	}
-
-	return (ftp->ftps_noffs);
-}
--- a/usr/src/lib/libdtrace/s390x/regs.d	Mon Oct 05 12:49:41 2009 -0400
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,120 +0,0 @@
-/*
- * 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 2003 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
-
-#pragma ident	"@(#)regs.d	1.2	05/06/08 SMI"
-
-inline int R_G0	= 0;
-#pragma D binding "1.0" R_G0
-inline int R_G1	= 1;
-#pragma D binding "1.0" R_G1
-inline int R_G2	= 2;
-#pragma D binding "1.0" R_G2
-inline int R_G3	= 3;
-#pragma D binding "1.0" R_G3
-inline int R_G4	= 4;
-#pragma D binding "1.0" R_G4
-inline int R_G5	= 5;
-#pragma D binding "1.0" R_G5
-inline int R_G6	= 6;
-#pragma D binding "1.0" R_G6
-inline int R_G7	= 7;
-#pragma D binding "1.0" R_G7
-
-inline int R_O0	= 8;
-#pragma D binding "1.0" R_O0
-inline int R_O1	= 9;
-#pragma D binding "1.0" R_O1
-inline int R_O2	= 10;
-#pragma D binding "1.0" R_O2
-inline int R_O3	= 11;
-#pragma D binding "1.0" R_O3
-inline int R_O4	= 12;
-#pragma D binding "1.0" R_O4
-inline int R_O5	= 13;
-#pragma D binding "1.0" R_O5
-inline int R_O6	= 14;
-#pragma D binding "1.0" R_O6
-inline int R_O7	= 15;
-#pragma D binding "1.0" R_O7
-
-inline int R_L0	= 16;
-#pragma D binding "1.0" R_L0
-inline int R_L1	= 17;
-#pragma D binding "1.0" R_L1
-inline int R_L2	= 18;
-#pragma D binding "1.0" R_L2
-inline int R_L3	= 19;
-#pragma D binding "1.0" R_L3
-inline int R_L4	= 20;
-#pragma D binding "1.0" R_L4
-inline int R_L5	= 21;
-#pragma D binding "1.0" R_L5
-inline int R_L6	= 22;
-#pragma D binding "1.0" R_L6
-inline int R_L7	= 23;
-#pragma D binding "1.0" R_L7
-
-inline int R_I0	= 24;
-#pragma D binding "1.0" R_I0
-inline int R_I1	= 25;
-#pragma D binding "1.0" R_I1
-inline int R_I2	= 26;
-#pragma D binding "1.0" R_I2
-inline int R_I3	= 27;
-#pragma D binding "1.0" R_I3
-inline int R_I4	= 28;
-#pragma D binding "1.0" R_I4
-inline int R_I5	= 29;
-#pragma D binding "1.0" R_I5
-inline int R_I6	= 30;
-#pragma D binding "1.0" R_I6
-inline int R_I7	= 31;
-#pragma D binding "1.0" R_I7
-
-inline int R_CCR = 32;
-#pragma D binding "1.0" R_CCR
-inline int R_PC = 33;
-#pragma D binding "1.0" R_PC
-inline int R_nPC = 34;
-#pragma D binding "1.0" R_nPC
-inline int R_NPC = R_nPC;
-#pragma D binding "1.0" R_NPC
-inline int R_Y = 35;
-#pragma D binding "1.0" R_Y
-inline int R_ASI = 36;
-#pragma D binding "1.0" R_ASI
-inline int R_FPRS = 37;
-#pragma D binding "1.0" R_FPRS
-inline int R_PS = R_CCR;
-#pragma D binding "1.0" R_PS
-inline int R_SP = R_O6;
-#pragma D binding "1.0" R_SP
-inline int R_FP = R_I6;
-#pragma D binding "1.0" R_FP
-inline int R_R0 = R_O0;
-#pragma D binding "1.0" R_R0
-inline int R_R1 = R_O1;
-#pragma D binding "1.0" R_R1
--- a/usr/src/uts/common/dtrace/profile.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/common/dtrace/profile.c	Thu Oct 08 12:44:34 2009 -0400
@@ -72,14 +72,18 @@
  */
 #ifdef __x86
 # define	PROF_ARTIFICIAL_FRAMES	10
-#elsif __sparc
+#elif __sparc
 # ifdef DEBUG
 #  define	PROF_ARTIFICIAL_FRAMES	4
 # else
 #  define	PROF_ARTIFICIAL_FRAMES	3
 # endif
-#elsif __s390
-# define	PROF_ARTIFICIAL_FRAMES	4
+#elif __s390
+# ifdef DEBUG
+#  define	PROF_ARTIFICIAL_FRAMES	4
+# else
+#  define	PROF_ARTIFICIAL_FRAMES	3
+# endif
 #endif
 
 #define	PROF_NAMELEN		15
--- a/usr/src/uts/common/sys/dtrace.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/common/sys/dtrace.h	Thu Oct 08 12:44:34 2009 -0400
@@ -2248,6 +2248,13 @@
 
 #endif
 
+#ifdef __s390
+# define DTRACE_INVOP_STMG		1
+# define DTRACE_INVOP_LMG		2
+# define DTRACE_INVOP_RET		3
+# define DTRACE_INVOP_NOP		4
+#endif
+
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/uts/s390x/Makefile.rules	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/s390x/Makefile.rules	Thu Oct 08 12:44:34 2009 -0400
@@ -98,7 +98,7 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
-$(OBJS_DIR)/%.o:		$(SRC)/common/dis/zSeries/%.c
+$(OBJS_DIR)/%.o:		$(SRC)/common/dis/s390/%.c
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
@@ -155,7 +155,7 @@
 $(LINTS_DIR)/%.ln:		$(UTSBASE)/common/os/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
-$(LINTS_DIR)/%.ln:		$(SRC)/common/dis/zSeries/%.c
+$(LINTS_DIR)/%.ln:		$(SRC)/common/dis/s390/%.c
 	@($(LHEAD) $(LINT.c) $< $(LTAIL))
 
 $(LINTS_DIR)/%.ln:		$(SRC)/common/atomic/%.c
--- a/usr/src/uts/s390x/ml/interrupt.s	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/s390x/ml/interrupt.s	Thu Oct 08 12:44:34 2009 -0400
@@ -112,7 +112,7 @@
 	.section ".rodata"
 	.align	8
 .svcTAB:
-	.quad	.syscall,  .nosvcall, .nosvcall, .nosvcall	//  0- 3
+	.quad	.syscall,  .dtrace,   .nosvcall, .nosvcall	//  0- 3
 	.quad	.nosvcall, .nosvcall, .nosvcall, .nosvcall	//  4- 7
 	.quad	.nosvcall, .nosvcall, .nosvcall, .nosvcall	//  8- B
 	.quad	.nosvcall, .nosvcall, .nosvcall, .nosvcall	//  C- F
@@ -382,7 +382,7 @@
 #if defined(lint)
 
 void
-()
+getlgrp()
 {}
 
 #else	/* lint */
@@ -504,6 +504,41 @@
 	
 /*------------------------------------------------------------------*/
 /*                                                                  */
+/* Name		- .dtrace.    					    */
+/*                                                                  */
+/* Function	- User probe trap encountered.                      */
+/*		                               		 	    */
+/* On Entry	- %r14 - return address        		 	    */
+/*          	- %r9  - Current thread pointer		 	    */
+/*          	- %r11 - Syscall number (not applicable here)	    */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+#if defined(lint)
+
+void
+dtrace()
+{}
+
+#else	/* lint */
+
+.dtrace:
+
+	lgr	%r10,%r14
+	la	%r6,MINFRAME(%r15)	// Get A(Save Area)
+	aghi	%r15,-SA(MINFRAME+8)
+	la	%r2,MINFRAME(%r15)
+	brasl	%r14,dtrace_user_probe
+	aghi	%r15,SA(MINFRAME+8)
+	lgr	%r14,%r10		// Restore link
+	br	%r14
+
+#endif
+
+/*========================= End of Function ========================*/
+	
+/*------------------------------------------------------------------*/
+/*                                                                  */
 /* Name		- .nosvcall.  					    */
 /*                                                                  */
 /* Function	- Unsupported call.                                 */
--- a/usr/src/uts/s390x/os/lgrpplat.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/s390x/os/lgrpplat.c	Thu Oct 08 12:44:34 2009 -0400
@@ -149,7 +149,7 @@
 /*------------------------------------------------------------------*/
 
 void
-lgrp_plat_init(lgrp_id_t lgrpid)
+lgrp_plat_init(lgrp_init_stages_t lgrpid)
 {
 	int i;
 
--- a/usr/src/uts/s390x/unix/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/s390x/unix/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -99,10 +99,6 @@
 CLOBBERFILES	= $(CLEANFILES) $(UNIX_BIN)
 CLEANLINTFILES	+= $(LINT_LIB)
 
-# instr_size needs a special header
-$(OBJS_DIR)/instr_size.o :=	EXTRA_OPTIONS	= -I$(SRC)/common/dis/s390x
-$(OBJS_DIR)/instr_size.ln :=	EXTRA_OPTIONS	= -I$(SRC)/common/dis/s390x
-
 CFLAGS += -DDIS_MEM
 
 #
--- a/usr/src/uts/zSeries/Makefile.files	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/Makefile.files	Thu Oct 08 12:44:34 2009 -0400
@@ -148,6 +148,12 @@
 #
 MODSTUB_OBJ =	modstubs.o
 
+#
+#			System z DTrace Providers
+#
+FBT_OBJS	+= fbt.o
+SDT_OBJS	+= sdt.o
+
 #	Section 3:	Misc.
 #
 ALL_DEFS	+= -Ds390x
--- a/usr/src/uts/zSeries/Makefile.rules	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/Makefile.rules	Thu Oct 08 12:44:34 2009 -0400
@@ -51,6 +51,10 @@
 	$(COMPILE.c) -o $@ $<
 	$(CTFCONVERT_O)
 
+$(OBJS_DIR)/%.o:		$(SRC)/common/dis/s390/%.c
+	$(COMPILE.c) -o $@ $<
+	$(CTFCONVERT_O)
+
 $(OBJS_DIR)/%.o:		$(UTSBASE)/zSeries/dtrace/%.s
 	$(COMPILE.s) -o $@ $<
 
--- a/usr/src/uts/zSeries/Makefile.zSeries.shared	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/Makefile.zSeries.shared	Thu Oct 08 12:44:34 2009 -0400
@@ -208,7 +208,7 @@
 #
 DRV_KMODS	+= arp bl bofi clone cn conskbd consms cpuid
 DRV_KMODS	+= crypto cryptoadm dca devinfo dump
-#DRV_KMODS	+= dtrace fasttrap fbt lockstat profile sdt systrace
+DRV_KMODS	+= dtrace fasttrap fbt lockstat profile sdt systrace
 DRV_KMODS	+= fssnap icmp icmp6 ip ip6 ipsecah
 DRV_KMODS	+= ipsecesp iptun iptunq iwscn keysock kmdb kstat ksyms llc1
 DRV_KMODS	+= lofi
--- a/usr/src/uts/zSeries/dtrace/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -40,13 +40,13 @@
 LINT_TARGET	= $(MODULE).lint
 INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOT_CONFFILE)
 
-DTRACE_INC_64	= -I$(UTSBASE)/s390x/zSeries
+DTRACE_OBJS    += dis_tables.o
+
+DTRACE_INC_64	= -I$(UTSBASE)/zSeries -I$(SRC)/common/dis/s390
 
 CFLAGS += $(CCVERBOSE)
 CPPFLAGS += $(DTRACE_INC_$(CLASS))
 
-DTRACE_XAS_64	= -xmarch=z900
-
 AS_CPPFLAGS	+= $(DTRACE_INC_64)
 ASFLAGS		+= $(DTRACE_XAS_$(CLASS))
 
--- a/usr/src/uts/zSeries/dtrace/dtrace_asm.s	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/dtrace_asm.s	Thu Oct 08 12:44:34 2009 -0400
@@ -280,7 +280,7 @@
 #else
 
 	ENTRY(dtrace_copyout)
-	larl	%r1,.LCexmvc
+	larl	%r1,.LCexmvc2
 	lghi	%r0,1			// 
 	sar	%a2,%r0			// Use access mode to get to user space
 	sacf	AC_ACCESS		//
@@ -301,7 +301,7 @@
 	ex	%r4,0(%r1)
 2:
 	br	%r14
-.lCexmvc:
+.lCexmvc2:
 	mvc	0(1,%r3),0(%r2)
 	SET_SIZE(dtrace_copyout)
 
@@ -317,6 +317,8 @@
 /*		                               		 	    */
 /*------------------------------------------------------------------*/
 
+#if defined(lint)
+
 /*ARGSUSED*/
 void
 dtrace_copyinstr(uintptr_t uaddr, uintptr_t kaddr, size_t size,
@@ -400,6 +402,8 @@
 /*		                               		 	    */
 /*------------------------------------------------------------------*/
 
+#if defined(lint)
+
 /*ARGSUSED*/
 void
 dtrace_copyoutstr(uintptr_t kaddr, uintptr_t uaddr, size_t size,
--- a/usr/src/uts/zSeries/dtrace/dtrace_isa.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/dtrace_isa.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1,72 +1,112 @@
-/*
- * 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
+/*------------------------------------------------------------------*/
+/* 								    */
+/* Name        - dtrace_isa.					    */
+/* 								    */
+/* Function    - Architecture dependent kernel support for dtrace.  */
+/* 								    */
+/* Name	       - Neale Ferguson					    */
+/* 								    */
+/* Date        - October, 2009.  				    */
+/* 								    */
+/*------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------*/
+/*                   L I C E N S E                                  */
+/*------------------------------------------------------------------*/
+
+/*==================================================================*/
+/* 								    */
+/* 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 the 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 2008 Sine Nomine Associates.                           */
 /* All rights reserved.                                             */
 /* Use is subject to license terms.                                 */
- */
+/* 								    */
+/* Copyright 2005 Sun Microsystems, Inc.  All rights reserved.	    */
+/* Use is subject to license terms.				    */
+/* 								    */
+/*==================================================================*/
 
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
+/*------------------------------------------------------------------*/
+/*                 D e f i n e s                                    */
+/*------------------------------------------------------------------*/
+
+/*========================= End of Defines =========================*/
 
+/*------------------------------------------------------------------*/
+/*                 I n c l u d e s                                  */
+/*------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/asm_linkage.h>
 #include <sys/dtrace_impl.h>
-#include <sys/atomic.h>
-#include <sys/model.h>
+#include <sys/stack.h>
 #include <sys/frame.h>
-#include <sys/stack.h>
-#include <sys/machpcb.h>
-#include <sys/procfs_isa.h>
 #include <sys/cmn_err.h>
+#include <sys/privregs.h>
 #include <sys/sysmacros.h>
 
-#define	DTRACE_FMT3OP3_MASK	0x81000000
-#define	DTRACE_FMT3OP3		0x80000000
-#define	DTRACE_FMT3RS1_SHIFT	14
-#define	DTRACE_FMT3RD_SHIFT	25
-#define	DTRACE_DISP22_SHIFT	10
-#define	DTRACE_RMASK		0x1f
-#define	DTRACE_REG_L0		16
-#define	DTRACE_REG_O7		15
-#define	DTRACE_REG_I0		24
-#define	DTRACE_REG_I6		30
-#define	DTRACE_RET		0x81c7e008
-#define	DTRACE_RETL		0x81c3e008
-#define	DTRACE_SAVE_MASK	0xc1f80000
-#define	DTRACE_SAVE		0x81e00000
-#define	DTRACE_RESTORE		0x81e80000
-#define	DTRACE_CALL_MASK	0xc0000000
-#define	DTRACE_CALL		0x40000000
-#define	DTRACE_JMPL_MASK	0x81f10000
-#define	DTRACE_JMPL		0x81c00000
-#define	DTRACE_BA_MASK		0xdfc00000
-#define	DTRACE_BA		0x10800000
-#define	DTRACE_BA_MAX		10
+/*========================= End of Includes ========================*/
+
+/*------------------------------------------------------------------*/
+/*                 T y p e d e f s                                  */
+/*------------------------------------------------------------------*/
+
+
+/*========================= End of Typedefs ========================*/
+
+/*------------------------------------------------------------------*/
+/*                E x t e r n a l   R e f e r e n c e s             */
+/*------------------------------------------------------------------*/
+
+extern uint8_t dtrace_fuword8_nocheck(void *);
+extern uint16_t dtrace_fuword16_nocheck(void *);
+extern uint32_t dtrace_fuword32_nocheck(void *);
+extern uint64_t dtrace_fuword64_nocheck(void *);
+
+/*=================== End of External References ===================*/
 
-extern int dtrace_getupcstack_top(uint64_t *, int, uintptr_t *);
-extern int dtrace_getustackdepth_top(uintptr_t *);
-extern ulong_t dtrace_getreg_win(uint_t, uint_t);
-extern void dtrace_putreg_win(uint_t, ulong_t);
-extern int dtrace_fish(int, int, uintptr_t *);
+/*------------------------------------------------------------------*/
+/*                   P r o t o t y p e s                            */
+/*------------------------------------------------------------------*/
+
+
+/*========================= End of Prototypes ======================*/
+
+/*------------------------------------------------------------------*/
+/*                 G l o b a l   V a r i a b l e s                  */
+/*------------------------------------------------------------------*/
+
+int	dtrace_ustackdepth_max = 2048;
+
+/*====================== End of Global Variables ===================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getpcstack.                                */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 /*
  * This is similar in principle to getpcstack(), but there are several marked
@@ -97,184 +137,18 @@
  *	don't fire through an interrupt source.)  This parameter is used to
  *	assure (b), above.
  */
+
+/*ARGSUSED*/
 void
-dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes, uint32_t *pc)
+dtrace_getpcstack(pc_t *pcstack, int pcstack_limit, int aframes,
+    uint32_t *intrpc)
 {
-	struct frame *fp, *nextfp, *minfp, *stacktop;
+	struct frame *fp = (struct frame *)dtrace_getfp();
+	struct frame *nextfp, *minfp, *stacktop;
 	int depth = 0;
-	int on_intr, j = 0;
-	uint32_t i, r;
-
-	fp = (struct frame *)((caddr_t)dtrace_getfp() + STACK_BIAS);
-	dtrace_flush_windows();
-
-	if (pc != NULL) {
-		/*
-		 * If we've been passed a non-NULL pc, we need to determine
-		 * whether or not the specified program counter falls in a leaf
-		 * function.  If it falls within a leaf function, we know that
-		 * %o7 is valid in its frame (and we can just drive on).  If
-		 * it's a non-leaf, however, we know that %o7 is garbage in the
-		 * bottom frame.  To trim this frame, we simply increment
-		 * aframes and drop into the stack-walking loop.
-		 *
-		 * To quickly determine if the specified program counter is in
-		 * a leaf function, we exploit the fact that leaf functions
-		 * tend to be short and non-leaf functions tend to frequently
-		 * perform operations that are only permitted in a non-leaf
-		 * function (e.g., using the %i's or %l's; calling a function;
-		 * performing a restore).  We exploit these tendencies by
-		 * simply scanning forward from the specified %pc -- if we see
-		 * an operation only permitted in a non-leaf, we know we're in
-		 * a non-leaf; if we see a retl, we know we're in a leaf.
-		 * Fortunately, one need not perform anywhere near full
-		 * disassembly to effectively determine the former: determining
-		 * that an instruction is a format-3 instruction and decoding
-		 * its rd and rs1 fields, for example, requires very little
-		 * manipulation.  Overall, this method of leaf determination
-		 * performs quite well:  on average, we only examine between
-		 * 1.5 and 2.5 instructions before making the determination.
-		 * (Outliers do exist, however; of note is the non-leaf
-		 * function ip_sioctl_not_ours() which -- as of this writing --
-		 * has a whopping 455 straight instructions that manipulate
-		 * only %g's and %o's.)
-		 */
-		int delay = 0, branches = 0, taken = 0;
-
-		if (depth < pcstack_limit)
-			pcstack[depth++] = (pc_t)(uintptr_t)pc;
-
-		/*
-		 * Our heuristic is exactly that -- a heuristic -- and there
-		 * exists a possibility that we could be either be vectored
-		 * off into the weeds (by following a bogus branch) or could
-		 * wander off the end of the function and off the end of a
-		 * text mapping (by not following a conditional branch at the
-		 * end of the function that is effectively always taken).  So
-		 * as a precautionary measure, we set the NOFAULT flag.
-		 */
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-
-		for (;;) {
-			i = pc[j++];
-
-			if ((i & DTRACE_FMT3OP3_MASK) == DTRACE_FMT3OP3) {
-				/*
-				 * This is a format-3 instruction.  We can
-				 * look at rd and rs1.
-				 */
-				r = (i >> DTRACE_FMT3RS1_SHIFT) & DTRACE_RMASK;
-
-				if (r >= DTRACE_REG_L0)
-					goto nonleaf;
-
-				r = (i >> DTRACE_FMT3RD_SHIFT) & DTRACE_RMASK;
-
-				if (r >= DTRACE_REG_L0)
-					goto nonleaf;
-
-				if ((i & DTRACE_JMPL_MASK) == DTRACE_JMPL) {
-					delay = 1;
-					continue;
-				}
-
-				/*
-				 * If we see explicit manipulation with %o7
-				 * as a destination register, we know that
-				 * %o7 is likely bogus -- and we treat this
-				 * function as a non-leaf.
-				 */
-				if (r == DTRACE_REG_O7) {
-					if (delay)
-						goto leaf;
-
-					i &= DTRACE_JMPL_MASK;
-
-					if (i == DTRACE_JMPL) {
-						delay = 1;
-						continue;
-					}
-
-					goto nonleaf;
-				}
-			} else {
-				/*
-				 * If this is a call, it may or may not be
-				 * a leaf; we need to check the delay slot.
-				 */
-				if ((i & DTRACE_CALL_MASK) == DTRACE_CALL) {
-					delay = 1;
-					continue;
-				}
-
-				/*
-				 * If we see a ret it's not a leaf; if we
-				 * see a retl, it is a leaf.
-				 */
-				if (i == DTRACE_RET)
-					goto nonleaf;
-
-				if (i == DTRACE_RETL)
-					goto leaf;
-
-				/*
-				 * If this is a ba (annulled or not), then we
-				 * need to actually follow the branch.  No, we
-				 * don't look at the delay slot -- hopefully
-				 * anything that can be gleaned from the delay
-				 * slot can also be gleaned from the branch
-				 * target.  To prevent ourselves from iterating
-				 * infinitely, we clamp the number of branches
-				 * that we'll follow, and we refuse to follow
-				 * the same branch twice consecutively.  In
-				 * both cases, we abort by deciding that we're
-				 * looking at a leaf.  While in theory this
-				 * could be wrong (we could be in the middle of
-				 * a loop in a non-leaf that ends with a ba and
-				 * only manipulates outputs and globals in the
-				 * body of the loop -- therefore leading us to
-				 * the wrong conclusion), this doesn't seem to
-				 * crop up in practice.  (Or rather, this
-				 * condition could not be deliberately induced,
-				 * despite concerted effort.)
-				 */
-				if ((i & DTRACE_BA_MASK) == DTRACE_BA) {
-					if (++branches == DTRACE_BA_MAX ||
-					    taken == j)
-						goto nonleaf;
-
-					taken = j;
-					j += ((int)(i << DTRACE_DISP22_SHIFT) >>
-					    DTRACE_DISP22_SHIFT) - 1;
-					continue;
-				}
-
-				/*
-				 * Finally, if it's a save, it should be
-				 * treated as a leaf; if it's a restore it
-				 * should not be treated as a leaf.
-				 */
-				if ((i & DTRACE_SAVE_MASK) == DTRACE_SAVE)
-					goto leaf;
-
-				if ((i & DTRACE_SAVE_MASK) == DTRACE_RESTORE)
-					goto nonleaf;
-			}
-
-			if (delay) {
-				/*
-				 * If this was a delay slot instruction and
-				 * we didn't pick it up elsewhere, this is a
-				 * non-leaf.
-				 */
-				goto nonleaf;
-			}
-		}
-nonleaf:
-		aframes++;
-leaf:
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-	}
+	int on_intr, last = 0;
+	uintptr_t pc;
+	uintptr_t caller = CPU->cpu_dtrace_caller;
 
 	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
 		stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME));
@@ -282,150 +156,193 @@
 		stacktop = (struct frame *)curthread->t_stk;
 	minfp = fp;
 
+	aframes++;
+
+	if (intrpc != NULL && depth < pcstack_limit)
+		pcstack[depth++] = (pc_t)intrpc;
+
 	while (depth < pcstack_limit) {
-		nextfp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS);
+		nextfp = (struct frame *)fp->fr_savfp;
+		pc = fp->fr_savpc;
+
 		if (nextfp <= minfp || nextfp >= stacktop) {
-			if (!on_intr && nextfp == stacktop && aframes != 0) {
-				/*
-				 * If we are exactly at the top of the stack
-				 * with a non-zero number of artificial frames,
-				 * it must be that the stack is filled with
-				 * nothing _but_ artificial frames.  In this
-				 * case, we assert that this is so, zero
-				 * pcstack, and return.
-				 */
-				ASSERT(aframes == 1);
-				ASSERT(depth == 0);
-
-				while (depth < pcstack_limit)
-					pcstack[depth++] = NULL;
-				return;
-			}
-
 			if (on_intr) {
 				/*
 				 * Hop from interrupt stack to thread stack.
 				 */
 				stacktop = (struct frame *)curthread->t_stk;
 				minfp = (struct frame *)curthread->t_stkbase;
-
 				on_intr = 0;
-
-				if (nextfp > minfp && nextfp < stacktop)
-					continue;
-			} else {
-				/*
-				 * High-level interrupts may occur when %sp is
-				 * not necessarily contained in the stack
-				 * bounds implied by %g7 -- interrupt thread
-				 * management runs with %pil at DISP_LEVEL,
-				 * and high-level interrupts may thus occur
-				 * in windows when %sp and %g7 are not self-
-				 * consistent.  If we call dtrace_getpcstack()
-				 * from a high-level interrupt that has occurred
-				 * in such a window, we will fail the above test
-				 * of nextfp against minfp/stacktop.  If the
-				 * high-level interrupt has in turn interrupted
-				 * a non-passivated interrupt thread, we
-				 * will execute the below code with non-zero
-				 * aframes.  We therefore want to assert that
-				 * aframes is zero _or_ we are in a high-level
-				 * interrupt -- but because cpu_intr_actv is
-				 * updated with high-level interrupts enabled,
-				 * we must reduce this to only asserting that
-				 * %pil is greater than DISP_LEVEL.
-				 */
-				ASSERT(aframes == 0 ||
-				    dtrace_getipl() > DISP_LEVEL);
-				pcstack[depth++] = (pc_t)fp->fr_savpc;
+				continue;
 			}
 
+			/*
+			 * This is the last frame we can process; indicate
+			 * that we should return after processing this frame.
+			 */
+			last = 1;
+		}
+
+		if (aframes > 0) {
+			if (--aframes == 0 && caller != NULL) {
+				/*
+				 * We've just run out of artificial frames,
+				 * and we have a valid caller -- fill it in
+				 * now.
+				 */
+				ASSERT(depth < pcstack_limit);
+				pcstack[depth++] = (pc_t)caller;
+				caller = NULL;
+			}
+		} else {
+			if (depth < pcstack_limit)
+				pcstack[depth++] = (pc_t)pc;
+		}
+
+		if (last) {
 			while (depth < pcstack_limit)
 				pcstack[depth++] = NULL;
 			return;
 		}
 
-		if (aframes > 0) {
-			aframes--;
-		} else {
-			pcstack[depth++] = (pc_t)fp->fr_savpc;
-		}
-
 		fp = nextfp;
 		minfp = fp;
 	}
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getustack_common.                          */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 static int
-dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t sp)
+dtrace_getustack_common(uint64_t *pcstack, int pcstack_limit, uintptr_t pc,
+    uintptr_t sp)
 {
+	klwp_t *lwp = ttolwp(curthread);
 	proc_t *p = curproc;
+	uintptr_t oldcontext = lwp->lwp_oldcontext;
+	uintptr_t oldsp;
+	volatile uint16_t *flags =
+	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+	size_t s1, s2;
 	int ret = 0;
 
 	ASSERT(pcstack == NULL || pcstack_limit > 0);
+	ASSERT(dtrace_ustackdepth_max > 0);
 
 	if (p->p_model == DATAMODEL_NATIVE) {
-		for (;;) {
-			struct frame *fr = (struct frame *)(sp + STACK_BIAS);
-			uintptr_t pc;
+		s1 = sizeof (struct frame) + 2 * sizeof (long);
+		s2 = s1 + sizeof (siginfo_t);
+	} else {
+		s1 = sizeof (struct frame32) + 3 * sizeof (int);
+		s2 = s1 + sizeof (siginfo32_t);
+	}
 
-			if (sp == 0 || fr == NULL ||
-			    !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN))
+	while (pc != 0) {
+		/*
+		 * We limit the number of times we can go around this
+		 * loop to account for a circular stack.
+		 */
+		if (ret++ >= dtrace_ustackdepth_max) {
+			*flags |= CPU_DTRACE_BADSTACK;
+			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = sp;
+			break;
+		}
+
+		if (pcstack != NULL) {
+			*pcstack++ = (uint64_t)pc;
+			pcstack_limit--;
+			if (pcstack_limit <= 0)
 				break;
+		}
 
-			pc = dtrace_fulword(&fr->fr_savpc);
-			sp = dtrace_fulword(&fr->fr_savfp);
+		if (sp == 0)
+			break;
+
+		oldsp = sp;
 
-			if (pc == 0)
-				break;
+		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
+			if (p->p_model == DATAMODEL_NATIVE) {
+				ucontext_t *ucp = (ucontext_t *)oldcontext;
+				greg_t *gregs = ucp->uc_mcontext.gregs;
 
-			ret++;
+				sp = dtrace_fulword(&gregs[REG_SP]);
+				pc = dtrace_fulword(&ucp->uc_mcontext.psw.pc);
+
+				oldcontext = dtrace_fulword(&ucp->uc_link);
+			} else {
+				ucontext32_t *ucp = (ucontext32_t *)oldcontext;
+				greg32_t *gregs = ucp->uc_mcontext.gregs;
 
-			if (pcstack != NULL) {
-				*pcstack++ = pc;
-				pcstack_limit--;
-				if (pcstack_limit == 0)
-					break;
+				sp = dtrace_fuword32(&gregs[REG_SP]);
+				pc = dtrace_fuword32(&ucp->uc_mcontext.psw.pc);
+
+				oldcontext = dtrace_fuword32(&ucp->uc_link);
+			}
+		} else {
+			if (p->p_model == DATAMODEL_NATIVE) {
+				struct frame *fr = (struct frame *)sp;
+
+				pc = dtrace_fulword(&fr->fr_savpc);
+				sp = dtrace_fulword(&fr->fr_savfp);
+			} else {
+				struct frame32 *fr = (struct frame32 *)sp;
+
+				pc = dtrace_fuword32(&fr->fr_savpc);
+				sp = dtrace_fuword32(&fr->fr_savfp);
 			}
 		}
-	} else {
-		for (;;) {
-			struct frame32 *fr = (struct frame32 *)sp;
-			uint32_t pc;
 
-			if (sp == 0 ||
-			    !IS_P2ALIGNED((uintptr_t)fr, STACK_ALIGN32))
-				break;
-
-			pc = dtrace_fuword32(&fr->fr_savpc);
-			sp = dtrace_fuword32(&fr->fr_savfp);
+		if (sp == oldsp) {
+			*flags |= CPU_DTRACE_BADSTACK;
+			cpu_core[CPU->cpu_id].cpuc_dtrace_illval = sp;
+			break;
+		}
 
-			if (pc == 0)
-				break;
-
-			ret++;
-
-			if (pcstack != NULL) {
-				*pcstack++ = pc;
-				pcstack_limit--;
-				if (pcstack_limit == 0)
-					break;
-			}
+		/*
+		 * 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;
 		}
 	}
 
 	return (ret);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getupcstack.                               */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 void
 dtrace_getupcstack(uint64_t *pcstack, int pcstack_limit)
 {
 	klwp_t *lwp = ttolwp(curthread);
 	proc_t *p = curproc;
 	struct regs *rp;
-	uintptr_t sp;
+	uintptr_t pc, sp;
 	int n;
 
+	ASSERT(DTRACE_CPUFLAG_ISSET(CPU_DTRACE_NOFAULT));
+
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
+		return;
+
 	if (pcstack_limit <= 0)
 		return;
 
@@ -441,31 +358,22 @@
 	if (pcstack_limit <= 0)
 		return;
 
-	*pcstack++ = (uint64_t)rp->r_pc;
-	pcstack_limit--;
-
-	if (pcstack_limit <= 0)
-		return;
+	pc = rp->r_pc;
+	sp = rp->r_sp;
 
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
-		*pcstack++ = (uint64_t)rp->r_o7;
+		*pcstack++ = (uint64_t)pc;
 		pcstack_limit--;
 		if (pcstack_limit <= 0)
 			return;
+
+		if (p->p_model == DATAMODEL_NATIVE)
+			pc = dtrace_fulword((void *)rp->r_sp);
+		else
+			pc = dtrace_fuword32((void *)rp->r_sp);
 	}
 
-	sp = rp->r_sp;
-
-	n = dtrace_getupcstack_top(pcstack, pcstack_limit, &sp);
-	ASSERT(n >= 0);
-	ASSERT(n <= pcstack_limit);
-
-	pcstack += n;
-	pcstack_limit -= n;
-	if (pcstack_limit <= 0)
-		return;
-
-	n = dtrace_getustack_common(pcstack, pcstack_limit, sp);
+	n = dtrace_getustack_common(pcstack, pcstack_limit, pc, sp);
 	ASSERT(n >= 0);
 	ASSERT(n <= pcstack_limit);
 
@@ -477,14 +385,24 @@
 		*pcstack++ = NULL;
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getustackdepth.                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 dtrace_getustackdepth(void)
 {
 	klwp_t *lwp = ttolwp(curthread);
 	proc_t *p = curproc;
 	struct regs *rp;
-	uintptr_t sp;
-	int n = 1;
+	uintptr_t pc, sp;
+	int n = 0;
 
 	if (lwp == NULL || p == NULL || (rp = lwp->lwp_regs) == NULL)
 		return (0);
@@ -492,30 +410,46 @@
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAULT))
 		return (-1);
 
+	pc = rp->r_pc;
 	sp = rp->r_sp;
 
-	n += dtrace_getustackdepth_top(&sp);
-	n += dtrace_getustack_common(NULL, 0, sp);
+	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		n++;
 
-	/*
-	 * Add one more to the stack depth if we're in an entry probe as long
-	 * as the return address is non-NULL or there are additional frames
-	 * beyond that NULL return address.
-	 */
-	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY) &&
-	    (rp->r_o7 != NULL || n != 1))
-		n++;
+		if (p->p_model == DATAMODEL_NATIVE)
+			pc = dtrace_fulword((void *)rp->r_sp);
+		else
+			pc = dtrace_fuword32((void *)rp->r_sp);
+	}
+
+	n += dtrace_getustack_common(NULL, 0, pc, sp);
 
 	return (n);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getufpstack.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 void
 dtrace_getufpstack(uint64_t *pcstack, uint64_t *fpstack, int pcstack_limit)
 {
 	klwp_t *lwp = ttolwp(curthread);
-	proc_t *p = ttoproc(curthread);
+	proc_t *p = curproc;
 	struct regs *rp;
-	uintptr_t sp;
+	uintptr_t pc, sp, oldcontext;
+	volatile uint16_t *flags =
+	    (volatile uint16_t *)&cpu_core[CPU->cpu_id].cpuc_dtrace_flags;
+	size_t s1, s2;
+
+	if (*flags & CPU_DTRACE_FAULT)
+		return;
 
 	if (pcstack_limit <= 0)
 		return;
@@ -532,68 +466,81 @@
 	if (pcstack_limit <= 0)
 		return;
 
+	pc = rp->r_pc;
+	sp = rp->r_sp;
+	oldcontext = lwp->lwp_oldcontext;
+
+	if (p->p_model == DATAMODEL_NATIVE) {
+		s1 = sizeof (struct frame) + 2 * sizeof (long);
+		s2 = s1 + sizeof (siginfo_t);
+	} else {
+		s1 = sizeof (struct frame32) + 3 * sizeof (int);
+		s2 = s1 + sizeof (siginfo32_t);
+	}
+
 	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_ENTRY)) {
+		*pcstack++ = (uint64_t)pc;
 		*fpstack++ = 0;
-		*pcstack++ = (uint64_t)rp->r_pc;
 		pcstack_limit--;
 		if (pcstack_limit <= 0)
 			return;
 
-		*fpstack++ = (uint64_t)rp->r_sp;
-		*pcstack++ = (uint64_t)rp->r_o7;
-		pcstack_limit--;
-	} else {
-		*fpstack++ = (uint64_t)rp->r_sp;
-		*pcstack++ = (uint64_t)rp->r_pc;
-		pcstack_limit--;
+		if (p->p_model == DATAMODEL_NATIVE)
+			pc = dtrace_fulword((void *)rp->r_sp);
+		else
+			pc = dtrace_fuword32((void *)rp->r_sp);
 	}
 
-	if (pcstack_limit <= 0)
-		return;
+	while (pc != 0) {
+		*pcstack++ = (uint64_t)pc;
+		*fpstack++ = sp;
+		pcstack_limit--;
+		if (pcstack_limit <= 0)
+			break;
 
-	sp = rp->r_sp;
-
-	dtrace_flush_user_windows();
+		if (sp == 0)
+			break;
 
-	if (p->p_model == DATAMODEL_NATIVE) {
-		while (pcstack_limit > 0) {
-			struct frame *fr = (struct frame *)(sp + STACK_BIAS);
-			uintptr_t pc;
+		if (oldcontext == sp + s1 || oldcontext == sp + s2) {
+			if (p->p_model == DATAMODEL_NATIVE) {
+				ucontext_t *ucp = (ucontext_t *)oldcontext;
+				greg_t *gregs = ucp->uc_mcontext.gregs;
 
-			if (sp == 0 || fr == NULL ||
-			    ((uintptr_t)&fr->fr_savpc & 3) != 0 ||
-			    ((uintptr_t)&fr->fr_savfp & 3) != 0)
-				break;
+				sp = dtrace_fulword(&gregs[REG_SP]);
+				pc = dtrace_fulword(&ucp->uc_mcontext.psw.pc);
 
-			pc = dtrace_fulword(&fr->fr_savpc);
-			sp = dtrace_fulword(&fr->fr_savfp);
-
-			if (pc == 0)
-				break;
+				oldcontext = dtrace_fulword(&ucp->uc_link);
+			} else {
+				ucontext_t *ucp = (ucontext_t *)oldcontext;
+				greg_t *gregs = ucp->uc_mcontext.gregs;
 
-			*fpstack++ = sp;
-			*pcstack++ = pc;
-			pcstack_limit--;
-		}
-	} else {
-		while (pcstack_limit > 0) {
-			struct frame32 *fr = (struct frame32 *)sp;
-			uint32_t pc;
+				sp = dtrace_fuword32(&gregs[REG_SP]);
+				pc = dtrace_fuword32(&ucp->uc_mcontext.psw.pc);
+
+				oldcontext = dtrace_fuword32(&ucp->uc_link);
+			}
+		} else {
+			if (p->p_model == DATAMODEL_NATIVE) {
+				struct frame *fr = (struct frame *)sp;
+
+				pc = dtrace_fulword(&fr->fr_savpc);
+				sp = dtrace_fulword(&fr->fr_savfp);
+			} else {
+				struct frame32 *fr = (struct frame32 *)sp;
 
-			if (sp == 0 ||
-			    ((uintptr_t)&fr->fr_savpc & 3) != 0 ||
-			    ((uintptr_t)&fr->fr_savfp & 3) != 0)
-				break;
+				pc = dtrace_fuword32(&fr->fr_savpc);
+				sp = dtrace_fuword32(&fr->fr_savfp);
+			}
+		}
 
-			pc = dtrace_fuword32(&fr->fr_savpc);
-			sp = dtrace_fuword32(&fr->fr_savfp);
-
-			if (pc == 0)
-				break;
-
-			*fpstack++ = sp;
-			*pcstack++ = pc;
-			pcstack_limit--;
+		/*
+		 * 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;
 		}
 	}
 
@@ -602,81 +549,96 @@
 		*pcstack++ = NULL;
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		-  dtrace_getarg.                                   */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
 uint64_t
 dtrace_getarg(int arg, int aframes)
 {
-	uintptr_t val;
-	struct frame *fp;
-	uint64_t rval;
+	uintptr_t rval;
+	uintptr_t *stack;
+	proc_t *p = curproc;
+	int i;
 
-	/*
-	 * Account for the fact that dtrace_getarg() consumes an additional
-	 * stack frame.
-	 */
 	aframes++;
 
-	if (arg < 6) {
-		if (dtrace_fish(aframes, DTRACE_REG_I0 + arg, &val) == 0)
-			return (val);
-	} else {
-		if (dtrace_fish(aframes, DTRACE_REG_I6, &val) == 0) {
-			/*
-			 * We have a stack pointer; grab the argument.
-			 */
-			fp = (struct frame *)(val + STACK_BIAS);
+	if (p->p_model == DATAMODEL_LP64) {
+		struct frame *fp = (struct frame *) ((caddr_t) dtrace_getfp());
+
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
 
-			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-			rval = fp->fr_argx[arg - 6];
-			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+		for (aframes -= 1; aframes; aframes--)
+			fp = (struct frame *)((caddr_t)fp->fr_savfp);
 
-			return (rval);
+		if (arg < 5) {
+			rval = fp->fr_argd[arg];
+		} else {
+			fp = (struct frame *)((caddr_t)fp->fr_savfp);
+			rval = fp->fr_argx[arg - 6];
 		}
-	}
 
-	/*
-	 * There are other ways to do this.  But the slow, painful way works
-	 * just fine.  Because this requires some loads, we need to set
-	 * CPU_DTRACE_NOFAULT to protect against looking for an argument that
-	 * isn't there.
-	 */
-	fp = (struct frame *)((caddr_t)dtrace_getfp() + STACK_BIAS);
-	dtrace_flush_windows();
+		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+	} else {
+		struct frame32 *fp = (struct frame32 *) ((caddr_t) dtrace_getfp());
 
-	DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+
+		for (aframes -= 1; aframes; aframes--) 
+			fp = (struct frame32 *)((caddr_t)fp->fr_savfp);
 
-	for (aframes -= 1; aframes; aframes--)
-		fp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS);
+		if (arg < 5) {
+			rval = fp->fr_argd[arg];
+		} else {
+			fp = (struct frame32 *)((caddr_t)fp->fr_savfp);
+			rval = fp->fr_argx[arg - 6];
+		}
 
-	if (arg < 6) {
-		rval = fp->fr_arg[arg];
-	} else {
-		fp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS);
-		rval = fp->fr_argx[arg - 6];
+		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 	}
 
-	DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-
 	return (rval);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getstackdepth.                             */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
 int
 dtrace_getstackdepth(int aframes)
 {
-	struct frame *fp, *nextfp, *minfp, *stacktop;
+	struct frame *fp = (struct frame *)dtrace_getfp();
+	struct frame *nextfp, *minfp, *stacktop;
 	int depth = 0;
 	int on_intr;
 
-	fp = (struct frame *)((caddr_t)dtrace_getfp() + STACK_BIAS);
-	dtrace_flush_windows();
-
 	if ((on_intr = CPU_ON_INTR(CPU)) != 0)
-		stacktop = (struct frame *)CPU->cpu_intr_stack + SA(MINFRAME);
+		stacktop = (struct frame *)(CPU->cpu_intr_stack + SA(MINFRAME));
 	else
 		stacktop = (struct frame *)curthread->t_stk;
 	minfp = fp;
 
+	aframes++;
+
 	for (;;) {
-		nextfp = (struct frame *)((caddr_t)fp->fr_savfp + STACK_BIAS);
+		depth++;
+
+		nextfp = (struct frame *)fp->fr_savfp;
+
 		if (nextfp <= minfp || nextfp >= stacktop) {
 			if (on_intr) {
 				/*
@@ -687,217 +649,122 @@
 				on_intr = 0;
 				continue;
 			}
-
-			return (++depth);
-		}
-
-		if (aframes > 0) {
-			aframes--;
-		} else {
-			depth++;
+			break;
 		}
 
 		fp = nextfp;
 		minfp = fp;
 	}
+
+	if (depth <= aframes)
+		return (0);
+
+	return (depth - aframes);
 }
 
-/*
- * This uses the same register numbering scheme as in sys/procfs_isa.h.
- */
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_getreg.                                    */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 ulong_t
 dtrace_getreg(struct regs *rp, uint_t reg)
 {
-	ulong_t value;
-	uintptr_t fp;
-	struct machpcb *mpcb;
-
-	if (reg == R_G0)
+	if (reg > REG_G15) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
 		return (0);
-
-	if (reg <= R_G7)
-		return ((&rp->r_g1)[reg - 1]);
-
-	if (reg > R_I7) {
-		switch (reg) {
-		case R_CCR:
-			return ((rp->r_tstate >> TSTATE_CCR_SHIFT) &
-			    TSTATE_CCR_MASK);
-		case R_PC:
-			return (rp->r_pc);
-		case R_nPC:
-			return (rp->r_npc);
-		case R_Y:
-			return (rp->r_y);
-		case R_ASI:
-			return ((rp->r_tstate >> TSTATE_ASI_SHIFT) &
-			    TSTATE_ASI_MASK);
-		case R_FPRS:
-			return (dtrace_getfprs());
-		default:
-			DTRACE_CPUFLAG_SET(CPU_DTRACE_ILLOP);
-			return (0);
-		}
-	}
-
-	/*
-	 * We reach go to the fake restore case if the probe we hit was a pid
-	 * return probe on a restore instruction. We partially emulate the
-	 * restore in the kernel and then execute a simple restore
-	 * instruction that we've secreted away to do the actual register
-	 * window manipulation. We need to go one register window further
-	 * down to get at the %ls, and %is and we need to treat %os like %is
-	 * to pull them out of the topmost user frame.
-	 */
-	if (DTRACE_CPUFLAG_ISSET(CPU_DTRACE_FAKERESTORE)) {
-		if (reg > R_O7)
-			goto fake_restore;
-		else
-			reg += R_I0 - R_O0;
-
-	} else if (reg <= R_O7) {
-		return ((&rp->r_g1)[reg - 1]);
-	}
-
-	if (dtrace_getotherwin() > 0)
-		return (dtrace_getreg_win(reg, 1));
-
-	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
-
-	if (curproc->p_model == DATAMODEL_NATIVE) {
-		struct frame *fr = (void *)(rp->r_sp + STACK_BIAS);
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp)
-					return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
-
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		value = dtrace_fulword(&fr->fr_local[reg - 16]);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-	} else {
-		struct frame32 *fr = (void *)(uintptr_t)(caddr32_t)rp->r_sp;
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp)
-					return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
-
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		value = dtrace_fuword32(&fr->fr_local[reg - 16]);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
 	}
 
-	return (value);
+	return ((&rp->r_g0)[reg]);
+}
 
-fake_restore:
-	ASSERT(R_L0 <= reg && reg <= R_I7);
+/*========================= End of Function ========================*/
 
-	/*
-	 * We first look two user windows down to see if we can dig out
-	 * the register we're looking for.
-	 */
-	if (dtrace_getotherwin() > 1)
-		return (dtrace_getreg_win(reg, 2));
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_fuword8.                                   */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
-	/*
-	 * First we need to get the frame pointer and then we perform
-	 * the same computation as in the non-fake-o-restore case.
-	 */
-
-	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
-
-	if (dtrace_getotherwin() > 0) {
-		fp = dtrace_getreg_win(R_FP, 1);
-		goto got_fp;
+uint8_t
+dtrace_fuword8(void *uaddr)
+{
+	if ((uintptr_t)uaddr >= _userlimit) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
 	}
+	return (dtrace_fuword8_nocheck(uaddr));
+}
 
-	if (curproc->p_model == DATAMODEL_NATIVE) {
-		struct frame *fr = (void *)(rp->r_sp + STACK_BIAS);
+/*========================= End of Function ========================*/
 
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) {
-					fp = rwin[i].rw_fp;
-					goto got_fp;
-				}
-			} while (i > 0);
-		}
-
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		fp = dtrace_fulword(&fr->fr_savfp);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-		if (cpu_core[CPU->cpu_id].cpuc_dtrace_flags & CPU_DTRACE_FAULT)
-			return (0);
-	} else {
-		struct frame32 *fr = (void *)(uintptr_t)(caddr32_t)rp->r_sp;
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_fuword16.                                  */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == rp->r_sp) {
-					fp = rwin[i].rw_fp;
-					goto got_fp;
-				}
-			} while (i > 0);
-		}
+uint16_t
+dtrace_fuword16(void *uaddr)
+{
+	if ((uintptr_t)uaddr >= _userlimit) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword16_nocheck(uaddr));
+}
 
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		fp = dtrace_fuword32(&fr->fr_savfp);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-		if (cpu_core[CPU->cpu_id].cpuc_dtrace_flags & CPU_DTRACE_FAULT)
-			return (0);
-	}
-got_fp:
+/*========================= End of Function ========================*/
 
-	if (curproc->p_model == DATAMODEL_NATIVE) {
-		struct frame *fr = (void *)(fp + STACK_BIAS);
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_fuword32.                                  */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == fp)
-					return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
+uint32_t
+dtrace_fuword32(void *uaddr)
+{
+	if ((uintptr_t)uaddr >= _userlimit) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
+	}
+	return (dtrace_fuword32_nocheck(uaddr));
+}
 
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		value = dtrace_fulword(&fr->fr_local[reg - 16]);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
-	} else {
-		struct frame32 *fr = (void *)(uintptr_t)(caddr32_t)fp;
+/*========================= End of Function ========================*/
 
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] == fp)
-					return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- dtrace_fuword64.                                  */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
-		DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
-		value = dtrace_fuword32(&fr->fr_local[reg - 16]);
-		DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT);
+uint64_t
+dtrace_fuword64(void *uaddr)
+{
+	if ((uintptr_t)uaddr >= _userlimit) {
+		DTRACE_CPUFLAG_SET(CPU_DTRACE_BADADDR);
+		cpu_core[CPU->cpu_id].cpuc_dtrace_illval = (uintptr_t)uaddr;
+		return (0);
 	}
+	return (dtrace_fuword64_nocheck(uaddr));
+}
 
-	return (value);
-}
+/*========================= End of Function ========================*/
--- a/usr/src/uts/zSeries/dtrace/fasttrap.conf	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/fasttrap.conf	Thu Oct 08 12:44:34 2009 -0400
@@ -23,7 +23,6 @@
 # Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"@(#)fasttrap.conf	1.3	05/06/08 SMI"
 
 name="fasttrap" parent="pseudo" instance=0;
 
--- a/usr/src/uts/zSeries/dtrace/fasttrap_isa.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/fasttrap_isa.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1,33 +1,95 @@
+/*------------------------------------------------------------------*/
+/* 								    */
+/* Name        - fasttrap_isa.					    */
+/* 								    */
+/* Function    - Process fasttrap system calls for dtrace.          */
+/* 								    */
+/* Name	       - Neale Ferguson					    */
+/* 								    */
+/* Date        - October, 2009   				    */
+/* 								    */
+/*------------------------------------------------------------------*/
+
 /*
- * CDDL HEADER START
+ * Lossless User-Land Tracing on System z
+ * --------------------------------------
  *
- * 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.
+ * The Basic Idea
+ *
+ * The most important design constraint is, of course, correct execution of
+ * the user thread above all else. The next most important goal is rapid
+ * execution. We combine execution of instructions in user-land with
+ * emulation of certain instructions in the kernel to aim for complete
+ * correctness and maximal performance.
+ *
+ * The execution of most instructions is not dependent on the address; for
+ * these instructions it is sufficient to copy them into the user process's
+ * address space and execute them. To effectively single-step an instruction
+ * in user-land, we copy out the following sequence of instructions to scratch
+ * space in the user thread's ulwp_t structure.
  *
- * 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.
+ * We then set the program counter to point to this scratch space
+ * Once execution resumes, the original instruction is executed and
+ * then control flow is redirected to what was originally the subsequent
+ * instruction. If the kernel attemps to deliver a signal while single-
+ * stepping, the signal is deferred and the program counter is moved into the
+ * second sequence of instructions. The second sequence ends in a trap into
+ * the kernel where the deferred signal is then properly handled and delivered.
+ *
+ * For instructions whose execute is position dependent, we perform 
+ * more complex operations as explained in the code.
  *
- * 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
+ */
+
+/*------------------------------------------------------------------*/
+/*                   L I C E N S E                                  */
+/*------------------------------------------------------------------*/
+
+/*==================================================================*/
+/* 								    */
+/* 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 the 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 2008 Sine Nomine Associates.                           */
+/* Copyright 2009 Sine Nomine Associates.                           */
 /* All rights reserved.                                             */
 /* Use is subject to license terms.                                 */
- */
+/* 								    */
+/* Copyright 2005 Sun Microsystems, Inc.  All rights reserved.	    */
+/* Use is subject to license terms.				    */
+/* 								    */
+/*==================================================================*/
+
+/*------------------------------------------------------------------*/
+/*                 D e f i n e s                                    */
+/*------------------------------------------------------------------*/
 
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
+#define JGOP1		0xc0
+#define JGOP2		0x4
+#define UNC		0xf
+
+/*========================= End of Defines =========================*/
+
+/*------------------------------------------------------------------*/
+/*                 I n c l u d e s                                  */
+/*------------------------------------------------------------------*/
 
 #include <sys/fasttrap_isa.h>
 #include <sys/fasttrap_impl.h>
@@ -38,165 +100,44 @@
 #include <sys/stack.h>
 #include <sys/sysmacros.h>
 #include <sys/trap.h>
+#include <sys/privregs.h>
+#include <dis_tables.h>
 
-#include <v9/sys/machpcb.h>
-#include <v9/sys/privregs.h>
+/*========================= End of Includes ========================*/
+
+/*------------------------------------------------------------------*/
+/*                 T y p e d e f s                                  */
+/*------------------------------------------------------------------*/
+
+
+/*========================= End of Typedefs ========================*/
+
+/*------------------------------------------------------------------*/
+/*                E x t e r n a l   R e f e r e n c e s             */
+/*------------------------------------------------------------------*/
+
+
+/*=================== End of External References ===================*/
 
-/*
- * Lossless User-Land Tracing on SPARC
- * -----------------------------------
- *
- * The Basic Idea
- *
- * The most important design constraint is, of course, correct execution of
- * the user thread above all else. The next most important goal is rapid
- * execution. We combine execution of instructions in user-land with
- * emulation of certain instructions in the kernel to aim for complete
- * correctness and maximal performance.
- *
- * We take advantage of the split PC/NPC architecture to speed up logical
- * single-stepping; when we copy an instruction out to the scratch space in
- * the ulwp_t structure (held in the %g7 register on SPARC), we can
- * effectively single step by setting the PC to our scratch space and leaving
- * the NPC alone. This executes the replaced instruction and then continues
- * on without having to reenter the kernel as with single- stepping. The
- * obvious caveat is for instructions whose execution is PC dependant --
- * branches, call and link instructions (call and jmpl), and the rdpc
- * instruction. These instructions cannot be executed in the manner described
- * so they must be emulated in the kernel.
- *
- * Emulation for this small set of instructions if fairly simple; the most
- * difficult part being emulating branch conditions.
- *
- *
- * A Cache Heavy Portfolio
- *
- * It's important to note at this time that copying an instruction out to the
- * ulwp_t scratch space in user-land is rather complicated. SPARC has
- * separate data and instruction caches so any writes to the D$ (using a
- * store instruction for example) aren't necessarily reflected in the I$.
- * The flush instruction can be used to synchronize the two and must be used
- * for any self-modifying code, but the flush instruction only applies to the
- * primary address space (the absence of a flusha analogue to the flush
- * instruction that accepts an ASI argument is an obvious omission from SPARC
- * v9 where the notion of the alternate address space was introduced on
- * SPARC). To correctly copy out the instruction we must use a block store
- * that doesn't allocate in the D$ and ensures synchronization with the I$;
- * see dtrace_blksuword32() for the implementation  (this function uses
- * ASI_BLK_COMMIT_S to write a block through the secondary ASI in the manner
- * described). Refer to the UltraSPARC I/II manual for details on the
- * ASI_BLK_COMMIT_S ASI.
- *
- *
- * Return Subtleties
- *
- * When we're firing a return probe we need to expose the value returned by
- * the function being traced. Since the function can set the return value
- * in its last instruction, we need to fire the return probe only _after_
- * the effects of the instruction are apparent. For instructions that we
- * emulate, we can call dtrace_probe() after we've performed the emulation;
- * for instructions that we execute after we return to user-land, we set
- * %pc to the instruction we copied out (as described above) and set %npc
- * to a trap instruction stashed in the ulwp_t structure. After the traced
- * instruction is executed, the trap instruction returns control to the
- * kernel where we can fire the return probe.
- *
- * This need for a second trap in cases where we execute the traced
- * instruction makes it all the more important to emulate the most common
- * instructions to avoid the second trip in and out of the kernel.
- *
- *
- * Making it Fast
- *
- * Since copying out an instruction is neither simple nor inexpensive for the
- * CPU, we should attempt to avoid doing it in as many cases as possible.
- * Since function entry and return are usually the most interesting probe
- * sites, we attempt to tune the performance of the fasttrap provider around
- * instructions typically in those places.
- *
- * Looking at a bunch of functions in libraries and executables reveals that
- * most functions begin with either a save or a sethi (to setup a larger
- * argument to the save) and end with a restore or an or (in the case of leaf
- * functions). To try to improve performance, we emulate all of these
- * instructions in the kernel.
- *
- * The save and restore instructions are a little tricky since they perform
- * register window maniplulation. Rather than trying to tinker with the
- * register windows from the kernel, we emulate the implicit add that takes
- * place as part of those instructions and set the %pc to point to a simple
- * save or restore we've hidden in the ulwp_t structure. If we're in a return
- * probe so want to make it seem as though the tracepoint has been completely
- * executed we need to remember that we've pulled this trick with restore and
- * pull registers from the previous window (the one that we'll switch to once
- * the simple store instruction is executed) rather than the current one. This
- * is why in the case of emulating a restore we set the DTrace CPU flag
- * CPU_DTRACE_FAKERESTORE before calling dtrace_probe() for the return probes
- * (see fasttrap_return_common()).
- */
+/*------------------------------------------------------------------*/
+/*                   P r o t o t y p e s                            */
+/*------------------------------------------------------------------*/
+
+/*========================= End of Prototypes ======================*/
+
+/*------------------------------------------------------------------*/
+/*                 G l o b a l   V a r i a b l e s                  */
+/*------------------------------------------------------------------*/
 
-#define	OP(x)		((x) >> 30)
-#define	OP2(x)		(((x) >> 22) & 0x07)
-#define	OP3(x)		(((x) >> 19) & 0x3f)
-#define	RCOND(x)	(((x) >> 25) & 0x07)
-#define	COND(x)		(((x) >> 25) & 0x0f)
-#define	A(x)		(((x) >> 29) & 0x01)
-#define	I(x)		(((x) >> 13) & 0x01)
-#define	RD(x)		(((x) >> 25) & 0x1f)
-#define	RS1(x)		(((x) >> 14) & 0x1f)
-#define	RS2(x)		(((x) >> 0) & 0x1f)
-#define	CC(x)		(((x) >> 20) & 0x03)
-#define	DISP16(x)	((((x) >> 6) & 0xc000) | ((x) & 0x3fff))
-#define	DISP22(x)	((x) & 0x3fffff)
-#define	DISP19(x)	((x) & 0x7ffff)
-#define	DISP30(x)	((x) & 0x3fffffff)
-#define	SW_TRAP(x)	((x) & 0x7f)
-
-#define	OP3_OR		0x02
-#define	OP3_RD		0x28
-#define	OP3_JMPL	0x38
-#define	OP3_RETURN	0x39
-#define	OP3_TCC		0x3a
-#define	OP3_SAVE	0x3c
-#define	OP3_RESTORE	0x3d
-
-#define	OP3_PREFETCH	0x2d
-#define	OP3_CASA	0x3c
-#define	OP3_PREFETCHA	0x3d
-#define	OP3_CASXA	0x3e
+/*====================== End of Global Variables ===================*/
 
-#define	OP2_ILLTRAP	0x0
-#define	OP2_BPcc	0x1
-#define	OP2_Bicc	0x2
-#define	OP2_BPr		0x3
-#define	OP2_SETHI	0x4
-#define	OP2_FBPfcc	0x5
-#define	OP2_FBfcc	0x6
-
-#define	R_G0		0
-#define	R_O0		8
-#define	R_SP		14
-#define	R_I0		24
-#define	R_I1		25
-#define	R_I2		26
-#define	R_I3		27
-
-/*
- * Check the comment in fasttrap.h when changing these offsets or adding
- * new instructions.
- */
-#define	FASTTRAP_OFF_SAVE	64
-#define	FASTTRAP_OFF_RESTORE	68
-#define	FASTTRAP_OFF_FTRET	72
-#define	FASTTRAP_OFF_RETURN	76
-
-#define	BREAKPOINT_INSTR	0x91d02001	/* ta 1 */
-
-/*
- * Tunable to let users turn off the fancy save instruction optimization.
- * If a program is non-ABI compliant, there's a possibility that the save
- * instruction optimization could cause an error.
- */
-int fasttrap_optimize_save = 1;
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_anarg.                                   */
+/*                                                                  */
+/* Function	- Retrieve an argument from the stack.              */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 static uint64_t
 fasttrap_anarg(struct regs *rp, int argno)
@@ -204,7 +145,7 @@
 	uint64_t value;
 
 	if (argno < 6)
-		return ((&rp->r_o0)[argno]);
+		return ((&rp->r_g2)[argno]);
 
 	if (curproc->p_model == DATAMODEL_NATIVE) {
 		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
@@ -225,20 +166,16 @@
 	return (value);
 }
 
-static ulong_t fasttrap_getreg(struct regs *, uint_t);
-static void fasttrap_putreg(struct regs *, uint_t, ulong_t);
+
+/*========================= End of Function ========================*/
 
-int
-fasttrap_probe(struct regs *rp)
-{
-	dtrace_probe(fasttrap_probe_id,
-	    rp->r_o0, rp->r_o1, rp->r_o2, rp->r_o3, rp->r_o4);
-
-	rp->r_pc = rp->r_npc;
-	rp->r_npc = rp->r_pc + 4;
-
-	return (0);
-}
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_usdt_args.                               */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 static void
 fasttrap_usdt_args(fasttrap_probe_t *probe, struct regs *rp, int argc,
@@ -247,14 +184,14 @@
 	int i, x, cap = MIN(argc, probe->ftp_nargs);
 
 	if (curproc->p_model == DATAMODEL_NATIVE) {
-		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
+		struct frame *fr = (struct frame *)rp->r_sp;
 		uintptr_t v;
 
 		for (i = 0; i < cap; i++) {
 			x = probe->ftp_argmap[i];
 
-			if (x < 6)
-				argv[i] = (&rp->r_o0)[x];
+			if (x < 5)
+				argv[i] = (&rp->r_g2)[x];
 			else if (fasttrap_fulword(&fr->fr_argd[x], &v) != 0)
 				argv[i] = 0;
 		}
@@ -266,8 +203,8 @@
 		for (i = 0; i < cap; i++) {
 			x = probe->ftp_argmap[i];
 
-			if (x < 6)
-				argv[i] = (&rp->r_o0)[x];
+			if (x < 5)
+				argv[i] = (&rp->r_g2)[x];
 			else if (fasttrap_fuword32(&fr->fr_argd[x], &v) != 0)
 				argv[i] = 0;
 		}
@@ -278,15 +215,28 @@
 	}
 }
 
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_return_common.                           */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 static void
-fasttrap_return_common(struct regs *rp, uintptr_t pc, pid_t pid,
-    uint_t fake_restore)
+fasttrap_return_common(struct regs *rp, uintptr_t pc, pid_t pid)
 {
 	fasttrap_tracepoint_t *tp;
 	fasttrap_bucket_t *bucket;
 	fasttrap_id_t *id;
 	kmutex_t *pid_mtx;
 	dtrace_icookie_t cookie;
+	kthread_t *thrp = curthread;
+	proc_t *p = curproc;
+	uint8_t *scratch;
 
 	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
 	mutex_enter(pid_mtx);
@@ -294,7 +244,7 @@
 
 	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
 		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
-		    !tp->ftt_proc->ftpc_defunct)
+		    tp->ftt_proc->ftpc_acount != 0)
 			break;
 	}
 
@@ -308,82 +258,56 @@
 		return;
 	}
 
-	for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
-		fasttrap_probe_t *probe = id->fti_probe;
-
-		if (probe->ftp_type == DTFTP_POST_OFFSETS) {
-			if (probe->ftp_argmap == NULL) {
-				dtrace_probe(probe->ftp_id, rp->r_o0, rp->r_o1,
-				    rp->r_o2, rp->r_o3, rp->r_o4);
-			} else {
-				uintptr_t t[5];
-
-				fasttrap_usdt_args(probe, rp,
-				    sizeof (t) / sizeof (t[0]), t);
+	if (p->p_model == DATAMODEL_LP64) {
+		scratch = (uint8_t *)((uintptr_t) rp->r_a0 << 32 | rp->r_a1);
+	} else {
+		scratch = (uint8_t *) rp->r_a0;
+	}
 
-				dtrace_probe(probe->ftp_id, t[0], t[1],
-				    t[2], t[3], t[4]);
-			}
-			continue;
-		}
+	thrp->t_dtrace_pc    = pc;
+	thrp->t_dtrace_scrpc = (uintptr_t) scratch;
+	thrp->t_dtrace_npc   = pc + tp->ftt_isize;
+	thrp->t_dtrace_astpc = (uintptr_t) scratch + tp->ftt_isize;
+	thrp->t_dtrace_on    = 1;
 
-		/*
-		 * If this is only a possible return point, we must
-		 * be looking at a potential tail call in leaf context.
-		 * If the %npc is still within this function, then we
-		 * must have misidentified a jmpl as a tail-call when it
-		 * is, in fact, part of a jump table. It would be nice to
-		 * remove this tracepoint, but this is neither the time
-		 * nor the place.
-		 */
-		if ((tp->ftt_flags & FASTTRAP_F_RETMAYBE) &&
-		    rp->r_npc - probe->ftp_faddr < probe->ftp_fsize)
-			continue;
+	if (fasttrap_copyout(scratch, (char *)tp->ftt_instr, tp->ftt_size)) {
+		fasttrap_sigtrap(p, thrp, pc);
+		rp->r_pc = pc;
+	} else {
 
-		/*
-		 * It's possible for a function to branch to the delay slot
-		 * of an instruction that we've identified as a return site.
-		 * We can dectect this spurious return probe activation by
-		 * observing that in this case %npc will be %pc + 4 and %npc
-		 * will be inside the current function (unless the user is
-		 * doing _crazy_ instruction picking in which case there's
-		 * very little we can do). The second check is important
-		 * in case the last instructions of a function make a tail-
-		 * call to the function located immediately subsequent.
-		 */
-		if (rp->r_npc == rp->r_pc + 4 &&
-		    rp->r_npc - probe->ftp_faddr < probe->ftp_fsize)
-			continue;
-
-		/*
-		 * The first argument is the offset of return tracepoint
-		 * in the function; the remaining arguments are the return
-		 * values.
-		 *
-		 * If fake_restore is set, we need to pull the return values
-		 * out of the %i's rather than the %o's -- a little trickier.
-		 */
-		if (!fake_restore) {
-			dtrace_probe(probe->ftp_id, pc - probe->ftp_faddr,
-			    rp->r_o0, rp->r_o1, rp->r_o2, rp->r_o3);
+		if (tp->ftt_retids != NULL) {
+			thrp->t_dtrace_step = 1;
+			thrp->t_dtrace_ret  = 1;
+			rp->r_pc = thrp->t_dtrace_astpc;
 		} else {
-			uintptr_t arg0 = fasttrap_getreg(rp, R_I0);
-			uintptr_t arg1 = fasttrap_getreg(rp, R_I1);
-			uintptr_t arg2 = fasttrap_getreg(rp, R_I2);
-			uintptr_t arg3 = fasttrap_getreg(rp, R_I3);
-
-			cookie = dtrace_interrupt_disable();
-			DTRACE_CPUFLAG_SET(CPU_DTRACE_FAKERESTORE);
-			dtrace_probe(probe->ftp_id, pc - probe->ftp_faddr,
-			    arg0, arg1, arg2, arg3);
-			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_FAKERESTORE);
-			dtrace_interrupt_enable(cookie);
+			rp->r_pc = thrp->t_dtrace_scrpc;
+		}
+		
+		for (id = tp->ftt_retids; id != NULL; id = id->fti_next) {
+			/*
+			 * The first argument is the offset of return tracepoint
+			 * in the function; the remaining arguments are the return
+			 * values.
+			 */
+			dtrace_probe(id->fti_probe->ftp_id, 
+				     pc - id->fti_probe->ftp_faddr,
+				     rp->r_g2, rp->r_g3, rp->r_g4, rp->r_g5);
 		}
 	}
 
 	mutex_exit(pid_mtx);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_pid_probe.                               */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 fasttrap_pid_probe(struct regs *rp)
 {
@@ -391,13 +315,12 @@
 	fasttrap_tracepoint_t *tp, tp_local;
 	fasttrap_id_t *id;
 	pid_t pid;
-	uintptr_t pc = rp->r_pc;
-	uintptr_t npc = rp->r_npc;
+	uintptr_t pc      = rp->r_pc;
 	uintptr_t orig_pc = pc;
 	fasttrap_bucket_t *bucket;
 	kmutex_t *pid_mtx;
-	uint_t fake_restore = 0;
 	dtrace_icookie_t cookie;
+	kthread_t *thrp = curthread;
 
 	/*
 	 * It's possible that a user (in a veritable orgy of bad planning)
@@ -405,20 +328,17 @@
 	 * return probe fasttrap. In this case we need to kill the process
 	 * since it's in a unrecoverable state.
 	 */
-	if (curthread->t_dtrace_step) {
-		ASSERT(curthread->t_dtrace_on);
-		fasttrap_sigtrap(p, curthread, pc);
+	if (thrp->t_dtrace_step) {
+		ASSERT(thrp->t_dtrace_on);
+		fasttrap_sigtrap(p, thrp, pc);
 		return (0);
 	}
 
 	/*
 	 * Clear all user tracing flags.
 	 */
-	curthread->t_dtrace_ft = 0;
-	curthread->t_dtrace_pc = 0;
-	curthread->t_dtrace_npc = 0;
-	curthread->t_dtrace_scrpc = 0;
-	curthread->t_dtrace_astpc = 0;
+	thrp->t_dtrace_ft    = 0;
+	thrp->t_dtrace_pc    = 0;
 
 	/*
 	 * Treat a child created by a call to vfork(2) as if it were its
@@ -429,17 +349,17 @@
 		p = p->p_parent;
 	}
 
-	pid = p->p_pid;
+	pid     = p->p_pid;
 	pid_mtx = &cpu_core[CPU->cpu_id].cpuc_pid_lock;
 	mutex_enter(pid_mtx);
-	bucket = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
+	bucket  = &fasttrap_tpoints.fth_table[FASTTRAP_TPOINTS_INDEX(pid, pc)];
 
 	/*
 	 * Lookup the tracepoint that the process just hit.
 	 */
 	for (tp = bucket->ftb_data; tp != NULL; tp = tp->ftt_next) {
 		if (pid == tp->ftt_pid && pc == tp->ftt_pc &&
-		    !tp->ftt_proc->ftpc_defunct)
+		    tp->ftt_proc->ftpc_acount != 0)
 			break;
 	}
 
@@ -460,12 +380,12 @@
 		 * We note that this was an entry probe to help ustack() find
 		 * the first caller.
 		 */
-		if ((isentry = (probe->ftp_type == DTFTP_ENTRY)) != 0) {
+		if ((isentry = (id->fti_ptype == DTFTP_ENTRY)) != 0) {
 			cookie = dtrace_interrupt_disable();
 			DTRACE_CPUFLAG_SET(CPU_DTRACE_ENTRY);
 		}
-		dtrace_probe(probe->ftp_id, rp->r_o0, rp->r_o1, rp->r_o2,
-		    rp->r_o3, rp->r_o4);
+		dtrace_probe(probe->ftp_id, rp->r_g2, rp->r_g3, rp->r_g4,
+		    rp->r_g5, rp->r_g6);
 		if (isentry) {
 			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_ENTRY);
 			dtrace_interrupt_enable(cookie);
@@ -482,497 +402,41 @@
 	tp = &tp_local;
 
 	/*
-	 * We emulate certain types of instructions do ensure correctness
-	 * (in the case of position dependent instructions) or optimize
-	 * common cases. The rest we have the thread execute back in user-
-	 * land.
-	 */
-	switch (tp->ftt_type) {
-	case FASTTRAP_T_SAVE:
-	{
-		int32_t imm;
-
-		/*
-		 * This an optimization to let us handle function entry
-		 * probes more efficiently. Many functions begin with a save
-		 * instruction that follows the pattern:
-		 *	save	%sp, <imm>, %sp
-		 *
-		 * Meanwhile, we've stashed the instruction:
-		 *	save	%g1, %g0, %sp
-		 *
-		 * off of %g7, so all we have to do is stick the right value
-		 * into %g1 and reset %pc to point to the instruction we've
-		 * cleverly hidden (%npc should not be touched).
-		 */
-
-		imm = tp->ftt_instr << 19;
-		imm >>= 19;
-		rp->r_g1 = rp->r_sp + imm;
-		pc = rp->r_g7 + FASTTRAP_OFF_SAVE;
-		break;
-	}
-
-	case FASTTRAP_T_RESTORE:
-	{
-		ulong_t value;
-		uint_t rd;
-
-		/*
-		 * This is an optimization to let us handle function
-		 * return probes more efficiently. Most non-leaf functions
-		 * end with the sequence:
-		 *	ret
-		 *	restore	<reg>, <reg_or_imm>, %oX
-		 *
-		 * We've stashed the instruction:
-		 *	restore	%g0, %g0, %g0
-		 *
-		 * off of %g7 so we just need to place the correct value
-		 * in the right %i register (since after our fake-o
-		 * restore, the %i's will become the %o's) and set the %pc
-		 * to point to our hidden restore. We also set fake_restore to
-		 * let fasttrap_return_common() know that it will find the
-		 * return values in the %i's rather than the %o's.
-		 */
-
-		if (I(tp->ftt_instr)) {
-			int32_t imm;
-
-			imm = tp->ftt_instr << 19;
-			imm >>= 19;
-			value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + imm;
-		} else {
-			value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) +
-			    fasttrap_getreg(rp, RS2(tp->ftt_instr));
-		}
-
-		/*
-		 * Convert %o's to %i's; leave %g's as they are.
-		 */
-		rd = RD(tp->ftt_instr);
-		fasttrap_putreg(rp, ((rd & 0x18) == 0x8) ? rd + 16 : rd, value);
-
-		pc = rp->r_g7 + FASTTRAP_OFF_RESTORE;
-		fake_restore = 1;
-		break;
-	}
-
-	case FASTTRAP_T_RETURN:
-	{
-		uintptr_t target;
-
-		/*
-		 * A return instruction is like a jmpl (without the link
-		 * part) that executes an implicit restore. We've stashed
-		 * the instruction:
-		 *	return %o0
-		 *
-		 * off of %g7 so we just need to place the target in %o0
-		 * and set the %pc to point to the stashed return instruction.
-		 * We use %o0 since that register disappears after the return
-		 * executes, erasing any evidence of this tampering.
-		 */
-		if (I(tp->ftt_instr)) {
-			int32_t imm;
-
-			imm = tp->ftt_instr << 19;
-			imm >>= 19;
-			target = fasttrap_getreg(rp, RS1(tp->ftt_instr)) + imm;
-		} else {
-			target = fasttrap_getreg(rp, RS1(tp->ftt_instr)) +
-			    fasttrap_getreg(rp, RS2(tp->ftt_instr));
-		}
-
-		fasttrap_putreg(rp, R_O0, target);
-
-		pc = rp->r_g7 + FASTTRAP_OFF_RETURN;
-		fake_restore = 1;
-		break;
-	}
-
-	case FASTTRAP_T_OR:
-	{
-		ulong_t value;
-
-		if (I(tp->ftt_instr)) {
-			int32_t imm;
-
-			imm = tp->ftt_instr << 19;
-			imm >>= 19;
-			value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) | imm;
-		} else {
-			value = fasttrap_getreg(rp, RS1(tp->ftt_instr)) |
-			    fasttrap_getreg(rp, RS2(tp->ftt_instr));
-		}
-
-		fasttrap_putreg(rp, RD(tp->ftt_instr), value);
-		pc = rp->r_npc;
-		npc = pc + 4;
-		break;
-	}
-
-	case FASTTRAP_T_SETHI:
-		if (RD(tp->ftt_instr) != R_G0) {
-			uint32_t imm32 = tp->ftt_instr << 10;
-			fasttrap_putreg(rp, RD(tp->ftt_instr), (ulong_t)imm32);
-		}
-		pc = rp->r_npc;
-		npc = pc + 4;
-		break;
-
-	case FASTTRAP_T_CCR:
-	{
-		uint_t c, v, z, n, taken;
-		uint_t ccr = rp->r_tstate >> TSTATE_CCR_SHIFT;
-
-		if (tp->ftt_cc != 0)
-			ccr >>= 4;
-
-		c = (ccr >> 0) & 1;
-		v = (ccr >> 1) & 1;
-		z = (ccr >> 2) & 1;
-		n = (ccr >> 3) & 1;
-
-		switch (tp->ftt_code) {
-		case 0x0:	/* BN */
-			taken = 0;		break;
-		case 0x1:	/* BE */
-			taken = z;		break;
-		case 0x2:	/* BLE */
-			taken = z | (n ^ v);	break;
-		case 0x3:	/* BL */
-			taken = n ^ v;		break;
-		case 0x4:	/* BLEU */
-			taken = c | z;		break;
-		case 0x5:	/* BCS (BLU) */
-			taken = c;		break;
-		case 0x6:	/* BNEG */
-			taken = n;		break;
-		case 0x7:	/* BVS */
-			taken = v;		break;
-		case 0x8:	/* BA */
-			/*
-			 * We handle the BA case differently since the annul
-			 * bit means something slightly different.
-			 */
-			panic("fasttrap: mishandled a branch");
-			taken = 1;		break;
-		case 0x9:	/* BNE */
-			taken = ~z;		break;
-		case 0xa:	/* BG */
-			taken = ~(z | (n ^ v));	break;
-		case 0xb:	/* BGE */
-			taken = ~(n ^ v);	break;
-		case 0xc:	/* BGU */
-			taken = ~(c | z);	break;
-		case 0xd:	/* BCC (BGEU) */
-			taken = ~c;		break;
-		case 0xe:	/* BPOS */
-			taken = ~n;		break;
-		case 0xf:	/* BVC */
-			taken = ~v;		break;
-		}
-
-		if (taken & 1) {
-			pc = rp->r_npc;
-			npc = tp->ftt_dest;
-		} else if (tp->ftt_flags & FASTTRAP_F_ANNUL) {
-			/*
-			 * Untaken annulled branches don't execute the
-			 * instruction in the delay slot.
-			 */
-			pc = rp->r_npc + 4;
-			npc = pc + 4;
-		} else {
-			pc = rp->r_npc;
-			npc = pc + 4;
-		}
-		break;
-	}
-
-	case FASTTRAP_T_FCC:
-	{
-		uint_t fcc;
-		uint_t taken;
-		uint64_t fsr;
-
-		dtrace_getfsr(&fsr);
-
-		if (tp->ftt_cc == 0) {
-			fcc = (fsr >> 10) & 0x3;
-		} else {
-			uint_t shift;
-			ASSERT(tp->ftt_cc <= 3);
-			shift = 30 + tp->ftt_cc * 2;
-			fcc = (fsr >> shift) & 0x3;
-		}
-
-		switch (tp->ftt_code) {
-		case 0x0:	/* FBN */
-			taken = (1 << fcc) & (0|0|0|0);	break;
-		case 0x1:	/* FBNE */
-			taken = (1 << fcc) & (8|4|2|0);	break;
-		case 0x2:	/* FBLG */
-			taken = (1 << fcc) & (0|4|2|0);	break;
-		case 0x3:	/* FBUL */
-			taken = (1 << fcc) & (8|0|2|0);	break;
-		case 0x4:	/* FBL */
-			taken = (1 << fcc) & (0|0|2|0);	break;
-		case 0x5:	/* FBUG */
-			taken = (1 << fcc) & (8|4|0|0);	break;
-		case 0x6:	/* FBG */
-			taken = (1 << fcc) & (0|4|0|0);	break;
-		case 0x7:	/* FBU */
-			taken = (1 << fcc) & (8|0|0|0);	break;
-		case 0x8:	/* FBA */
-			/*
-			 * We handle the FBA case differently since the annul
-			 * bit means something slightly different.
-			 */
-			panic("fasttrap: mishandled a branch");
-			taken = (1 << fcc) & (8|4|2|1);	break;
-		case 0x9:	/* FBE */
-			taken = (1 << fcc) & (0|0|0|1);	break;
-		case 0xa:	/* FBUE */
-			taken = (1 << fcc) & (8|0|0|1);	break;
-		case 0xb:	/* FBGE */
-			taken = (1 << fcc) & (0|4|0|1);	break;
-		case 0xc:	/* FBUGE */
-			taken = (1 << fcc) & (8|4|0|1);	break;
-		case 0xd:	/* FBLE */
-			taken = (1 << fcc) & (0|0|2|1);	break;
-		case 0xe:	/* FBULE */
-			taken = (1 << fcc) & (8|0|2|1);	break;
-		case 0xf:	/* FBO */
-			taken = (1 << fcc) & (0|4|2|1);	break;
-		}
-
-		if (taken) {
-			pc = rp->r_npc;
-			npc = tp->ftt_dest;
-		} else if (tp->ftt_flags & FASTTRAP_F_ANNUL) {
-			/*
-			 * Untaken annulled branches don't execute the
-			 * instruction in the delay slot.
-			 */
-			pc = rp->r_npc + 4;
-			npc = pc + 4;
-		} else {
-			pc = rp->r_npc;
-			npc = pc + 4;
-		}
-		break;
-	}
-
-	case FASTTRAP_T_REG:
-	{
-		uint64_t value;
-		uint_t taken;
-		uint_t reg = RS1(tp->ftt_instr);
-
-		/*
-		 * An ILP32 process shouldn't be using a branch predicated on
-		 * an %i or an %l since it would violate the ABI. It's a
-		 * violation of the ABI because we can't ensure deterministic
-		 * behavior. We should have identified this case when we
-		 * enabled the probe.
-		 */
-		ASSERT(p->p_model == DATAMODEL_LP64 || reg < 16);
-
-		value = fasttrap_getreg(rp, reg);
-
-		switch (tp->ftt_code) {
-		case 0x1:	/* BRZ */
-			taken = (value == 0);	break;
-		case 0x2:	/* BRLEZ */
-			taken = (value <= 0);	break;
-		case 0x3:	/* BRLZ */
-			taken = (value < 0);	break;
-		case 0x5:	/* BRNZ */
-			taken = (value != 0);	break;
-		case 0x6:	/* BRGZ */
-			taken = (value > 0);	break;
-		case 0x7:	/* BRGEZ */
-			taken = (value <= 0);	break;
-		default:
-		case 0x0:
-		case 0x4:
-			panic("fasttrap: mishandled a branch");
-		}
-
-		if (taken) {
-			pc = rp->r_npc;
-			npc = tp->ftt_dest;
-		} else if (tp->ftt_flags & FASTTRAP_F_ANNUL) {
-			/*
-			 * Untaken annulled branches don't execute the
-			 * instruction in the delay slot.
-			 */
-			pc = rp->r_npc + 4;
-			npc = pc + 4;
-		} else {
-			pc = rp->r_npc;
-			npc = pc + 4;
-		}
-		break;
-	}
-
-	case FASTTRAP_T_ALWAYS:
-		/*
-		 * BAs, BA,As...
-		 */
-
-		if (tp->ftt_flags & FASTTRAP_F_ANNUL) {
-			/*
-			 * Annulled branch always instructions never execute
-			 * the instruction in the delay slot.
-			 */
-			pc = tp->ftt_dest;
-			npc = tp->ftt_dest + 4;
-		} else {
-			pc = rp->r_npc;
-			npc = tp->ftt_dest;
-		}
-		break;
-
-	case FASTTRAP_T_RDPC:
-		fasttrap_putreg(rp, RD(tp->ftt_instr), rp->r_pc);
-		pc = rp->r_npc;
-		npc = pc + 4;
-		break;
-
-	case FASTTRAP_T_CALL:
-		/*
-		 * It's a call _and_ link remember...
-		 */
-		rp->r_o7 = rp->r_pc;
-		pc = rp->r_npc;
-		npc = tp->ftt_dest;
-		break;
-
-	case FASTTRAP_T_JMPL:
-		pc = rp->r_npc;
-
-		if (I(tp->ftt_instr)) {
-			uint_t rs1 = RS1(tp->ftt_instr);
-			int32_t imm;
-
-			imm = tp->ftt_instr << 19;
-			imm >>= 19;
-			npc = fasttrap_getreg(rp, rs1) + imm;
-		} else {
-			uint_t rs1 = RS1(tp->ftt_instr);
-			uint_t rs2 = RS2(tp->ftt_instr);
-
-			npc = fasttrap_getreg(rp, rs1) +
-			    fasttrap_getreg(rp, rs2);
-		}
-
-		/*
-		 * Do the link part of the jump-and-link instruction.
-		 */
-		fasttrap_putreg(rp, RD(tp->ftt_instr), rp->r_pc);
-
-		break;
-
-	case FASTTRAP_T_COMMON:
-	{
-		curthread->t_dtrace_scrpc = rp->r_g7;
-		curthread->t_dtrace_astpc = rp->r_g7 + FASTTRAP_OFF_FTRET;
-
-		/*
-		 * Copy the instruction to a reserved location in the
-		 * user-land thread structure, then set the PC to that
-		 * location and leave the NPC alone. We take pains to ensure
-		 * consistency in the instruction stream (See SPARC
-		 * Architecture Manual Version 9, sections 8.4.7, A.20, and
-		 * H.1.6; UltraSPARC I/II User's Manual, sections 3.1.1.1,
-		 * and 13.6.4) by using the ASI ASI_BLK_COMMIT_S to copy the
-		 * instruction into the user's address space without
-		 * bypassing the I$. There's no AS_USER version of this ASI
-		 * (as exist for other ASIs) so we use the lofault
-		 * mechanism to catch faults.
-		 */
-		if (dtrace_blksuword32(rp->r_g7, &tp->ftt_instr, 1) == -1) {
-			/*
-			 * If the copyout fails, then the process's state
-			 * is not consistent (the effects of the traced
-			 * instruction will never be seen). This process
-			 * cannot be allowed to continue execution.
-			 */
-			fasttrap_sigtrap(curproc, curthread, pc);
-			return (0);
-		}
-
-		curthread->t_dtrace_pc = pc;
-		curthread->t_dtrace_npc = npc;
-		curthread->t_dtrace_on = 1;
-
-		pc = curthread->t_dtrace_scrpc;
-
-		if (tp->ftt_retids != NULL) {
-			curthread->t_dtrace_step = 1;
-			curthread->t_dtrace_ret = 1;
-			npc = curthread->t_dtrace_astpc;
-		}
-		break;
-	}
-
-	default:
-		panic("fasttrap: mishandled an instruction");
-	}
-
-	/*
-	 * This bit me in the ass a couple of times, so lets toss this
-	 * in as a cursory sanity check.
-	 */
-	ASSERT(pc != rp->r_g7 + 4);
-	ASSERT(pc != rp->r_g7 + 8);
-
-	/*
 	 * If there were no return probes when we first found the tracepoint,
 	 * we should feel no obligation to honor any return probes that were
 	 * subsequently enabled -- they'll just have to wait until the next
 	 * time around.
 	 */
 	if (tp->ftt_retids != NULL) {
-		/*
-		 * We need to wait until the results of the instruction are
-		 * apparent before invoking any return probes. If this
-		 * instruction was emulated we can just call
-		 * fasttrap_return_common(); if it needs to be executed, we
-		 * need to wait until we return to the kernel.
-		 */
-		if (tp->ftt_type != FASTTRAP_T_COMMON) {
-			fasttrap_return_common(rp, orig_pc, pid, fake_restore);
-		} else {
-			ASSERT(curthread->t_dtrace_ret != 0);
-			ASSERT(curthread->t_dtrace_pc == orig_pc);
-			ASSERT(curthread->t_dtrace_scrpc == rp->r_g7);
-			ASSERT(npc == curthread->t_dtrace_astpc);
-		}
+		ASSERT(thrp->t_dtrace_ret != 0);
+		ASSERT(thrp->t_dtrace_pc == orig_pc);
 	}
 
 	ASSERT(pc != 0);
 	rp->r_pc = pc;
-	rp->r_npc = npc;
 
 	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_return_probe.                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 fasttrap_return_probe(struct regs *rp)
 {
-	proc_t *p = ttoproc(curthread);
 	pid_t pid;
-	uintptr_t pc = curthread->t_dtrace_pc;
-	uintptr_t npc = curthread->t_dtrace_npc;
+	kthread_t *thrp = curthread;
+	proc_t *p = ttoproc(thrp);
+	uintptr_t pc = thrp->t_dtrace_pc;
 
-	curthread->t_dtrace_pc = 0;
-	curthread->t_dtrace_npc = 0;
-	curthread->t_dtrace_scrpc = 0;
-	curthread->t_dtrace_astpc = 0;
+	thrp->t_dtrace_pc = 0;
 
 	/*
 	 * Treat a child created by a call to vfork(2) as if it were its
@@ -984,33 +448,52 @@
 	}
 
 	/*
-	 * We set the %pc and %npc to their values when the traced
+	 * We set the %pc to its value when the traced
 	 * instruction was initially executed so that it appears to
 	 * dtrace_probe() that we're on the original instruction, and so that
 	 * the user can't easily detect our complex web of lies.
-	 * dtrace_return_probe() (our caller) will correctly set %pc and %npc
+	 * dtrace_return_probe() (our caller) will correctly set %pc
 	 * after we return.
 	 */
 	rp->r_pc = pc;
-	rp->r_npc = npc;
 
 	pid = p->p_pid;
-	fasttrap_return_common(rp, pc, pid, 0);
+	fasttrap_return_common(rp, pc, pid);
 
 	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_tracepoint_install.                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 fasttrap_tracepoint_install(proc_t *p, fasttrap_tracepoint_t *tp)
 {
 	fasttrap_instr_t instr = FASTTRAP_INSTR;
 
-	if (uwrite(p, &instr, 4, tp->ftt_pc) != 0)
+	if (uwrite(p, &instr, sizeof(instr), tp->ftt_pc) != 0)
 		return (-1);
 
 	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_tracepoint_remove.                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 fasttrap_tracepoint_remove(proc_t *p, fasttrap_tracepoint_t *tp)
 {
@@ -1020,22 +503,36 @@
 	 * Distinguish between read or write failures and a changed
 	 * instruction.
 	 */
-	if (uread(p, &instr, 4, tp->ftt_pc) != 0)
+	if (uread(p, &instr, sizeof(instr), tp->ftt_pc) != 0)
 		return (0);
-	if (instr != FASTTRAP_INSTR && instr != BREAKPOINT_INSTR)
+	if (instr != FASTTRAP_INSTR)
 		return (0);
-	if (uwrite(p, &tp->ftt_instr, 4, tp->ftt_pc) != 0)
+	if (uwrite(p, &tp->ftt_instr, sizeof(instr), tp->ftt_pc) != 0)
 		return (-1);
 
 	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_tracepoint_init.                         */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
-fasttrap_tracepoint_init(proc_t *p, fasttrap_probe_t *probe,
-    fasttrap_tracepoint_t *tp, uintptr_t pc)
+fasttrap_tracepoint_init(proc_t *p, fasttrap_tracepoint_t *tp, uintptr_t pc,
+			 fasttrap_probe_type_t type)
 {
-	uint32_t instr;
+	uint8_t instr[FASTTRAP_MAX_INSTR_SIZE],
+		fmt;
+	size_t	len   = FASTTRAP_MAX_INSTR_SIZE,
+		first = MIN(len, PAGESIZE - (pc & PAGEOFFSET));
 	int32_t disp;
+	RIL2_t *retl;
 
 	/*
 	 * Read the instruction at the given address out of the process's
@@ -1043,274 +540,167 @@
 	 * changing this instruction before we overwrite it with our trap
 	 * instruction since P_PR_LOCK is set.
 	 */
-	if (uread(p, &instr, 4, pc) != 0)
+	if (uread(p, &instr[0], first, pc) != 0)
 		return (-1);
 
+	if (len > first &&
+	    uread(p, &instr[first], len - first, pc + first) != 0) {
+		bzero(&instr[first], len - first);
+		len = first;
+	}
+
+	tp->ftt_isize = dtrace_getfmtlen(instr, &fmt);
+	bcopy(instr, tp->ftt_instr, tp->ftt_size);
+
+	/*
+	 * pc-relative instructions need further processing. For 32-bit 
+	 * offsets then we can simply calculate a new offset based on where
+	 * our ftt_instr lives, for 16-bit offsets we need to create a simple
+	 * trampoline, we'll let the branch jump over our return instruction
+	 * to a 32-bit offset jump which will take us to the desired target.
+	 *
+ 	 * For example:
+	 *		a:	bras  %r14,x
+	 * 	becomes:
+	 *			bras  %r14,y
+	 *			jg     a
+	 *		y:	jg     x
+	 */
+
 	/*
-	 * Decode the instruction to fill in the probe flags. We can have
-	 * the process execute most instructions on its own using a pc/npc
-	 * trick, but pc-relative control transfer present a problem since
-	 * we're relocating the instruction. We emulate these instructions
-	 * in the kernel. We assume a default type and over-write that as
-	 * needed.
-	 *
-	 * pc-relative instructions must be emulated for correctness;
-	 * other instructions (which represent a large set of commonly traced
-	 * instructions) are emulated or otherwise optimized for performance.
+	 * Create the return jump
 	 */
-	tp->ftt_type = FASTTRAP_T_COMMON;
-	if (OP(instr) == 1) {
-		/*
-		 * Call instructions.
-		 */
-		tp->ftt_type = FASTTRAP_T_CALL;
-		disp = DISP30(instr) << 2;
-		tp->ftt_dest = pc + (intptr_t)disp;
+	retl 	  = (RIL2_t *) (&tp->ftt_instr + tp->ftt_isize);
+	retl->op1 = JGOP1;
+	retl->m1  = UNC;
+	retl->op2 = JGOP2; 
+	retl->i2  = ((intptr_t) retl - pc + tp->ftt_isize) / 2;
 
-	} else if (OP(instr) == 0) {
-		/*
-		 * Branch instructions.
-		 *
-		 * Unconditional branches need careful attention when they're
-		 * annulled: annulled unconditional branches never execute
-		 * the instruction in the delay slot.
-		 */
-		switch (OP2(instr)) {
-		case OP2_ILLTRAP:
-		case 0x7:
-			/*
-			 * The compiler may place an illtrap after a call to
-			 * a function that returns a structure. In the case of
-			 * a returned structure, the compiler places an illtrap
-			 * whose const22 field is the size of the returned
-			 * structure immediately following the delay slot of
-			 * the call. To stay out of the way, we refuse to
-			 * place tracepoints on top of illtrap instructions.
-			 *
-			 * This is one of the dumbest architectural decisions
-			 * I've ever had to work around.
-			 *
-			 * We also identify the only illegal op2 value (See
-			 * SPARC Architecture Manual Version 9, E.2 table 31).
-			 */
-			return (-1);
+	tp->ftt_size = tp->ftt_isize + sizeof(retl);
 
-		case OP2_BPcc:
-			if (COND(instr) == 8) {
-				tp->ftt_type = FASTTRAP_T_ALWAYS;
-			} else {
-				/*
-				 * Check for an illegal instruction.
-				 */
-				if (CC(instr) & 1)
-					return (-1);
-				tp->ftt_type = FASTTRAP_T_CCR;
-				tp->ftt_cc = CC(instr);
-				tp->ftt_code = COND(instr);
-			}
-
-			if (A(instr) != 0)
-				tp->ftt_flags |= FASTTRAP_F_ANNUL;
-
-			disp = DISP19(instr);
-			disp <<= 13;
-			disp >>= 11;
-			tp->ftt_dest = pc + (intptr_t)disp;
-			break;
+	/*
+	 * If this instruction has an operand that is relative to PC 
+	 * then more processing is required
+	 */
+	if (fmt & IFMT_PCREL) {
+		intptr_t addr;
 
-		case OP2_Bicc:
-			if (COND(instr) == 8) {
-				tp->ftt_type = FASTTRAP_T_ALWAYS;
-			} else {
-				tp->ftt_type = FASTTRAP_T_CCR;
-				tp->ftt_cc = 0;
-				tp->ftt_code = COND(instr);
-			}
-
-			if (A(instr) != 0)
-				tp->ftt_flags |= FASTTRAP_F_ANNUL;
-
-			disp = DISP22(instr);
-			disp <<= 10;
-			disp >>= 8;
-			tp->ftt_dest = pc + (intptr_t)disp;
-			break;
-
-		case OP2_BPr:
-			/*
-			 * Check for an illegal instruction.
+		switch((fmt & ~IFMT_PCREL)) {
+		case IFMT_RIE1 : {
+			/* 
+			 * For these instructions we are going to get the
+			 * jump to go to a trampoline that will jump to 
+			 * the actual target
 			 */
-			if ((RCOND(instr) & 3) == 0)
-				return (-1);
+			RIE1_t *rie1 = (RIE1_t *) &tp->ftt_instr;
+			RIL2_t *ril2 = (RIL2_t *) (retl + 1);
+			intptr_t nxt = (intptr_t) (ril2 + 1);
 
 			/*
-			 * It's a violation of the v8plus ABI to use a
-			 * register-predicated branch in a 32-bit app if
-			 * the register used is an %l or an %i (%gs and %os
-			 * are legit because they're not saved to the stack
-			 * in 32-bit words when we take a trap).
+			 *  1. Determine address of real target
+			 *  2. Change target to be our jump instruction
+			 *  3. Construct a jump following the return jump
 			 */
-			if (p->p_model == DATAMODEL_ILP32 && RS1(instr) >= 16)
-				return (-1);
+			addr      = (intptr_t) (rie1->i2 * 2 + pc);
+			rie1->i2  = ((intptr_t) ((intptr_t) rie1 - nxt)) / 2;
+			ril2->op1 = JGOP1;
+			ril2->m1  = UNC;
+			ril2->op2 = JGOP2; 
+			ril2->i2  = ((intptr_t) &tp->ftt_instr - addr) / 2;
 
-			tp->ftt_type = FASTTRAP_T_REG;
-			if (A(instr) != 0)
-				tp->ftt_flags |= FASTTRAP_F_ANNUL;
-			disp = DISP16(instr);
-			disp <<= 16;
-			disp >>= 14;
-			tp->ftt_dest = pc + (intptr_t)disp;
-			tp->ftt_code = RCOND(instr);
+			tp->ftt_size += sizeof(ril2);
 			break;
-
-		case OP2_SETHI:
-			tp->ftt_type = FASTTRAP_T_SETHI;
-			break;
+		}
+		case IFMT_RIE2 : {
+			RIE2_t *rie2 = (RIE2_t *) &tp->ftt_instr;
+			RIL2_t *ril2 = (RIL2_t *) (retl + 1);
+			intptr_t nxt = (intptr_t) (ril2 + 1);
 
-		case OP2_FBPfcc:
-			if (COND(instr) == 8) {
-				tp->ftt_type = FASTTRAP_T_ALWAYS;
-			} else {
-				tp->ftt_type = FASTTRAP_T_FCC;
-				tp->ftt_cc = CC(instr);
-				tp->ftt_code = COND(instr);
-			}
+			addr      = (intptr_t) (rie2->i4 * 2 + pc);
+			rie2->i4  = ((intptr_t) ((intptr_t) rie2 - nxt)) / 2;
+			ril2->op1 = JGOP1;
+			ril2->m1  = UNC;
+			ril2->op2 = JGOP2; 
+			ril2->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
 
-			if (A(instr) != 0)
-				tp->ftt_flags |= FASTTRAP_F_ANNUL;
-
-			disp = DISP19(instr);
-			disp <<= 13;
-			disp >>= 11;
-			tp->ftt_dest = pc + (intptr_t)disp;
+			tp->ftt_size += sizeof(ril2);
 			break;
+		}
+		case IFMT_RSI : {
+			RSI_t  *rsi  = (RSI_t *) &tp->ftt_instr;
+			RIL2_t *ril2 = (RIL2_t *) (retl + 1);
+			intptr_t nxt = (intptr_t) (ril2 + 1);
 
-		case OP2_FBfcc:
-			if (COND(instr) == 8) {
-				tp->ftt_type = FASTTRAP_T_ALWAYS;
-			} else {
-				tp->ftt_type = FASTTRAP_T_FCC;
-				tp->ftt_cc = 0;
-				tp->ftt_code = COND(instr);
-			}
+			addr      = (intptr_t) (rsi->i2 * 2 + pc);
+			rsi->i2   = ((intptr_t) ((intptr_t) rsi - nxt)) / 2;
+			ril2->op1 = JGOP1;
+			ril2->m1  = UNC;
+			ril2->op2 = JGOP2; 
+			ril2->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
 
-			if (A(instr) != 0)
-				tp->ftt_flags |= FASTTRAP_F_ANNUL;
-
-			disp = DISP22(instr);
-			disp <<= 10;
-			disp >>= 8;
-			tp->ftt_dest = pc + (intptr_t)disp;
+			tp->ftt_size += sizeof(ril2);
 			break;
 		}
-
-	} else if (OP(instr) == 2) {
-		switch (OP3(instr)) {
-		case OP3_RETURN:
-			tp->ftt_type = FASTTRAP_T_RETURN;
-			break;
-
-		case OP3_JMPL:
-			tp->ftt_type = FASTTRAP_T_JMPL;
-			break;
-
-		case OP3_RD:
-			if (RS1(instr) == 5)
-				tp->ftt_type = FASTTRAP_T_RDPC;
-			break;
+		case IFMT_RIL1 : {
+			RIL1_t *ril1 = (RIL1_t *) &tp->ftt_instr;
 
-		case OP3_SAVE:
-			/*
-			 * We optimize for save instructions at function
-			 * entry; see the comment in fasttrap_pid_probe()
-			 * (near FASTTRAP_T_SAVE) for details.
-			 */
-			if (fasttrap_optimize_save != 0 &&
-			    probe->ftp_type == DTFTP_ENTRY &&
-			    I(instr) == 1 && RD(instr) == R_SP)
-				tp->ftt_type = FASTTRAP_T_SAVE;
+			addr     = (intptr_t) (ril1->i2 * 2 + pc);
+			ril1->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
 			break;
+		}
+		case IFMT_RIL2 : {
+			RIL2_t *ril2 = (RIL2_t *) &tp->ftt_instr;
 
-		case OP3_RESTORE:
-			/*
-			 * We optimize restore instructions at function
-			 * return; see the comment in fasttrap_pid_probe()
-			 * (near FASTTRAP_T_RESTORE) for details.
-			 *
-			 * rd must be an %o or %g register.
-			 */
-			if ((RD(instr) & 0x10) == 0)
-				tp->ftt_type = FASTTRAP_T_RESTORE;
+			addr     = (intptr_t) (ril2->i2 * 2 + pc);
+			ril2->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
 			break;
+		}
+		case IFMT_RI1 : {
+			RI1_t  *ri1  = (RI1_t *) &tp->ftt_instr;
+			RIL2_t *ril2 = (RIL2_t *) (retl + 1);
+			intptr_t nxt = (intptr_t) (ril2 + 1);
 
-		case OP3_OR:
-			/*
-			 * A large proportion of instructions in the delay
-			 * slot of retl instructions are or's so we emulate
-			 * these downstairs as an optimization.
-			 */
-			tp->ftt_type = FASTTRAP_T_OR;
-			break;
-
-		case OP3_TCC:
-			/*
-			 * Breakpoint instructions are effectively position-
-			 * dependent since the debugger uses the %pc value
-			 * to lookup which breakpoint was executed. As a
-			 * result, we can't actually instrument breakpoints.
-			 */
-			if (SW_TRAP(instr) == ST_BREAKPOINT)
-				return (-1);
-			break;
+			addr      = (intptr_t) (ri1->i2 * 2 + pc);
+			ri1->i2   = ((intptr_t) ((intptr_t) ri1 - nxt)) / 2;
+			ril2->op1 = JGOP1;
+			ril2->m1  = UNC;
+			ril2->op2 = JGOP2; 
+			ril2->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
 
-		case 0x19:
-		case 0x1d:
-		case 0x29:
-		case 0x33:
-		case 0x3f:
-			/*
-			 * Identify illegal instructions (See SPARC
-			 * Architecture Manual Version 9, E.2 table 32).
-			 */
-			return (-1);
+			tp->ftt_size += sizeof(ril2);
+			break;
 		}
-	} else if (OP(instr) == 3) {
-		uint32_t op3 = OP3(instr);
+		case IFMT_RI2 : {
+			RI2_t  *ri2  = (RI2_t *) &tp->ftt_instr;
+			RIL2_t *ril2 = (RIL2_t *) (retl + 1);
+			intptr_t nxt = (intptr_t) (ril2 + 1);
 
-		/*
-		 * Identify illegal instructions (See SPARC Architecture
-		 * Manual Version 9, E.2 table 33).
-		 */
-		if ((op3 & 0x28) == 0x28) {
-			if (op3 != OP3_PREFETCH && op3 != OP3_CASA &&
-			    op3 != OP3_PREFETCHA && op3 != OP3_CASXA)
-				return (-1);
-		} else {
-			if ((op3 & 0x0f) == 0x0c || (op3 & 0x3b) == 0x31)
-				return (-1);
+			addr      = (intptr_t) (ri2->i2 * 2 + pc);
+			ri2->i2   = ((intptr_t) ((intptr_t) ri2 - nxt)) / 2;
+			ril2->op1 = JGOP1;
+			ril2->m1  = UNC;
+			ril2->op2 = JGOP2; 
+			ril2->i2 = ((intptr_t) &tp->ftt_instr - addr) / 2;
+
+			tp->ftt_size += sizeof(ril2);
+			break;
+		}
 		}
 	}
 
-	tp->ftt_instr = instr;
-
-	/*
-	 * We don't know how this tracepoint is going to be used, but in case
-	 * it's used as part of a function return probe, we need to indicate
-	 * whether it's always a return site or only potentially a return
-	 * site. If it's part of a return probe, it's always going to be a
-	 * return from that function if it's a restore instruction or if
-	 * the previous instruction was a return. If we could reliably
-	 * distinguish jump tables from return sites, this wouldn't be
-	 * necessary.
-	 */
-	if (tp->ftt_type != FASTTRAP_T_RESTORE &&
-	    (uread(p, &instr, 4, pc - sizeof (instr)) != 0 ||
-	    !(OP(instr) == 2 && OP3(instr) == OP3_RETURN)))
-		tp->ftt_flags |= FASTTRAP_F_RETMAYBE;
-
 	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		-                                                   */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 uint64_t
 fasttrap_getarg(void *arg, dtrace_id_t id, void *parg, int argno, int aframes)
@@ -1318,6 +708,16 @@
 	return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno));
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fasttrap_usdt_getarg.                             */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 uint64_t
 fasttrap_usdt_getarg(void *arg, dtrace_id_t id, void *parg, int argno,
@@ -1326,216 +726,4 @@
 	return (fasttrap_anarg(ttolwp(curthread)->lwp_regs, argno));
 }
 
-static uint64_t fasttrap_getreg_fast_cnt;
-static uint64_t fasttrap_getreg_mpcb_cnt;
-static uint64_t fasttrap_getreg_slow_cnt;
-
-static ulong_t
-fasttrap_getreg(struct regs *rp, uint_t reg)
-{
-	ulong_t value;
-	dtrace_icookie_t cookie;
-	struct machpcb *mpcb;
-	extern ulong_t dtrace_getreg_win(uint_t, uint_t);
-
-	/*
-	 * We have the %os and %gs in our struct regs, but if we need to
-	 * snag a %l or %i we need to go scrounging around in the process's
-	 * address space.
-	 */
-	if (reg == 0)
-		return (0);
-
-	if (reg < 16)
-		return ((&rp->r_g1)[reg - 1]);
-
-	/*
-	 * Before we look at the user's stack, we'll check the register
-	 * windows to see if the information we want is in there.
-	 */
-	cookie = dtrace_interrupt_disable();
-	if (dtrace_getotherwin() > 0) {
-		value = dtrace_getreg_win(reg, 1);
-		dtrace_interrupt_enable(cookie);
-
-		atomic_add_64(&fasttrap_getreg_fast_cnt, 1);
-
-		return (value);
-	}
-	dtrace_interrupt_enable(cookie);
-
-	/*
-	 * First check the machpcb structure to see if we've already read
-	 * in the register window we're looking for; if we haven't, (and
-	 * we probably haven't) try to copy in the value of the register.
-	 */
-	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
-
-	if (get_udatamodel() == DATAMODEL_NATIVE) {
-		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
-					continue;
-
-				atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);
-				return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
-
-		if (fasttrap_fulword(&fr->fr_local[reg - 16], &value) != 0)
-			goto err;
-	} else {
-		struct frame32 *fr =
-		    (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
-		uint32_t *v32 = (uint32_t *)&value;
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			struct rwindow32 *rwin = (void *)mpcb->mpcb_wbuf;
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
-					continue;
-
-				atomic_add_64(&fasttrap_getreg_mpcb_cnt, 1);
-				return (rwin[i].rw_local[reg - 16]);
-			} while (i > 0);
-		}
-
-		if (fasttrap_fuword32(&fr->fr_local[reg - 16], &v32[1]) != 0)
-			goto err;
-
-		v32[0] = 0;
-	}
-
-	atomic_add_64(&fasttrap_getreg_slow_cnt, 1);
-	return (value);
-
-err:
-	/*
-	 * If the copy in failed, the process will be in a irrecoverable
-	 * state, and we have no choice but to kill it.
-	 */
-	psignal(ttoproc(curthread), SIGILL);
-	return (0);
-}
-
-static uint64_t fasttrap_putreg_fast_cnt;
-static uint64_t fasttrap_putreg_mpcb_cnt;
-static uint64_t fasttrap_putreg_slow_cnt;
-
-static void
-fasttrap_putreg(struct regs *rp, uint_t reg, ulong_t value)
-{
-	dtrace_icookie_t cookie;
-	struct machpcb *mpcb;
-	extern void dtrace_putreg_win(uint_t, ulong_t);
-
-	if (reg == 0)
-		return;
-
-	if (reg < 16) {
-		(&rp->r_g1)[reg - 1] = value;
-		return;
-	}
-
-	/*
-	 * If the user process is still using some register windows, we
-	 * can just place the value in the correct window.
-	 */
-	cookie = dtrace_interrupt_disable();
-	if (dtrace_getotherwin() > 0) {
-		dtrace_putreg_win(reg, value);
-		dtrace_interrupt_enable(cookie);
-		atomic_add_64(&fasttrap_putreg_fast_cnt, 1);
-		return;
-	}
-	dtrace_interrupt_enable(cookie);
-
-	/*
-	 * First see if there's a copy of the register window in the
-	 * machpcb structure that we can modify; if there isn't try to
-	 * copy out the value. If that fails, we try to create a new
-	 * register window in the machpcb structure. While this isn't
-	 * _precisely_ the intended use of the machpcb structure, it
-	 * can't cause any problems since we know at this point in the
-	 * code that all of the user's data have been flushed out of the
-	 * register file (since %otherwin is 0).
-	 */
-	mpcb = (struct machpcb *)((caddr_t)rp - REGOFF);
-
-	if (get_udatamodel() == DATAMODEL_NATIVE) {
-		struct frame *fr = (struct frame *)(rp->r_sp + STACK_BIAS);
-		struct rwindow *rwin = (struct rwindow *)mpcb->mpcb_wbuf;
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
-					continue;
-
-				rwin[i].rw_local[reg - 16] = value;
-				atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
-				return;
-			} while (i > 0);
-		}
-
-		if (fasttrap_sulword(&fr->fr_local[reg - 16], value) != 0) {
-			if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
-			    &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
-				goto err;
-
-			rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = value;
-			mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
-			mpcb->mpcb_wbcnt++;
-			atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
-			return;
-		}
-	} else {
-		struct frame32 *fr =
-		    (struct frame32 *)(uintptr_t)(caddr32_t)rp->r_sp;
-		struct rwindow32 *rwin = (struct rwindow32 *)mpcb->mpcb_wbuf;
-		uint32_t v32 = (uint32_t)value;
-
-		if (mpcb->mpcb_wbcnt > 0) {
-			int i = mpcb->mpcb_wbcnt;
-			do {
-				i--;
-				if ((long)mpcb->mpcb_spbuf[i] != rp->r_sp)
-					continue;
-
-				rwin[i].rw_local[reg - 16] = v32;
-				atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
-				return;
-			} while (i > 0);
-		}
-
-		if (fasttrap_suword32(&fr->fr_local[reg - 16], v32) != 0) {
-			if (mpcb->mpcb_wbcnt >= MAXWIN || copyin(fr,
-			    &rwin[mpcb->mpcb_wbcnt], sizeof (*rwin)) != 0)
-				goto err;
-
-			rwin[mpcb->mpcb_wbcnt].rw_local[reg - 16] = v32;
-			mpcb->mpcb_spbuf[mpcb->mpcb_wbcnt] = (caddr_t)rp->r_sp;
-			mpcb->mpcb_wbcnt++;
-			atomic_add_64(&fasttrap_putreg_mpcb_cnt, 1);
-			return;
-		}
-	}
-
-	atomic_add_64(&fasttrap_putreg_slow_cnt, 1);
-	return;
-
-err:
-	/*
-	 * If we couldn't record this register's value, the process is in an
-	 * irrecoverable state and we have no choice but to euthanize it.
-	 */
-	psignal(ttoproc(curthread), SIGILL);
-}
+/*========================= End of Function ========================*/
--- a/usr/src/uts/zSeries/dtrace/fbt.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/fbt.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1,1023 +1,319 @@
-/*
- * 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
+/*------------------------------------------------------------------*/
+/* 								    */
+/* Name        - fbt.c      					    */
+/* 								    */
+/* Function    - Platform specific support for Dtrace FBT.          */
+/* 								    */
+/* Name	       - Neale Ferguson					    */
+/* 								    */
+/* Date        - October, 2009   				    */
+/* 								    */
+/*------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------*/
+/*                   L I C E N S E                                  */
+/*------------------------------------------------------------------*/
+
+/*==================================================================*/
+/* 								    */
+/* 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 the 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 2008 Sine Nomine Associates.                           */
 /* All rights reserved.                                             */
 /* Use is subject to license terms.                                 */
- */
-/*
- * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
+/* 								    */
+/* Copyright 2005 Sun Microsystems, Inc.  All rights reserved.	    */
+/* Use is subject to license terms.				    */
+/* 								    */
+/*==================================================================*/
+
+/*------------------------------------------------------------------*/
+/*                 D e f i n e s                                    */
+/*------------------------------------------------------------------*/
+
+#define	OP_STMG1		0xeb
+#define	OP_STMG2		0x24
+#define	OP_LMG1			0xeb
+#define	OP_LMG2			0x04
+#define OP_BR			0x07
 
-#include <sys/errno.h>
-#include <sys/stat.h>
+#define UNC			0xf
+#define R14			0xe
+#define R4			0x4
+
+#define	FBT_PATCHVAL		0x0a01
+
+#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 */
+
+/*========================= End of Defines =========================*/
+
+/*------------------------------------------------------------------*/
+/*                 I n c l u d e s                                  */
+/*------------------------------------------------------------------*/
+
 #include <sys/modctl.h>
-#include <sys/conf.h>
-#include <sys/systm.h>
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#include <sys/cpuvar.h>
-#include <sys/kmem.h>
-#include <sys/strsubr.h>
 #include <sys/dtrace.h>
 #include <sys/kobj.h>
-#include <sys/modctl.h>
-#include <sys/atomic.h>
-#include <vm/seg_kmem.h>
-#include <sys/stack.h>
-#include <sys/ctf_api.h>
-#include <sys/sysmacros.h>
-
-static dev_info_t		*fbt_devi;
-static dtrace_provider_id_t	fbt_id;
-static uintptr_t		fbt_trampoline;
-static caddr_t			fbt_trampoline_window;
-static size_t			fbt_trampoline_size;
-static int			fbt_verbose = 0;
-
-/*
- * Various interesting bean counters.
- */
-static int			fbt_entry;
-static int			fbt_ret;
-static int			fbt_retl;
-static int			fbt_retl_jmptab;
-static int			fbt_retl_twoinstr;
-static int			fbt_retl_tailcall;
-static int			fbt_retl_tailjmpl;
-static int			fbt_leaf_functions;
-
-extern char			stubs_base[];
-extern char			stubs_end[];
-
-#define	FBT_REG_G0		0
-#define	FBT_REG_G1		1
-#define	FBT_REG_O0		8
-#define	FBT_REG_O1		9
-#define	FBT_REG_O2		10
-#define	FBT_REG_O3		11
-#define	FBT_REG_O4		12
-#define	FBT_REG_O5		13
-#define	FBT_REG_O6		14
-#define	FBT_REG_O7		15
-#define	FBT_REG_I0		24
-#define	FBT_REG_I1		25
-#define	FBT_REG_I2		26
-#define	FBT_REG_I3		27
-#define	FBT_REG_I4		28
-#define	FBT_REG_I7		31
-#define	FBT_REG_L0		16
-#define	FBT_REG_L1		17
-#define	FBT_REG_L2		18
-#define	FBT_REG_L3		19
-#define	FBT_REG_PC		5
-
-#define	FBT_REG_ISGLOBAL(r)	((r) < 8)
-#define	FBT_REG_ISOUTPUT(r)	((r) >= 8 && (r) < 16)
-#define	FBT_REG_ISLOCAL(r)	((r) >= 16 && (r) < 24)
-#define	FBT_REG_ISVOLATILE(r)	\
-	((FBT_REG_ISGLOBAL(r) || FBT_REG_ISOUTPUT(r)) && (r) != FBT_REG_G0)
-#define	FBT_REG_NLOCALS		8
-
-#define	FBT_REG_MARKLOCAL(locals, r)	\
-	if (FBT_REG_ISLOCAL(r)) \
-		(locals)[(r) - FBT_REG_L0] = 1;
-
-#define	FBT_REG_INITLOCALS(local, locals)	\
-	for ((local) = 0; (local) < FBT_REG_NLOCALS; (local)++)  \
-		(locals)[(local)] = 0; \
-	(local) = FBT_REG_L0
-
-#define	FBT_REG_ALLOCLOCAL(local, locals)	\
-	while ((locals)[(local) - FBT_REG_L0]) \
-		(local)++; \
-	(locals)[(local) - FBT_REG_L0] = 1;
-
-#define	FBT_OP_MASK		0xc0000000
-#define	FBT_OP_SHIFT		30
-#define	FBT_OP(val)		((val) & FBT_FMT1_MASK)
-
-#define	FBT_SIMM13_MASK		0x1fff
-#define	FBT_SIMM13_MAX		((int32_t)0xfff)
-#define	FBT_IMM22_MASK		0x3fffff
-#define	FBT_IMM22_SHIFT		10
-#define	FBT_IMM10_MASK		0x3ff
-
-#define	FBT_DISP30_MASK		0x3fffffff
-#define	FBT_DISP30(from, to)	\
-	(((uintptr_t)(to) - (uintptr_t)(from) >> 2) & FBT_DISP30_MASK)
-
-#define	FBT_DISP22_MASK		0x3fffff
-#define	FBT_DISP22(from, to)	\
-	(((uintptr_t)(to) - (uintptr_t)(from) >> 2) & FBT_DISP22_MASK)
-
-#define	FBT_DISP19_MASK		0x7ffff
-#define	FBT_DISP19(from, to)	\
-	(((uintptr_t)(to) - (uintptr_t)(from) >> 2) & FBT_DISP19_MASK)
-
-#define	FBT_DISP16_HISHIFT	20
-#define	FBT_DISP16_HIMASK	(0x3 << FBT_DISP16_HISHIFT)
-#define	FBT_DISP16_LOMASK	(0x3fff)
-#define	FBT_DISP16_MASK		(FBT_DISP16_HIMASK | FBT_DISP16_LOMASK)
-#define	FBT_DISP16(val)	\
-	((((val) & FBT_DISP16_HIMASK) >> 6) | ((val) & FBT_DISP16_LOMASK))
-
-#define	FBT_DISP14_MASK		0x3fff
-#define	FBT_DISP14(from, to)	\
-	(((uintptr_t)(to) - (uintptr_t)(from) >> 2) & FBT_DISP14_MASK)
-
-#define	FBT_OP0			(((uint32_t)0) << FBT_OP_SHIFT)
-#define	FBT_OP1			(((uint32_t)1) << FBT_OP_SHIFT)
-#define	FBT_OP2			(((uint32_t)2) << FBT_OP_SHIFT)
-#define	FBT_ILLTRAP		0
-
-#define	FBT_ANNUL_SHIFT		29
-#define	FBT_ANNUL		(1 << FBT_ANNUL_SHIFT)
-
-#define	FBT_FMT3_OP3_SHIFT	19
-#define	FBT_FMT3_OP_MASK	0xc1f80000
-#define	FBT_FMT3_OP(val)	((val) & FBT_FMT3_OP_MASK)
-
-#define	FBT_FMT3_RD_SHIFT	25
-#define	FBT_FMT3_RD_MASK	(0x1f << FBT_FMT3_RD_SHIFT)
-#define	FBT_FMT3_RD(val)	\
-	(((val) & FBT_FMT3_RD_MASK) >> FBT_FMT3_RD_SHIFT)
-
-#define	FBT_FMT3_RS1_SHIFT	14
-#define	FBT_FMT3_RS1_MASK	(0x1f << FBT_FMT3_RS1_SHIFT)
-#define	FBT_FMT3_RS1(val)	\
-	(((val) & FBT_FMT3_RS1_MASK) >> FBT_FMT3_RS1_SHIFT)
-#define	FBT_FMT3_RS1_SET(val, rs1) \
-	(val) = ((val) & ~FBT_FMT3_RS1_MASK) | ((rs1) << FBT_FMT3_RS1_SHIFT)
-
-#define	FBT_FMT3_RS2_SHIFT	0
-#define	FBT_FMT3_RS2_MASK	(0x1f << FBT_FMT3_RS2_SHIFT)
-#define	FBT_FMT3_RS2(val)	\
-	(((val) & FBT_FMT3_RS2_MASK) >> FBT_FMT3_RS2_SHIFT)
-#define	FBT_FMT3_RS2_SET(val, rs2) \
-	(val) = ((val) & ~FBT_FMT3_RS2_MASK) | ((rs2) << FBT_FMT3_RS2_SHIFT)
+#include <sys/stat.h>
+#include <sys/ddi.h>
+#include <sys/sunddi.h>
+#include <sys/conf.h>
+#include <dis_tables.h>
 
-#define	FBT_FMT3_IMM_SHIFT	13
-#define	FBT_FMT3_IMM		(1 << FBT_FMT3_IMM_SHIFT)
-#define	FBT_FMT3_SIMM13_MASK	FBT_SIMM13_MASK
-
-#define	FBT_FMT3_ISIMM(val)	((val) & FBT_FMT3_IMM)
-#define	FBT_FMT3_SIMM13(val)	((val) & FBT_FMT3_SIMM13_MASK)
-
-#define	FBT_FMT2_OP2_SHIFT	22
-#define	FBT_FMT2_OP2_MASK	(0x7 << FBT_FMT2_OP2_SHIFT)
-#define	FBT_FMT2_RD_SHIFT	25
-
-#define	FBT_FMT1_OP(val)	((val) & FBT_OP_MASK)
-#define	FBT_FMT1_DISP30(val)	((val) & FBT_DISP30_MASK)
-
-#define	FBT_FMT2_OP2_BPCC	(0x01 << FBT_FMT2_OP2_SHIFT)
-#define	FBT_FMT2_OP2_BCC	(0x02 << FBT_FMT2_OP2_SHIFT)
-#define	FBT_FMT2_OP2_BPR	(0x03 << FBT_FMT2_OP2_SHIFT)
-#define	FBT_FMT2_OP2_SETHI	(0x04 << FBT_FMT2_OP2_SHIFT)
-
-#define	FBT_FMT2_COND_SHIFT	25
-#define	FBT_FMT2_COND_BA	(0x8 << FBT_FMT2_COND_SHIFT)
-#define	FBT_FMT2_COND_BL	(0x3 << FBT_FMT2_COND_SHIFT)
-#define	FBT_FMT2_COND_BGE	(0xb << FBT_FMT2_COND_SHIFT)
-
-#define	FBT_OP_RESTORE		(FBT_OP2 | (0x3d << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_SAVE		(FBT_OP2 | (0x3c << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_JMPL		(FBT_OP2 | (0x38 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_RETURN		(FBT_OP2 | (0x39 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_CALL		FBT_OP1
-#define	FBT_OP_SETHI		(FBT_OP0 | FBT_FMT2_OP2_SETHI)
-#define	FBT_OP_ADD		(FBT_OP2 | (0x00 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_OR		(FBT_OP2 | (0x02 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_SUB		(FBT_OP2 | (0x04 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_CC		(FBT_OP2 | (0x10 << FBT_FMT3_OP3_SHIFT))
-#define	FBT_OP_BA		(FBT_OP0 | FBT_FMT2_OP2_BCC | FBT_FMT2_COND_BA)
-#define	FBT_OP_BL		(FBT_OP0 | FBT_FMT2_OP2_BCC | FBT_FMT2_COND_BL)
-#define	FBT_OP_BGE		(FBT_OP0 | FBT_FMT2_OP2_BCC | FBT_FMT2_COND_BGE)
-#define	FBT_OP_BAPCC		(FBT_OP0 | FBT_FMT2_OP2_BPCC | FBT_FMT2_COND_BA)
-#define	FBT_OP_RD		(FBT_OP2 | (0x28 << FBT_FMT3_OP3_SHIFT))
-
-#define	FBT_ORLO(rs, val, rd) \
-	(FBT_OP_OR | ((rs) << FBT_FMT3_RS1_SHIFT) | \
-	((rd) << FBT_FMT3_RD_SHIFT) | FBT_FMT3_IMM | ((val) & FBT_IMM10_MASK))
-
-#define	FBT_ORSIMM13(rs, val, rd) \
-	(FBT_OP_OR | ((rs) << FBT_FMT3_RS1_SHIFT) | \
-	((rd) << FBT_FMT3_RD_SHIFT) | FBT_FMT3_IMM | ((val) & FBT_SIMM13_MASK))
-
-#define	FBT_ADDSIMM13(rs, val, rd) \
-	(FBT_OP_ADD | ((rs) << FBT_FMT3_RS1_SHIFT) | \
-	((rd) << FBT_FMT3_RD_SHIFT) | FBT_FMT3_IMM | ((val) & FBT_SIMM13_MASK))
-
-#define	FBT_ADD(rs1, rs2, rd) \
-	(FBT_OP_ADD | ((rs1) << FBT_FMT3_RS1_SHIFT) | \
-	((rs2) << FBT_FMT3_RS2_SHIFT) | ((rd) << FBT_FMT3_RD_SHIFT))
-
-#define	FBT_CMP(rs1, rs2) \
-	(FBT_OP_SUB | FBT_OP_CC | ((rs1) << FBT_FMT3_RS1_SHIFT) | \
-	((rs2) << FBT_FMT3_RS2_SHIFT) | (FBT_REG_G0 << FBT_FMT3_RD_SHIFT))
-
-#define	FBT_MOV(rs, rd) \
-	(FBT_OP_OR | (FBT_REG_G0 << FBT_FMT3_RS1_SHIFT) | \
-	((rs) << FBT_FMT3_RS2_SHIFT) | ((rd) << FBT_FMT3_RD_SHIFT))
-
-#define	FBT_SETHI(val, reg)	\
-	(FBT_OP_SETHI | (reg << FBT_FMT2_RD_SHIFT) | \
-	((val >> FBT_IMM22_SHIFT) & FBT_IMM22_MASK))
+/*========================= End of Includes ========================*/
 
-#define	FBT_CALL(orig, dest)	(FBT_OP_CALL | FBT_DISP30(orig, dest))
-
-#define	FBT_RET \
-	(FBT_OP_JMPL | (FBT_REG_I7 << FBT_FMT3_RS1_SHIFT) | \
-	(FBT_REG_G0 << FBT_FMT3_RD_SHIFT) | FBT_FMT3_IMM | (sizeof (pc_t) << 1))
-
-#define	FBT_SAVEIMM(rd, val, rs1)	\
-	(FBT_OP_SAVE | ((rs1) << FBT_FMT3_RS1_SHIFT) | \
-	((rd) << FBT_FMT3_RD_SHIFT) | FBT_FMT3_IMM | ((val) & FBT_SIMM13_MASK))
-
-#define	FBT_RESTORE(rd, rs1, rs2)	\
-	(FBT_OP_RESTORE | ((rs1) << FBT_FMT3_RS1_SHIFT) | \
-	((rd) << FBT_FMT3_RD_SHIFT) | ((rs2) << FBT_FMT3_RS2_SHIFT))
-
-#define	FBT_RETURN(rs1, val)		\
-	(FBT_OP_RETURN | ((rs1) << FBT_FMT3_RS1_SHIFT) | \
-	FBT_FMT3_IMM | ((val) & FBT_SIMM13_MASK))
-
-#define	FBT_BA(orig, dest)	(FBT_OP_BA | FBT_DISP22(orig, dest))
-#define	FBT_BAA(orig, dest)	(FBT_BA(orig, dest) | FBT_ANNUL)
-#define	FBT_BL(orig, dest)	(FBT_OP_BL | FBT_DISP22(orig, dest))
-#define	FBT_BGE(orig, dest)	(FBT_OP_BGE | FBT_DISP22(orig, dest))
-#define	FBT_BDEST(va, instr)	((uintptr_t)(va) + \
-	(((int32_t)(((instr) & FBT_DISP22_MASK) << 10)) >> 8))
-#define	FBT_BPCCDEST(va, instr)	((uintptr_t)(va) + \
-	(((int32_t)(((instr) & FBT_DISP19_MASK) << 13)) >> 11))
-#define	FBT_BPRDEST(va, instr)	((uintptr_t)(va) + \
-	(((int32_t)((FBT_DISP16(instr)) << 16)) >> 14))
-
-/*
- * We're only going to treat a save as safe if (a) both rs1 and rd are
- * %sp and (b) if the instruction has a simm, the value isn't 0.
- */
-#define	FBT_IS_SAVE(instr)	\
-	(FBT_FMT3_OP(instr) == FBT_OP_SAVE && \
-	FBT_FMT3_RD(instr) == FBT_REG_O6 && \
-	FBT_FMT3_RS1(instr) == FBT_REG_O6 && \
-	!(FBT_FMT3_ISIMM(instr) && FBT_FMT3_SIMM13(instr) == 0))
-
-#define	FBT_IS_BA(instr)	(((instr) & ~FBT_DISP22_MASK) == FBT_OP_BA)
-#define	FBT_IS_BAPCC(instr)	(((instr) & ~FBT_DISP22_MASK) == FBT_OP_BAPCC)
-
-#define	FBT_IS_RDPC(instr)	((FBT_FMT3_OP(instr) == FBT_OP_RD) && \
-	(FBT_FMT3_RD(instr) == FBT_REG_PC))
-
-#define	FBT_IS_PCRELATIVE(instr)	\
-	((((instr) & FBT_OP_MASK) == FBT_OP0 && \
-	((instr) & FBT_FMT2_OP2_MASK) != FBT_FMT2_OP2_SETHI) || \
-	((instr) & FBT_OP_MASK) == FBT_OP1 || \
-	FBT_IS_RDPC(instr))
-
-#define	FBT_IS_CTI(instr)	\
-	((((instr) & FBT_OP_MASK) == FBT_OP0 && \
-	((instr) & FBT_FMT2_OP2_MASK) != FBT_FMT2_OP2_SETHI) || \
-	((instr) & FBT_OP_MASK) == FBT_OP1 || \
-	(FBT_FMT3_OP(instr) == FBT_OP_JMPL) || \
-	(FBT_FMT3_OP(instr) == FBT_OP_RETURN))
-
-#define	FBT_PROBENAME_ENTRY	"entry"
-#define	FBT_PROBENAME_RETURN	"return"
-#define	FBT_ESTIMATE_ID		(UINT32_MAX)
-#define	FBT_COUNTER(id, count)	if ((id) != FBT_ESTIMATE_ID) (count)++
-
-#define	FBT_ENTENT_MAXSIZE	(16 * sizeof (uint32_t))
-#define	FBT_RETENT_MAXSIZE	(11 * sizeof (uint32_t))
-#define	FBT_RETLENT_MAXSIZE	(23 * sizeof (uint32_t))
-#define	FBT_ENT_MAXSIZE		\
-	MAX(MAX(FBT_ENTENT_MAXSIZE, FBT_RETENT_MAXSIZE), FBT_RETLENT_MAXSIZE)
+/*------------------------------------------------------------------*/
+/*                 T y p e d e f s                                  */
+/*------------------------------------------------------------------*/
 
 typedef struct fbt_probe {
-	char		*fbtp_name;
+	struct fbt_probe *fbtp_hashnext;
+	uint8_t		*fbtp_patchpoint;
+	uint16_t	fbtp_patchval;
+	int8_t		fbtp_rval;
+	uint8_t		fbtp_savedval;
+	uintptr_t	fbtp_roffset;
 	dtrace_id_t	fbtp_id;
-	uintptr_t	fbtp_addr;
+	char		*fbtp_name;
 	struct modctl	*fbtp_ctl;
 	int		fbtp_loadcnt;
 	int		fbtp_symndx;
 	int		fbtp_primary;
-	int		fbtp_return;
-	uint32_t	*fbtp_patchpoint;
-	uint32_t	fbtp_patchval;
-	uint32_t	fbtp_savedval;
 	struct fbt_probe *fbtp_next;
 } fbt_probe_t;
 
-typedef struct fbt_trampoline {
-	uintptr_t	fbtt_va;
-	uintptr_t	fbtt_limit;
-	uintptr_t	fbtt_next;
-} fbt_trampoline_t;
+/*========================= End of Typedefs ========================*/
+
+/*------------------------------------------------------------------*/
+/*                E x t e r n a l   R e f e r e n c e s             */
+/*------------------------------------------------------------------*/
 
-static caddr_t
-fbt_trampoline_map(uintptr_t tramp, size_t size)
-{
-	uintptr_t offs;
-	page_t **ppl;
+
+/*=================== End of External References ===================*/
+
+/*------------------------------------------------------------------*/
+/*                   P r o t o t y p e s                            */
+/*------------------------------------------------------------------*/
 
-	ASSERT(fbt_trampoline_window == NULL);
-	ASSERT(fbt_trampoline_size == 0);
-	ASSERT(fbt_trampoline == NULL);
+static int fbt_open(dev_t *, int, int, cred_t *);
+static int fbt_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
+static int fbt_attach(dev_info_t *, ddi_attach_cmd_t);
+static int fbt_detach(dev_info_t *, ddi_detach_cmd_t);
+static int fbt_enable(void *, dtrace_id_t, void *);
+static void fbt_provide_module(void *, struct modctl *);
+static void fbt_disable(void *, dtrace_id_t, void *);
+static void fbt_suspend(void *, dtrace_id_t, void *);
+static void fbt_resume(void *, dtrace_id_t, void *);
+static void fbt_getargdesc(void *, dtrace_id_t, void *, dtrace_argdesc_t *);
+static void fbt_cleanup(dev_info_t *);
+static void fbt_destroy(void *, dtrace_id_t, void *);
+
+/*========================= End of Prototypes ======================*/
 
-	size += tramp & PAGEOFFSET;
-	fbt_trampoline = tramp & PAGEMASK;
-	fbt_trampoline_size = (size + PAGESIZE - 1) & PAGEMASK;
-	fbt_trampoline_window =
-	    vmem_alloc(heap_arena, fbt_trampoline_size, VM_SLEEP);
+/*------------------------------------------------------------------*/
+/*                 G l o b a l   V a r i a b l e s                  */
+/*------------------------------------------------------------------*/
 
-	(void) as_pagelock(&kas, &ppl, (caddr_t)fbt_trampoline,
-	    fbt_trampoline_size, S_WRITE);
+static struct cb_ops fbt_cb_ops = {
+	fbt_open,		/* open */
+	nodev,			/* close */
+	nulldev,		/* strategy */
+	nulldev,		/* print */
+	nodev,			/* dump */
+	nodev,			/* read */
+	nodev,			/* write */
+	nodev,			/* ioctl */
+	nodev,			/* devmap */
+	nodev,			/* mmap */
+	nodev,			/* segmap */
+	nochpoll,		/* poll */
+	ddi_prop_op,		/* cb_prop_op */
+	0,			/* streamtab  */
+	D_NEW | D_MP		/* Driver compatibility flag */
+};
 
-	for (offs = 0; offs < fbt_trampoline_size; offs += PAGESIZE) {
-		hat_devload(kas.a_hat, fbt_trampoline_window + offs, PAGESIZE,
-		    hat_getpfnum(kas.a_hat, (caddr_t)fbt_trampoline + offs),
-		    PROT_READ | PROT_WRITE,
-		    HAT_LOAD_LOCK | HAT_LOAD_NOCONSIST);
-	}
+static struct dev_ops fbt_ops = {
+	DEVO_REV,		/* devo_rev */
+	0,			/* refcnt */
+	fbt_info,		/* get_dev_info */
+	nulldev,		/* identify */
+	nulldev,		/* probe */
+	fbt_attach,		/* attach */
+	fbt_detach,		/* detach */
+	nodev,			/* reset */
+	&fbt_cb_ops,		/* driver operations */
+	NULL,			/* bus operations */
+	nodev,			/* dev power */
+	ddi_quiesce_not_needed,	/* quiesce */
+};
 
-	as_pageunlock(&kas, ppl, (caddr_t)fbt_trampoline, fbt_trampoline_size,
-	    S_WRITE);
+/*
+ * Module linkage information for the kernel.
+ */
+static struct modldrv modldrv = {
+	&mod_driverops,		/* module type (this is a pseudo driver) */
+	"Function Boundary Tracing",	/* name of module */
+	&fbt_ops,		/* driver ops */
+};
 
-	return (fbt_trampoline_window + (tramp & PAGEOFFSET));
-}
+static struct modlinkage modlinkage = {
+	MODREV_1,
+	(void *)&modldrv,
+	NULL
+};
 
-static void
-fbt_trampoline_unmap()
-{
-	ASSERT(fbt_trampoline_window != NULL);
-	ASSERT(fbt_trampoline_size != 0);
-	ASSERT(fbt_trampoline != NULL);
-
-	membar_enter();
-	sync_icache((caddr_t)fbt_trampoline, fbt_trampoline_size);
-	sync_icache(fbt_trampoline_window, fbt_trampoline_size);
+static dtrace_pattr_t fbt_attr = {
+	{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
+	{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+	{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
+	{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
+	{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
+};
 
-	hat_unload(kas.a_hat, fbt_trampoline_window, fbt_trampoline_size,
-	    HAT_UNLOAD_UNLOCK);
-
-	vmem_free(heap_arena, fbt_trampoline_window, fbt_trampoline_size);
+static dtrace_pops_t fbt_pops = {
+	NULL,
+	fbt_provide_module,
+	fbt_enable,
+	fbt_disable,
+	fbt_suspend,
+	fbt_resume,
+	fbt_getargdesc,
+	NULL,
+	NULL,
+	fbt_destroy
+};
 
-	fbt_trampoline_window = NULL;
-	fbt_trampoline = NULL;
-	fbt_trampoline_size = 0;
-}
+static dev_info_t		*fbt_devi;
+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;
+
+/*====================== End of Global Variables ===================*/
 
-static uintptr_t
-fbt_patch_entry(uint32_t *instr, uint32_t id, fbt_trampoline_t *tramp,
-    int nargs)
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_invop.                                        */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+static int
+fbt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t rval)
 {
-	uint32_t *tinstr = (uint32_t *)tramp->fbtt_next;
-	uint32_t first = *instr;
-	uintptr_t va = tramp->fbtt_va;
-	uintptr_t base = tramp->fbtt_next;
-
-	if (tramp->fbtt_next + FBT_ENTENT_MAXSIZE > tramp->fbtt_limit) {
-		/*
-		 * There isn't sufficient room for this entry; return failure.
-		 */
-		return (0);
-	}
-
-	FBT_COUNTER(id, fbt_entry);
-
-	if (FBT_IS_SAVE(first)) {
-		*tinstr++ = first;
-	} else {
-		*tinstr++ = FBT_SAVEIMM(FBT_REG_O6, -SA(MINFRAME), FBT_REG_O6);
-	}
-
-	if (id > (uint32_t)FBT_SIMM13_MAX) {
-		*tinstr++ = FBT_SETHI(id, FBT_REG_O0);
-		*tinstr++ = FBT_ORLO(FBT_REG_O0, id, FBT_REG_O0);
-	} else {
-		*tinstr++ = FBT_ORSIMM13(FBT_REG_G0, id, FBT_REG_O0);
-	}
-
-	if (nargs >= 1)
-		*tinstr++ = FBT_MOV(FBT_REG_I0, FBT_REG_O1);
-
-	if (nargs >= 2)
-		*tinstr++ = FBT_MOV(FBT_REG_I1, FBT_REG_O2);
-
-	if (nargs >= 3)
-		*tinstr++ = FBT_MOV(FBT_REG_I2, FBT_REG_O3);
+	uintptr_t stack0, stack1, stack2, stack3, stack4;
+	fbt_probe_t *fbt = fbt_probetab[FBT_ADDR2NDX(addr)];
 
-	if (nargs >= 4)
-		*tinstr++ = FBT_MOV(FBT_REG_I3, FBT_REG_O4);
-
-	if (nargs >= 5)
-		*tinstr++ = FBT_MOV(FBT_REG_I4, FBT_REG_O5);
-
-	if (FBT_IS_SAVE(first)) {
-		uintptr_t ret = (uintptr_t)instr - sizeof (uint32_t);
-
-		*tinstr++ = FBT_SETHI(ret, FBT_REG_G1);
-		*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dtrace_probe);
-		tinstr++;
-		*tinstr++ = FBT_ORLO(FBT_REG_G1, ret, FBT_REG_O7);
-	} else {
-		uintptr_t slot = *--tinstr;
-		uintptr_t ret = (uintptr_t)instr + sizeof (uint32_t);
-		uint32_t delay = first;
+	for (; fbt != NULL; fbt = fbt->fbtp_hashnext) {
+		if ((uintptr_t)fbt->fbtp_patchpoint == addr) {
+			if (fbt->fbtp_roffset == 0) {
+				int i = 0;
+				/*
+				 * When accessing the arguments on the stack,
+				 * we must protect against accessing beyond
+				 * the stack.  We can safely set NOFAULT here
+				 * -- we know that interrupts are already
+				 * disabled.
+				 */
+				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+				CPU->cpu_dtrace_caller = stack[i++];
+#ifdef __amd64
+				/*
+				 * On amd64, stack[0] contains the dereferenced
+				 * stack pointer, stack[1] contains savfp,
+				 * stack[2] contains savpc.  We want to step
+				 * over these entries.
+				 */
+				i += 2;
+#endif
+				stack0 = stack[i++];
+				stack1 = stack[i++];
+				stack2 = stack[i++];
+				stack3 = stack[i++];
+				stack4 = stack[i++];
+				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
+				    CPU_DTRACE_BADADDR);
 
-		*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dtrace_probe);
-		tinstr++;
-		*tinstr++ = slot;
-		*tinstr++ = FBT_RESTORE(FBT_REG_G0, FBT_REG_G0, FBT_REG_G0);
+				dtrace_probe(fbt->fbtp_id, stack0, stack1,
+				    stack2, stack3, stack4);
 
-		if (FBT_IS_BA(first) || FBT_IS_BAPCC(first)) {
-			/*
-			 * This is a special case:  we are instrumenting a
-			 * a non-annulled branch-always (or variant).  We'll
-			 * return directly to the destination of the branch,
-			 * copying the instruction in the delay slot here,
-			 * and then executing it in the slot of a ba.
-			 */
-			if (FBT_IS_BA(first)) {
-				ret = FBT_BDEST(instr, *instr);
+				CPU->cpu_dtrace_caller = NULL;
 			} else {
-				ret = FBT_BPCCDEST(instr, *instr);
+#ifdef __amd64
+				/*
+				 * On amd64, we instrument the ret, not the
+				 * leave.  We therefore need to set the caller
+				 * to assure that the top frame of a stack()
+				 * action is correct.
+				 */
+				DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+				CPU->cpu_dtrace_caller = stack[0];
+				DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
+				    CPU_DTRACE_BADADDR);
+#endif
+
+				dtrace_probe(fbt->fbtp_id, fbt->fbtp_roffset,
+				    rval, 0, 0, 0);
+				CPU->cpu_dtrace_caller = NULL;
 			}
 
-			delay = *(instr + 1);
-		}
-
-		if ((first & FBT_OP_MASK) != FBT_OP0 ||
-		    (first & FBT_FMT2_OP2_MASK) != FBT_FMT2_OP2_BPR) {
-			*tinstr = FBT_BA((uintptr_t)tinstr - base + va, ret);
-			tinstr++;
-			*tinstr++ = delay;
-		} else {
-			/*
-			 * If this is a branch-on-register, we have a little
-			 * more work to do:  because the displacement is only
-			 * sixteen bits, we're going to thunk the branch into
-			 * the trampoline, and then ba,a to the appropriate
-			 * destination in the branch targets.  That is, we're
-			 * constructing this sequence in the trampoline:
-			 *
-			 *		br[cc]	%[rs], 1f
-			 *		<delay-instruction>
-			 *		ba,a	<not-taken-destination>
-			 *	1:	ba,a	<taken-destination>
-			 *
-			 */
-			uintptr_t targ = FBT_BPRDEST(instr, first);
-
-			*tinstr = first & ~(FBT_DISP16_MASK);
-			*tinstr |= FBT_DISP14(tinstr, &tinstr[3]);
-			tinstr++;
-			*tinstr++ = *(instr + 1);
-			*tinstr = FBT_BAA((uintptr_t)tinstr - base + va,
-			    ret + sizeof (uint32_t));
-			tinstr++;
-			*tinstr = FBT_BAA((uintptr_t)tinstr - base + va, targ);
-			tinstr++;
+			return (fbt->fbtp_rval);
 		}
 	}
 
-	tramp->fbtt_va += (uintptr_t)tinstr - tramp->fbtt_next;
-	tramp->fbtt_next = (uintptr_t)tinstr;
-
-	return (1);
-}
-
-/*
- * We are patching control-transfer/restore couplets.  There are three
- * variants of couplet:
- *
- * (a)	return		rs1 + imm
- *	delay
- *
- * (b)	jmpl		rs1 + (rs2 | offset), rd
- *	restore		rs1, rs2 | imm, rd
- *
- * (c)	call		displacement
- *	restore		rs1, rs2 | imm, rd
- *
- * If rs1 in (a) is anything other than %i7, or imm is anything other than 8,
- * or delay is a DCTI, we fail.  If rd from the jmpl in (b) is something other
- * than %g0 (a ret or a tail-call through a function pointer) or %o7 (a call
- * through a register), we fail.
- *
- * Note that rs1 and rs2 in the restore instructions in (b) and (c) are
- * potentially outputs and/or globals.  Because these registers cannot be
- * relied upon across the call to dtrace_probe(), we move rs1 into an unused
- * local, ls0, and rs2 into an unused local, ls1, and restructure the restore
- * to be:
- *
- *	restore		ls0, ls1, rd
- *
- * Likewise, rs1 and rs2 in the jmpl of case (b) may be outputs and/or globals.
- * If the jmpl uses outputs or globals, we restructure it to be:
- *
- * 	jmpl		ls2 + (ls3 | offset), (%g0 | %o7)
- *
- */
-/*ARGSUSED*/
-static int
-fbt_canpatch_return(uint32_t *instr, int offset, const char *name)
-{
-	int rd;
-
-	if (FBT_FMT3_OP(*instr) == FBT_OP_RETURN) {
-		uint32_t delay = *(instr + 1);
-
-		if (*instr != FBT_RETURN(FBT_REG_I7, 8)) {
-			/*
-			 * It's unclear if we should warn about this or not.
-			 * We really wouldn't expect the compiler to generate
-			 * return instructions with something other than %i7
-			 * as rs1 and 8 as the simm13 -- it would just be
-			 * mean-spirited.  That said, such a construct isn't
-			 * necessarily incorrect.  Sill, we err on the side of
-			 * caution and warn about it...
-			 */
-			cmn_err(CE_NOTE, "cannot instrument return of %s at "
-			    "%p: non-canonical return instruction", name,
-			    (void *)instr);
-			return (0);
-		}
-
-		if (FBT_IS_CTI(delay)) {
-			/*
-			 * This is even weirder -- a DCTI coupled with a
-			 * return instruction.  Similar constructs are used to
-			 * return from utraps, but these typically have the
-			 * return in the slot -- and we wouldn't expect to see
-			 * it in the kernel regardless.  At any rate, we don't
-			 * want to try to instrument this construct, whatever
-			 * it may be.
-			 */
-			cmn_err(CE_NOTE, "cannot instrument return of %s at "
-			    "%p: CTI in delay slot of return instruction",
-			    name, (void *)instr);
-			return (0);
-		}
-
-		if (FBT_IS_PCRELATIVE(delay)) {
-			/*
-			 * This is also very weird, but might be correct code
-			 * if the function is (for example) returning the
-			 * address of the delay instruction of the return as
-			 * its return value (e.g. "rd %pc, %o0" in the slot).
-			 * Perhaps correct, but still too weird to not warn
-			 * about it...
-			 */
-			cmn_err(CE_NOTE, "cannot instrument return of %s at "
-			    "%p: PC-relative instruction in delay slot of "
-			    "return instruction", name, (void *)instr);
-			return (0);
-		}
-
-		return (1);
-	}
-
-	if (FBT_FMT3_OP(*(instr + 1)) != FBT_OP_RESTORE)
-		return (0);
-
-	if (FBT_FMT1_OP(*instr) == FBT_OP_CALL)
-		return (1);
-
-	if (FBT_FMT3_OP(*instr) != FBT_OP_JMPL)
-		return (0);
-
-	rd = FBT_FMT3_RD(*instr);
-
-	if (rd == FBT_REG_I7 || rd == FBT_REG_O7 || rd == FBT_REG_G0)
-		return (1);
-
-	/*
-	 * We have encountered a jmpl that is storing the calling %pc in
-	 * some register besides %i7, %o7 or %g0.  This is strange; emit
-	 * a warning and fail.
-	 */
-	cmn_err(CE_NOTE, "cannot instrument return of %s at %p: unexpected "
-	    "jmpl destination register", name, (void *)instr);
 	return (0);
 }
 
-static int
-fbt_canpatch_retl(uint32_t *instr, int offset, const char *name)
-{
-	if (FBT_FMT1_OP(*instr) == FBT_OP_CALL ||
-	    (FBT_FMT3_OP(*instr) == FBT_OP_JMPL &&
-	    FBT_FMT3_RD(*instr) == FBT_REG_O7)) {
-		/*
-		 * If this is a call (or a jmpl that links into %o7), we can
-		 * patch it iff the next instruction uses %o7 as a destination
-		 * register.  Because there is an ABI responsibility to
-		 * restore %o7 to the value before the call/jmpl, we don't
-		 * particularly care how this routine is managing to restore
-		 * it (mov, add, ld or divx for all we care).  If it doesn't
-		 * seem to be restoring it at all, however, we'll refuse
-		 * to patch it.
-		 */
-		uint32_t delay = *(instr + 1);
-		uint32_t op, rd;
-
-		op = FBT_FMT1_OP(delay);
-		rd = FBT_FMT3_RD(delay);
-
-		if (op != FBT_OP2 || rd != FBT_REG_O7) {
-			/*
-			 * This is odd.  Before we assume that we're looking
-			 * at something bizarre (and warn accordingly), we'll
-			 * check to see if it's obviously a jump table entry.
-			 */
-			if (*instr < (uintptr_t)instr &&
-			    *instr >= (uintptr_t)instr - offset)
-				return (0);
-
-			cmn_err(CE_NOTE, "cannot instrument return of %s at "
-			    "%p: leaf jmpl/call delay isn't restoring %%o7",
-			    name, (void *)instr);
-			return (0);
-		}
-
-		return (1);
-	}
-
-	if (offset == sizeof (uint32_t)) {
-		/*
-		 * If this is the second instruction in the function, we're
-		 * going to allow it to be patched if the first instruction
-		 * is a patchable return-from-leaf instruction.
-		 */
-		if (fbt_canpatch_retl(instr - 1, 0, name))
-			return (1);
-	}
-
-	if (FBT_FMT3_OP(*instr) != FBT_OP_JMPL)
-		return (0);
-
-	if (FBT_FMT3_RD(*instr) != FBT_REG_G0)
-		return (0);
-
-	return (1);
-}
-
-/*ARGSUSED*/
-static uint32_t
-fbt_patch_return(uint32_t *instr, uint32_t *funcbase, uint32_t *funclim,
-    int offset, uint32_t id, fbt_trampoline_t *tramp, const char *name)
-{
-	uint32_t *tinstr = (uint32_t *)tramp->fbtt_next;
-	uint32_t cti = *instr, restore = *(instr + 1), rs1, dest;
-	uintptr_t va = tramp->fbtt_va;
-	uintptr_t base = tramp->fbtt_next;
-	uint32_t locals[FBT_REG_NLOCALS], local;
-
-	if (tramp->fbtt_next + FBT_RETENT_MAXSIZE > tramp->fbtt_limit) {
-		/*
-		 * There isn't sufficient room for this entry; return failure.
-		 */
-		return (FBT_ILLTRAP);
-	}
-
-	FBT_COUNTER(id, fbt_ret);
-
-	if (FBT_FMT3_OP(*instr) == FBT_OP_RETURN) {
-		/*
-		 * To handle the case of the return instruction, we'll emit a
-		 * restore, followed by the instruction in the slot (which
-		 * we'll transplant here), and then another save.  While it
-		 * may seem intellectually unsatisfying to emit the additional
-		 * restore/save couplet, one can take solace in the fact that
-		 * we don't do this if the instruction in the return delay
-		 * slot is a nop -- which it is nearly 90% of the time with
-		 * gcc.  (And besides, this couplet can't induce unnecessary
-		 * spill/fill traps; rewriting the delay instruction to be
-		 * in terms of the current window hardly seems worth the
-		 * trouble -- let alone the risk.)
-		 */
-		uint32_t delay = *(instr + 1);
-		ASSERT(*instr == FBT_RETURN(FBT_REG_I7, 8));
-
-		cti = FBT_RET;
-		restore = FBT_RESTORE(FBT_REG_G0, FBT_REG_G0, FBT_REG_G0);
-
-		if (delay != FBT_SETHI(0, FBT_REG_G0)) {
-			*tinstr++ = restore;
-			*tinstr++ = delay;
-			*tinstr++ = FBT_SAVEIMM(FBT_REG_O6,
-			    -SA(MINFRAME), FBT_REG_O6);
-		}
-	}
-
-	FBT_REG_INITLOCALS(local, locals);
-
-	/*
-	 * Mark the locals used in the jmpl.
-	 */
-	if (FBT_FMT3_OP(cti) == FBT_OP_JMPL) {
-		uint32_t rs1 = FBT_FMT3_RS1(cti);
-		FBT_REG_MARKLOCAL(locals, rs1);
-
-		if (!FBT_FMT3_ISIMM(cti)) {
-			uint32_t rs2 = FBT_FMT3_RS2(cti);
-			FBT_REG_MARKLOCAL(locals, rs2);
-		}
-	}
-
-	/*
-	 * And mark the locals used in the restore.
-	 */
-	rs1 = FBT_FMT3_RS1(restore);
-	FBT_REG_MARKLOCAL(locals, rs1);
-
-	if (!FBT_FMT3_ISIMM(restore)) {
-		uint32_t rs2 = FBT_FMT3_RS2(restore);
-		FBT_REG_MARKLOCAL(locals, rs2);
-	}
-
-	if (FBT_FMT3_OP(cti) == FBT_OP_JMPL) {
-		uint32_t rs1 = FBT_FMT3_RS1(cti);
-
-		if (FBT_REG_ISVOLATILE(rs1)) {
-			FBT_REG_ALLOCLOCAL(local, locals);
-			FBT_FMT3_RS1_SET(cti, local);
-			*tinstr++ = FBT_MOV(rs1, local);
-		}
-
-		if (!FBT_FMT3_ISIMM(cti)) {
-			uint32_t rs2 = FBT_FMT3_RS2(cti);
-
-			if (FBT_REG_ISVOLATILE(rs2)) {
-				FBT_REG_ALLOCLOCAL(local, locals);
-				FBT_FMT3_RS2_SET(cti, local);
-				*tinstr++ = FBT_MOV(rs2, local);
-			}
-		}
-	}
-
-	rs1 = FBT_FMT3_RS1(restore);
-
-	if (FBT_REG_ISVOLATILE(rs1)) {
-		FBT_REG_ALLOCLOCAL(local, locals);
-		FBT_FMT3_RS1_SET(restore, local);
-		*tinstr++ = FBT_MOV(rs1, local);
-	}
-
-	if (!FBT_FMT3_ISIMM(restore)) {
-		uint32_t rs2 = FBT_FMT3_RS2(restore);
-
-		if (FBT_REG_ISVOLATILE(rs2)) {
-			FBT_REG_ALLOCLOCAL(local, locals);
-			FBT_FMT3_RS2_SET(restore, local);
-			*tinstr++ = FBT_MOV(rs2, local);
-		}
-	}
-
-	if (id > (uint32_t)FBT_SIMM13_MAX) {
-		*tinstr++ = FBT_SETHI(id, FBT_REG_O0);
-		*tinstr++ = FBT_ORLO(FBT_REG_O0, id, FBT_REG_O0);
-	} else {
-		*tinstr++ = FBT_ORSIMM13(FBT_REG_G0, id, FBT_REG_O0);
-	}
-
-	if (offset > (uint32_t)FBT_SIMM13_MAX) {
-		*tinstr++ = FBT_SETHI(offset, FBT_REG_O1);
-		*tinstr++ = FBT_ORLO(FBT_REG_O1, offset, FBT_REG_O1);
-	} else {
-		*tinstr++ = FBT_ORSIMM13(FBT_REG_G0, offset, FBT_REG_O1);
-	}
+/*========================= End of Function ========================*/
 
-	*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dtrace_probe);
-	tinstr++;
-
-	if (FBT_FMT3_RD(restore) == FBT_REG_O0) {
-		/*
-		 * If the destination register of the restore is %o0, we
-		 * need to perform the implied calculation to derive the
-		 * return value.
-		 */
-		uint32_t add = (restore & ~FBT_FMT3_OP_MASK) | FBT_OP_ADD;
-		add &= ~FBT_FMT3_RD_MASK;
-		*tinstr++ = add | (FBT_REG_O2 << FBT_FMT3_RD_SHIFT);
-	} else {
-		*tinstr++ = FBT_MOV(FBT_REG_I0, FBT_REG_O2);
-	}
-
-	/*
-	 * If the control transfer instruction is %pc-relative (i.e. a
-	 * call), we need to reset it appropriately.
-	 */
-	if (FBT_FMT1_OP(cti) == FBT_OP_CALL) {
-		dest = (uintptr_t)instr + (FBT_FMT1_DISP30(cti) << 2);
-		*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dest);
-		tinstr++;
-	} else {
-		*tinstr++ = cti;
-	}
-
-	*tinstr++ = restore;
-	tramp->fbtt_va += (uintptr_t)tinstr - tramp->fbtt_next;
-	tramp->fbtt_next = (uintptr_t)tinstr;
-
-	return (FBT_BAA(instr, va));
-}
-
-static uint32_t
-fbt_patch_retl(uint32_t *instr, uint32_t *funcbase, uint32_t *funclim,
-    int offset, uint32_t id, fbt_trampoline_t *tramp, const char *name)
-{
-	uint32_t *tinstr = (uint32_t *)tramp->fbtt_next;
-	uintptr_t va = tramp->fbtt_va;
-	uintptr_t base = tramp->fbtt_next;
-	uint32_t cti = *instr, dest;
-	int annul = 0;
-
-	FBT_COUNTER(id, fbt_retl);
-
-	if (tramp->fbtt_next + FBT_RETLENT_MAXSIZE > tramp->fbtt_limit) {
-		/*
-		 * There isn't sufficient room for this entry; return failure.
-		 */
-		return (FBT_ILLTRAP);
-	}
-
-	if (offset == sizeof (uint32_t) &&
-	    fbt_canpatch_retl(instr - 1, 0, name)) {
-		*tinstr++ = *instr;
-		annul = 1;
-		FBT_COUNTER(id, fbt_retl_twoinstr);
-	} else {
-		if (FBT_FMT3_OP(cti) == FBT_OP_JMPL &&
-		    FBT_FMT3_RD(cti) != FBT_REG_O7 &&
-		    FBT_FMT3_RS1(cti) != FBT_REG_O7) {
-			annul = 1;
-			*tinstr++ = *(instr + 1);
-		}
-	}
-
-	*tinstr++ = FBT_SAVEIMM(FBT_REG_O6, -SA(MINFRAME), FBT_REG_O6);
-
-	if (FBT_FMT3_OP(cti) == FBT_OP_JMPL) {
-		uint32_t rs1, rs2, o2i = FBT_REG_I0 - FBT_REG_O0;
-
-		/*
-		 * If we have a jmpl and it's in terms of output registers, we
-		 * need to rewrite it to be in terms of the corresponding input
-		 * registers.  If it's in terms of the globals, we'll rewrite
-		 * it to be in terms of locals.
-		 */
-		rs1 = FBT_FMT3_RS1(cti);
-
-		if (FBT_REG_ISOUTPUT(rs1))
-			rs1 += o2i;
-
-		if (FBT_REG_ISGLOBAL(rs1)) {
-			*tinstr++ = FBT_MOV(rs1, FBT_REG_L0);
-			rs1 = FBT_REG_L0;
-		}
-
-		FBT_FMT3_RS1_SET(cti, rs1);
-
-		if (!FBT_FMT3_ISIMM(cti)) {
-			rs2 = FBT_FMT3_RS2(cti);
-
-			if (FBT_REG_ISOUTPUT(rs2))
-				rs2 += o2i;
-
-			if (FBT_REG_ISGLOBAL(rs2)) {
-				*tinstr++ = FBT_MOV(rs2, FBT_REG_L1);
-				rs2 = FBT_REG_L1;
-			}
-
-			FBT_FMT3_RS2_SET(cti, rs2);
-		}
-
-		/*
-		 * Now we need to check the rd and source register for the jmpl;
-		 * If neither rd nor the source register is %o7, then we might
-		 * have a jmp that is actually part of a jump table.  We need
-		 * to generate the code to compare it to the base and limit of
-		 * the function.
-		 */
-		if (FBT_FMT3_RD(cti) != FBT_REG_O7 && rs1 != FBT_REG_I7) {
-			uintptr_t base = (uintptr_t)funcbase;
-			uintptr_t limit = (uintptr_t)funclim;
-
-			FBT_COUNTER(id, fbt_retl_jmptab);
-
-			if (FBT_FMT3_ISIMM(cti)) {
-				*tinstr++ = FBT_ADDSIMM13(rs1,
-				    FBT_FMT3_SIMM13(cti), FBT_REG_L2);
-			} else {
-				*tinstr++ = FBT_ADD(rs1, rs2, FBT_REG_L2);
-			}
-
-			*tinstr++ = FBT_SETHI(base, FBT_REG_L3);
-			*tinstr++ = FBT_ORLO(FBT_REG_L3, base, FBT_REG_L3);
-			*tinstr++ = FBT_CMP(FBT_REG_L2, FBT_REG_L3);
-			*tinstr++ = FBT_BL(0, 8 * sizeof (uint32_t));
-			*tinstr++ = FBT_SETHI(limit, FBT_REG_L3);
-			*tinstr++ = FBT_ORLO(FBT_REG_L3, limit, FBT_REG_L3);
-			*tinstr++ = FBT_CMP(FBT_REG_L2, FBT_REG_L3);
-			*tinstr++ = FBT_BGE(0, 4 * sizeof (uint32_t));
-			*tinstr++ = FBT_SETHI(0, FBT_REG_G0);
-			*tinstr++ = cti;
-			*tinstr++ = FBT_RESTORE(FBT_REG_G0,
-			    FBT_REG_G0, FBT_REG_G0);
-		}
-	}
-
-	if (id > (uint32_t)FBT_SIMM13_MAX) {
-		*tinstr++ = FBT_SETHI(id, FBT_REG_O0);
-		*tinstr++ = FBT_ORLO(FBT_REG_O0, id, FBT_REG_O0);
-	} else {
-		*tinstr++ = FBT_ORSIMM13(FBT_REG_G0, id, FBT_REG_O0);
-	}
-
-	if (offset > (uint32_t)FBT_SIMM13_MAX) {
-		*tinstr++ = FBT_SETHI(offset, FBT_REG_O1);
-		*tinstr++ = FBT_ORLO(FBT_REG_O1, offset, FBT_REG_O1);
-	} else {
-		*tinstr++ = FBT_ORSIMM13(FBT_REG_G0, offset, FBT_REG_O1);
-	}
-
-	*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dtrace_probe);
-	tinstr++;
-	*tinstr++ = FBT_MOV(FBT_REG_I0, FBT_REG_O2);
-
-	/*
-	 * If the control transfer instruction is %pc-relative (i.e. a
-	 * call), we need to reset it appropriately.
-	 */
-	if (FBT_FMT1_OP(cti) == FBT_OP_CALL) {
-		FBT_COUNTER(id, fbt_retl_tailcall);
-		dest = (uintptr_t)instr + (FBT_FMT1_DISP30(cti) << 2);
-		*tinstr = FBT_CALL((uintptr_t)tinstr - base + va, dest);
-		tinstr++;
-		annul = 1;
-	} else {
-		if (FBT_FMT3_OP(cti) == FBT_OP_JMPL) {
-			*tinstr++ = cti;
-
-			if (FBT_FMT3_RD(cti) == FBT_REG_O7) {
-				FBT_COUNTER(id, fbt_retl_tailjmpl);
-				annul = 1;
-			}
-		} else {
-			*tinstr++ = FBT_RET;
-		}
-	}
-
-	*tinstr++ = FBT_RESTORE(FBT_REG_G0, FBT_REG_G0, FBT_REG_G0);
-
-	tramp->fbtt_va += (uintptr_t)tinstr - tramp->fbtt_next;
-	tramp->fbtt_next = (uintptr_t)tinstr;
-
-	return (annul ? FBT_BAA(instr, va) : FBT_BA(instr, va));
-}
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_provide_module.                               */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 /*ARGSUSED*/
 static void
 fbt_provide_module(void *arg, struct modctl *ctl)
 {
 	struct module *mp = ctl->mod_mp;
-	char *modname = ctl->mod_modname;
-	char *str = mp->strings;
-	int nsyms = mp->nsyms;
-	Shdr *symhdr = mp->symhdr;
-	size_t symsize;
-	char *name;
-	int i;
+	char   *str     = mp->strings;
+	int    nsyms    = mp->nsyms;
+	Shdr   *symhdr  = mp->symhdr;
+	char   *modname = ctl->mod_modname;
+	char   *name;
+	RSY1_t *rsy;
+	RR_t   *rr;
 	fbt_probe_t *fbt, *retfbt;
-	fbt_trampoline_t tramp;
-	uintptr_t offset;
-	int primary = 0;
-	ctf_file_t *fp = NULL;
-	int error;
-	int estimate = 1;
-	uint32_t faketramp[50];
-	size_t fbt_size = 0;
+	size_t symsize;
+	int i, size;
+	uint8_t fmt;
 
 	/*
 	 * Employees of dtrace and their families are ineligible.  Void
@@ -1062,42 +358,10 @@
 		return;
 	}
 
-	if (mp->fbt_tab != NULL)
-		estimate = 0;
-
-	/*
-	 * This is a hack for unix/genunix/krtld.
-	 */
-	primary = vmem_contains(heap_arena, (void *)ctl,
-	    sizeof (struct modctl)) == 0;
-	kobj_textwin_alloc(mp);
-
-	/*
-	 * Open the CTF data for the module.  We'll use this to determine the
-	 * functions that can be instrumented.  Note that this call can fail,
-	 * in which case we'll use heuristics to determine the functions that
-	 * can be instrumented.  (But in particular, leaf functions will not be
-	 * instrumented.)
-	 */
-	fp = ctf_modopen(mp, &error);
-
-forreal:
-	if (!estimate) {
-		tramp.fbtt_next =
-		    (uintptr_t)fbt_trampoline_map((uintptr_t)mp->fbt_tab,
-		    mp->fbt_size);
-		tramp.fbtt_limit = tramp.fbtt_next + mp->fbt_size;
-		tramp.fbtt_va = (uintptr_t)mp->fbt_tab;
-	}
-
 	for (i = 1; i < nsyms; i++) {
-		ctf_funcinfo_t f;
-		uint32_t *instr, *base, *limit;
+		uint8_t *instr, *limit;
 		Sym *sym = (Sym *)(symhdr->sh_addr + i * symsize);
-		int have_ctf = 0, is_leaf = 0, nargs, cti = 0;
-		int (*canpatch)(uint32_t *, int, const char *);
-		uint32_t (*patch)(uint32_t *, uint32_t *, uint32_t *, int,
-		    uint32_t, fbt_trampoline_t *, const char *);
+		int j;
 
 		if (ELF_ST_TYPE(sym->st_info) != STT_FUNC)
 			continue;
@@ -1134,47 +398,6 @@
 			continue;
 		}
 
-		if (strstr(name, "__relocatable") != NULL) {
-			/*
-			 * Anything with the string "__relocatable" anywhere
-			 * in the function name is considered to be a function
-			 * that may be manually relocated before execution.
-			 * Because FBT uses a PC-relative technique for
-			 * instrumentation, these functions cannot safely
-			 * be instrumented by us.
-			 */
-			continue;
-		}
-
-		if (strstr(name, "ip_ocsum") == name) {
-			/*
-			 * The ip_ocsum_* family of routines are all ABI
-			 * violators.  (They expect incoming arguments in the
-			 * globals!)  Break the ABI?  No soup for you!
-			 */
-			continue;
-		}
-
-		/*
-		 * We want to scan the function for one (and only one) save.
-		 * Any more indicates that something fancy is going on.
-		 */
-		base = (uint32_t *)sym->st_value;
-		limit = (uint32_t *)(sym->st_value + sym->st_size);
-
-		/*
-		 * We don't want to interpose on the module stubs.
-		 */
-		if (base >= (uint32_t *)stubs_base &&
-		    base <= (uint32_t *)stubs_end)
-			continue;
-
-		/*
-		 * We can't safely trace a zero-length function...
-		 */
-		if (base == limit)
-			continue;
-
 		/*
 		 * Due to 4524008, _init and _fini may have a bloated st_size.
 		 * While this bug was fixed quite some time ago, old drivers
@@ -1194,335 +417,194 @@
 		if (strcmp(name, "_fini") == 0)
 			continue;
 
-		instr = base;
-
 		/*
-		 * While we try hard to only trace safe functions (that is,
-		 * functions at TL=0), one unsafe function manages to otherwise
-		 * appear safe:  prom_trap().  We could discover prom_trap()
-		 * if we added an additional rule:  in order to trace a
-		 * function, we must either (a) discover a restore or (b)
-		 * determine that the function does not have any unlinked
-		 * control transfers to another function (i.e., the function
-		 * never returns).  Unfortunately, as of this writing, one
-		 * legitimate function (resume_from_zombie()) transfers
-		 * control to a different function (_resume_from_idle())
-		 * without executing a restore.  Barring a rule to figure out
-		 * that resume_from_zombie() is safe while prom_trap() is not,
-		 * we resort to hard-coding prom_trap() here.
+		 * In order to be eligible, the function must begin with the
+		 * following sequence:
+		 *
+		 * 	stmg	%rx,%ry,xxx
 		 */
-		if (strcmp(name, "prom_trap") == 0)
-			continue;
-
-		if (fp != NULL && ctf_func_info(fp, i, &f) != CTF_ERR) {
-			nargs = f.ctc_argc;
-			have_ctf = 1;
-		} else {
-			nargs = 32;
-		}
-
-		/*
-		 * If the first instruction of the function is a branch and
-		 * it's not a branch-always-not-annulled, we're going to refuse
-		 * to patch it.
-		 */
-		if ((*instr & FBT_OP_MASK) == FBT_OP0 &&
-		    (*instr & FBT_FMT2_OP2_MASK) != FBT_FMT2_OP2_SETHI &&
-		    (*instr & FBT_FMT2_OP2_MASK) != FBT_FMT2_OP2_BPR) {
-			if (!FBT_IS_BA(*instr) && !FBT_IS_BAPCC(*instr)) {
-				if (have_ctf) {
-					cmn_err(CE_NOTE, "cannot instrument %s:"
-					    " begins with non-ba, "
-					    "non-br CTI", name);
-				}
-				continue;
-			}
-		}
-
-		while (!FBT_IS_SAVE(*instr)) {
-			/*
-			 * Before we assume that this is a leaf routine, check
-			 * forward in the basic block for a save.
-			 */
-			int op = *instr & FBT_OP_MASK;
-			int op2 = *instr & FBT_FMT2_OP2_MASK;
+		instr = (uint8_t *)sym->st_value;
+		limit = (uint8_t *)(sym->st_value + sym->st_size);
 
-			if (op == FBT_OP0 && op2 != FBT_FMT2_OP2_SETHI) {
-				/*
-				 * This is a CTI.  If we see a subsequent
-				 * save, we will refuse to process this
-				 * routine unless both of the following are
-				 * true:
-				 *
-				 *  (a)	The branch is not annulled
-				 *
-				 *  (b)	The subsequent save is in the delay
-				 *	slot of the branch
-				 */
-				if ((*instr & FBT_ANNUL) ||
-				    !FBT_IS_SAVE(*(instr + 1))) {
-					cti = 1;
-				} else {
-					instr++;
-					break;
-				}
-			}
-
-			if (op == FBT_OP1)
-				cti = 1;
-
-			if (++instr == limit)
+		while (instr < limit) {
+			if ((size = dtrace_getfmtlen(instr, &fmt)) <= 0)
 				break;
-		}
 
-		if (instr < limit && cti) {
-			/*
-			 * If we found a CTI before the save, we need to not
-			 * do anything.  But if we have CTF information, this
-			 * is weird enough that it merits a message.
-			 */
-			if (!have_ctf)
-				continue;
-
-			cmn_err(CE_NOTE, "cannot instrument %s: "
-			    "save not in first basic block", name);
-			continue;
-		}
-
-		if (instr == limit) {
-			if (!have_ctf)
-				continue;
-			is_leaf = 1;
-
-			if (!estimate)
-				fbt_leaf_functions++;
-
-			canpatch = fbt_canpatch_retl;
-			patch = fbt_patch_retl;
-		} else {
-			canpatch = fbt_canpatch_return;
-			patch = fbt_patch_return;
-		}
-
-		if (!have_ctf && !is_leaf) {
-			/*
-			 * Before we assume that this isn't something tricky,
-			 * look for other saves.  If we find them, there are
-			 * multiple entry points here (or something), and we'll
-			 * leave it alone.
-			 */
-			while (++instr < limit) {
-				if (FBT_IS_SAVE(*instr))
+			if (fmt == IFMT_RSY1) {
+				rsy = (RSY1_t *) instr;
+				if ((rsy->op1 == OP_STMG1) && (rsy->op2 == OP_STMG2)) 
 					break;
 			}
 
-			if (instr != limit)
-				continue;
+			instr += size;
+		}
+
+		if (instr >= limit) {
+			/*
+			 * We either don't save the frame pointer in this
+			 * function, or we ran into some disassembly
+			 * screw-up.  Either way, we bail.
+			 */
+			continue;
 		}
 
-		instr = base;
-
-		if (FBT_IS_CTI(*instr)) {
-			/*
-			 * If we have a CTI, we want to be sure that we don't
-			 * have a CTI or a PC-relative instruction in the
-			 * delay slot -- we want to be able to thunk the
-			 * instruction into the trampoline without worrying
-			 * about either DCTIs or relocations.  It would be
-			 * very odd for the compiler to generate this kind of
-			 * code, so we warn about it if we have CTF
-			 * information.
-			 */
-			if (FBT_IS_CTI(*(instr + 1))) {
-				if (!have_ctf)
-					continue;
-
-				cmn_err(CE_NOTE, "cannot instrument %s: "
-				    "CTI in delay slot of first instruction",
-				    name);
-				continue;
-			}
-
-			if (FBT_IS_PCRELATIVE(*(instr + 1))) {
-				if (!have_ctf)
-					continue;
+		fbt		     = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);
+		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	     = ctl;
+		fbt->fbtp_loadcnt    = ctl->mod_loadcnt;
+		fbt->fbtp_rval	     = DTRACE_INVOP_STMG;
+		fbt->fbtp_savedval   = *instr;
+		fbt->fbtp_patchval   = FBT_PATCHVAL;
 
-				cmn_err(CE_NOTE, "cannot instrument %s: "
-				    "PC-relative instruction in delay slot of"
-				    " first instruction", name);
-				continue;
-			}
-		}
+		fbt->fbtp_hashnext   = fbt_probetab[FBT_ADDR2NDX(instr)];
+		fbt->fbtp_symndx     = i;
+		fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
 
-		if (estimate) {
-			tramp.fbtt_next = (uintptr_t)faketramp;
-			tramp.fbtt_limit = tramp.fbtt_next + sizeof (faketramp);
-			(void) fbt_patch_entry(instr, FBT_ESTIMATE_ID,
-			    &tramp, nargs);
-			fbt_size += tramp.fbtt_next - (uintptr_t)faketramp;
-		} else {
-			fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);
-			fbt->fbtp_name = name;
-			fbt->fbtp_ctl = ctl;
-			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
-			    name, FBT_PROBENAME_ENTRY, 1, fbt);
-			fbt->fbtp_patchval = FBT_BAA(instr, tramp.fbtt_va);
-
-			if (!fbt_patch_entry(instr, fbt->fbtp_id,
-			    &tramp, nargs)) {
-				cmn_err(CE_WARN, "unexpectedly short FBT table "
-				    "in module %s (sym %d of %d)", modname,
-				    i, nsyms);
-				break;
-			}
-
-			fbt->fbtp_patchpoint =
-			    (uint32_t *)((uintptr_t)mp->textwin +
-			    ((uintptr_t)instr - (uintptr_t)mp->text));
-			fbt->fbtp_savedval = *instr;
-
-			fbt->fbtp_loadcnt = ctl->mod_loadcnt;
-			fbt->fbtp_primary = primary;
-			fbt->fbtp_symndx = i;
-			mp->fbt_nentries++;
-		}
+		mp->fbt_nentries++;
 
 		retfbt = NULL;
 again:
-		if (++instr == limit)
+		if (instr >= limit)
+			continue;
+
+		/*
+		 * If this disassembly fails, then we've likely walked off into
+		 * a jump table or some other unsuitable area.  Bail out of the
+		 * disassembly now.
+		 */
+		if ((size = dtrace_getfmtlen(instr, &fmt)) <= 0)
 			continue;
 
-		offset = (uintptr_t)instr - (uintptr_t)base;
-
-		if (!(*canpatch)(instr, offset, name))
-			goto again;
+		/*
+		 * We only instrument BR %r14 or BR %r4 to avoid matching 
+		 * against a jump table.
+		 */
+		if (fmt == IFMT_RR) {
+			rr = (RR_t *) instr;
 
-		if (estimate) {
-			tramp.fbtt_next = (uintptr_t)faketramp;
-			tramp.fbtt_limit = tramp.fbtt_next + sizeof (faketramp);
-			(void) (*patch)(instr, base, limit,
-			    offset, FBT_ESTIMATE_ID, &tramp, name);
-			fbt_size += tramp.fbtt_next - (uintptr_t)faketramp;
-
-			goto again;
+			if (!((rr->opcode = OP_BR) && (rr->r1 == UNC) && 
+			      ((rr->r2 == R14) || (rr->r2 == R4)))) {
+				instr += size;
+				goto again;
+			}
 		}
 
-		fbt = kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);
-		fbt->fbtp_name = name;
-		fbt->fbtp_ctl = ctl;
+		fbt		= kmem_zalloc(sizeof (fbt_probe_t), KM_SLEEP);
+		fbt->fbtp_name	= name;
 
 		if (retfbt == NULL) {
 			fbt->fbtp_id = dtrace_probe_create(fbt_id, modname,
-			    name, FBT_PROBENAME_RETURN, 1, fbt);
+			    				   name, FBT_RETURN, 
+							   3, fbt);
 		} else {
 			retfbt->fbtp_next = fbt;
-			fbt->fbtp_id = retfbt->fbtp_id;
+			fbt->fbtp_id	  = retfbt->fbtp_id;
 		}
 
-		fbt->fbtp_return = 1;
-		retfbt = fbt;
+		retfbt		     = fbt;
+		fbt->fbtp_patchpoint = instr;
+		fbt->fbtp_ctl        = ctl;
+		fbt->fbtp_loadcnt    = ctl->mod_loadcnt;
 
-		if ((fbt->fbtp_patchval = (*patch)(instr, base, limit, offset,
-		    fbt->fbtp_id, &tramp, name)) == FBT_ILLTRAP) {
-			cmn_err(CE_WARN, "unexpectedly short FBT table "
-			    "in module %s (sym %d of %d)", modname, i, nsyms);
-			break;
-		}
+		fbt->fbtp_rval	     = DTRACE_INVOP_RET;
+		fbt->fbtp_roffset    = (uintptr_t)(instr - (uint8_t *)sym->st_value);
 
-		fbt->fbtp_patchpoint = (uint32_t *)((uintptr_t)mp->textwin +
-		    ((uintptr_t)instr - (uintptr_t)mp->text));
-		fbt->fbtp_savedval = *instr;
-		fbt->fbtp_loadcnt = ctl->mod_loadcnt;
-		fbt->fbtp_primary = primary;
-		fbt->fbtp_symndx = i;
+		fbt->fbtp_savedval   = *instr;
+		fbt->fbtp_patchval   = FBT_PATCHVAL;
+		fbt->fbtp_hashnext   = fbt_probetab[FBT_ADDR2NDX(instr)];
+		fbt->fbtp_symndx     = i;
+		fbt_probetab[FBT_ADDR2NDX(instr)] = fbt;
+
 		mp->fbt_nentries++;
 
+		instr += size;
 		goto again;
 	}
+}
 
-	if (estimate) {
-		/*
-		 * Slosh on another entry's worth...
-		 */
-		fbt_size += FBT_ENT_MAXSIZE;
-		mp->fbt_size = fbt_size;
-		mp->fbt_tab = kobj_texthole_alloc(mp->text, fbt_size);
+/*========================= End of Function ========================*/
 
-		if (mp->fbt_tab == NULL) {
-			cmn_err(CE_WARN, "couldn't allocate FBT table "
-			    "for module %s", modname);
-		} else {
-			estimate = 0;
-			goto forreal;
-		}
-	} else {
-		fbt_trampoline_unmap();
-	}
-
-error:
-	if (fp != NULL)
-		ctf_close(fp);
-}
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_destroy.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 /*ARGSUSED*/
 static void
 fbt_destroy(void *arg, dtrace_id_t id, void *parg)
 {
-	fbt_probe_t *fbt = parg, *next;
+	fbt_probe_t *fbt = parg, *next, *hash, *last;
 	struct modctl *ctl = fbt->fbtp_ctl;
+	int ndx;
 
 	do {
 		if (ctl != NULL && ctl->mod_loadcnt == fbt->fbtp_loadcnt) {
 			if ((ctl->mod_loadcnt == fbt->fbtp_loadcnt &&
-			    ctl->mod_loaded) || fbt->fbtp_primary) {
+			    ctl->mod_loaded)) {
 				((struct module *)
 				    (ctl->mod_mp))->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;
 		kmem_free(fbt, sizeof (fbt_probe_t));
+
 		fbt = next;
 	} while (fbt != NULL);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_enable.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
-static void
+static int
 fbt_enable(void *arg, dtrace_id_t id, void *parg)
 {
-	fbt_probe_t *fbt = parg, *f;
+	fbt_probe_t *fbt = parg;
 	struct modctl *ctl = fbt->fbtp_ctl;
 
 	ctl->mod_nenabled++;
 
-	for (f = fbt; f != NULL; f = f->fbtp_next) {
-		if (f->fbtp_patchpoint == NULL) {
-			/*
-			 * Due to a shortened FBT table, this entry was never
-			 * completed; refuse to enable it.
-			 */
-			if (fbt_verbose) {
-				cmn_err(CE_NOTE, "fbt is failing for probe %s "
-				    "(short FBT table in %s)",
-				    fbt->fbtp_name, ctl->mod_modname);
-			}
-
-			return;
-		}
-	}
-
-	/*
-	 * If this module has disappeared since we discovered its probes,
-	 * refuse to enable it.
-	 */
-	if (!fbt->fbtp_primary && !ctl->mod_loaded) {
+	if (!ctl->mod_loaded) {
 		if (fbt_verbose) {
 			cmn_err(CE_NOTE, "fbt is failing for probe %s "
 			    "(module %s unloaded)",
 			    fbt->fbtp_name, ctl->mod_modname);
 		}
 
-		return;
+		return (0);
 	}
 
 	/*
@@ -1537,36 +619,52 @@
 			    fbt->fbtp_name, ctl->mod_modname);
 		}
 
-		return;
+		return (0);
 	}
 
 	for (; fbt != NULL; fbt = fbt->fbtp_next)
 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
+
+	return (0);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_disable.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static void
 fbt_disable(void *arg, dtrace_id_t id, void *parg)
 {
-	fbt_probe_t *fbt = parg, *f;
+	fbt_probe_t *fbt = parg;
 	struct modctl *ctl = fbt->fbtp_ctl;
 
 	ASSERT(ctl->mod_nenabled > 0);
 	ctl->mod_nenabled--;
 
-	for (f = fbt; f != NULL; f = f->fbtp_next) {
-		if (f->fbtp_patchpoint == NULL)
-			return;
-	}
-
-	if ((!fbt->fbtp_primary && !ctl->mod_loaded) ||
-	    (ctl->mod_loadcnt != fbt->fbtp_loadcnt))
+	if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt))
 		return;
 
 	for (; fbt != NULL; fbt = fbt->fbtp_next)
 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_suspend.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static void
 fbt_suspend(void *arg, dtrace_id_t id, void *parg)
@@ -1574,18 +672,25 @@
 	fbt_probe_t *fbt = parg;
 	struct modctl *ctl = fbt->fbtp_ctl;
 
-	if (!fbt->fbtp_primary && !ctl->mod_loaded)
-		return;
+	ASSERT(ctl->mod_nenabled > 0);
 
-	if (ctl->mod_loadcnt != fbt->fbtp_loadcnt)
+	if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt))
 		return;
 
-	ASSERT(ctl->mod_nenabled > 0);
-
 	for (; fbt != NULL; fbt = fbt->fbtp_next)
 		*fbt->fbtp_patchpoint = fbt->fbtp_savedval;
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_resume.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static void
 fbt_resume(void *arg, dtrace_id_t id, void *parg)
@@ -1593,18 +698,25 @@
 	fbt_probe_t *fbt = parg;
 	struct modctl *ctl = fbt->fbtp_ctl;
 
-	if (!fbt->fbtp_primary && !ctl->mod_loaded)
-		return;
+	ASSERT(ctl->mod_nenabled > 0);
 
-	if (ctl->mod_loadcnt != fbt->fbtp_loadcnt)
+	if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt))
 		return;
 
-	ASSERT(ctl->mod_nenabled > 0);
-
 	for (; fbt != NULL; fbt = fbt->fbtp_next)
 		*fbt->fbtp_patchpoint = fbt->fbtp_patchval;
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_getargdesc.                                   */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static void
 fbt_getargdesc(void *arg, dtrace_id_t id, void *parg, dtrace_argdesc_t *desc)
@@ -1622,7 +734,7 @@
 	if (!ctl->mod_loaded || (ctl->mod_loadcnt != fbt->fbtp_loadcnt))
 		goto err;
 
-	if (fbt->fbtp_return && desc->dtargd_ndx == 0) {
+	if (fbt->fbtp_roffset != 0 && desc->dtargd_ndx == 0) {
 		(void) strcpy(desc->dtargd_native, "int");
 		return;
 	}
@@ -1639,22 +751,26 @@
 	 * If we have a parent container, we must manually import it.
 	 */
 	if ((parent = ctf_parent_name(fp)) != NULL) {
-		struct modctl *mod;
+		struct modctl *mp = &modules;
+		struct modctl *mod = NULL;
 
 		/*
 		 * We must iterate over all modules to find the module that
 		 * is our parent.
 		 */
-		for (mod = &modules; mod != NULL; mod = mod->mod_next) {
-			if (strcmp(mod->mod_filename, parent) == 0)
+		do {
+			if (strcmp(mp->mod_modname, parent) == 0) {
+				mod = mp;
 				break;
-		}
+			}
+		} while ((mp = mp->mod_next) != &modules);
 
 		if (mod == NULL)
 			goto err;
 
-		if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL)
+		if ((pfp = ctf_modopen(mod->mod_mp, &error)) == NULL) {
 			goto err;
+		}
 
 		if (ctf_import(fp, pfp) != 0) {
 			ctf_close(pfp);
@@ -1667,7 +783,7 @@
 	if (ctf_func_info(fp, fbt->fbtp_symndx, &f) == CTF_ERR)
 		goto err;
 
-	if (fbt->fbtp_return) {
+	if (fbt->fbtp_roffset != 0) {
 		if (desc->dtargd_ndx > 1)
 			goto err;
 
@@ -1695,26 +811,35 @@
 	desc->dtargd_ndx = DTRACE_ARGNONE;
 }
 
-static dtrace_pattr_t fbt_attr = {
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_UNKNOWN },
-{ DTRACE_STABILITY_EVOLVING, DTRACE_STABILITY_EVOLVING, DTRACE_CLASS_ISA },
-{ DTRACE_STABILITY_PRIVATE, DTRACE_STABILITY_PRIVATE, DTRACE_CLASS_ISA },
-};
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_cleanup.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
-static dtrace_pops_t fbt_pops = {
-	NULL,
-	fbt_provide_module,
-	fbt_enable,
-	fbt_disable,
-	fbt_suspend,
-	fbt_resume,
-	fbt_getargdesc,
-	NULL,
-	NULL,
-	fbt_destroy
-};
+static void
+fbt_cleanup(dev_info_t *devi)
+{
+	dtrace_invop_remove(fbt_invop);
+	ddi_remove_minor_node(devi, NULL);
+	kmem_free(fbt_probetab, fbt_probetab_size * sizeof (fbt_probe_t *));
+	fbt_probetab = NULL;
+	fbt_probetab_mask = 0;
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_attach.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 static int
 fbt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
@@ -1728,19 +853,39 @@
 		return (DDI_FAILURE);
 	}
 
+	if (fbt_probetab_size == 0)
+		fbt_probetab_size = FBT_PROBETAB_SIZE;
+
+	fbt_probetab_mask = fbt_probetab_size - 1;
+	fbt_probetab =
+	    kmem_zalloc(fbt_probetab_size * sizeof (fbt_probe_t *), KM_SLEEP);
+
+	dtrace_invop_add(fbt_invop);
+
 	if (ddi_create_minor_node(devi, "fbt", S_IFCHR, 0,
 	    DDI_PSEUDO, NULL) == DDI_FAILURE ||
-	    dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_KERNEL, 0,
+	    dtrace_register("fbt", &fbt_attr, DTRACE_PRIV_KERNEL, NULL,
 	    &fbt_pops, NULL, &fbt_id) != 0) {
-		ddi_remove_minor_node(devi, NULL);
+		fbt_cleanup(devi);
 		return (DDI_FAILURE);
 	}
 
 	ddi_report_dev(devi);
 	fbt_devi = devi;
+
 	return (DDI_SUCCESS);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_detach.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 static int
 fbt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
 {
@@ -1756,10 +901,21 @@
 	if (dtrace_unregister(fbt_id) != 0)
 		return (DDI_FAILURE);
 
-	ddi_remove_minor_node(devi, NULL);
+	fbt_cleanup(devi);
+
 	return (DDI_SUCCESS);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_info.                                         */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static int
 fbt_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
@@ -1781,6 +937,16 @@
 	return (error);
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- fbt_open.                                         */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 /*ARGSUSED*/
 static int
 fbt_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
@@ -1788,52 +954,15 @@
 	return (0);
 }
 
-static struct cb_ops fbt_cb_ops = {
-	fbt_open,		/* open */
-	nodev,			/* close */
-	nulldev,		/* strategy */
-	nulldev,		/* print */
-	nodev,			/* dump */
-	nodev,			/* read */
-	nodev,			/* write */
-	nodev,			/* ioctl */
-	nodev,			/* devmap */
-	nodev,			/* mmap */
-	nodev,			/* segmap */
-	nochpoll,		/* poll */
-	ddi_prop_op,		/* cb_prop_op */
-	0,			/* streamtab  */
-	D_NEW | D_MP		/* Driver compatibility flag */
-};
+/*========================= End of Function ========================*/
 
-static struct dev_ops fbt_ops = {
-	DEVO_REV,		/* devo_rev */
-	0,			/* refcnt */
-	fbt_info,		/* get_dev_info */
-	nulldev,		/* identify */
-	nulldev,		/* probe */
-	fbt_attach,		/* attach */
-	fbt_detach,		/* detach */
-	nodev,			/* reset */
-	&fbt_cb_ops,		/* driver operations */
-	NULL,			/* bus operations */
-	nodev			/* dev power */
-};
-
-/*
- * Module linkage information for the kernel.
- */
-static struct modldrv modldrv = {
-	&mod_driverops,		/* module type (this is a pseudo driver) */
-	"Function Boundary Tracing",	/* name of module */
-	&fbt_ops,		/* driver ops */
-};
-
-static struct modlinkage modlinkage = {
-	MODREV_1,
-	(void *)&modldrv,
-	NULL
-};
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _init.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
 
 int
 _init(void)
@@ -1841,14 +970,50 @@
 	return (mod_install(&modlinkage));
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _info.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 _info(struct modinfo *modinfop)
 {
 	return (mod_info(&modlinkage, modinfop));
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _fini.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+
 int
 _fini(void)
 {
 	return (mod_remove(&modlinkage));
 }
+
+/*========================= End of Function ========================*/
+
+
+
+
+
+
+
+
+
+
+
+
+
--- a/usr/src/uts/zSeries/dtrace/fbt.conf	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/fbt.conf	Thu Oct 08 12:44:34 2009 -0400
@@ -23,6 +23,5 @@
 # Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"@(#)fbt.conf	1.2	05/06/08 SMI"
 
 name="fbt" parent="pseudo" instance=0;
--- a/usr/src/uts/zSeries/dtrace/sdt.c	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/sdt.c	Thu Oct 08 12:44:34 2009 -0400
@@ -1,33 +1,67 @@
-/*
- * 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
+/*------------------------------------------------------------------*/
+/* 								    */
+/* Name        - sdt.c      					    */
+/* 								    */
+/* Function    - Platform specific support for Dtrace SDT.          */
+/* 								    */
+/* Name	       - Neale Ferguson					    */
+/* 								    */
+/* Date        - October, 2009   				    */
+/* 								    */
+/*------------------------------------------------------------------*/
+
+/*------------------------------------------------------------------*/
+/*                   L I C E N S E                                  */
+/*------------------------------------------------------------------*/
+
+/*==================================================================*/
+/* 								    */
+/* 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 the 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 2008 Sine Nomine Associates.                           */
 /* All rights reserved.                                             */
 /* Use is subject to license terms.                                 */
- */
-/*
- * Copyright 2004 Sun Microsystems, Inc.  All rights reserved.
- * Use is subject to license terms.
- */
+/* 								    */
+/* Copyright 2004 Sun Microsystems, Inc.  All rights reserved.	    */
+/* Use is subject to license terms.				    */
+/* 								    */
+/*==================================================================*/
+
+/*------------------------------------------------------------------*/
+/*                 D e f i n e s                                    */
+/*------------------------------------------------------------------*/
 
+#define	SDT_PATCHVAL	0xf0
+#define	SDT_ADDR2NDX(addr)	((((uintptr_t)(addr)) >> 4) & sdt_probetab_mask)
+#define	SDT_PROBETAB_SIZE	0x1000		/* 4k entries -- 16K total */
+
+/*========================= End of Defines =========================*/
+
+/*------------------------------------------------------------------*/
+/*                 I n c l u d e s                                  */
+/*------------------------------------------------------------------*/
+
+#include <sys/types.h>
+#include <sys/asm_linkage.h>
 #include <sys/modctl.h>
 #include <sys/sunddi.h>
 #include <sys/dtrace.h>
@@ -36,309 +70,56 @@
 #include <sys/conf.h>
 #include <vm/seg_kmem.h>
 #include <sys/stack.h>
+#include <sys/frame.h>
+#include <sys/dtrace_impl.h>
+#include <sys/cmn_err.h>
+#include <sys/sysmacros.h>
+#include <sys/privregs.h>
 #include <sys/sdt_impl.h>
 
+/*========================= End of Includes ========================*/
+
+/*------------------------------------------------------------------*/
+/*                 T y p e d e f s                                  */
+/*------------------------------------------------------------------*/
+
+
+/*========================= End of Typedefs ========================*/
+
+/*------------------------------------------------------------------*/
+/*                E x t e r n a l   R e f e r e n c e s             */
+/*------------------------------------------------------------------*/
+
+
+/*=================== End of External References ===================*/
+
+/*------------------------------------------------------------------*/
+/*                   P r o t o t y p e s                            */
+/*------------------------------------------------------------------*/
+
+static int sdt_open(dev_t *, int, int, cred_t *);
+static int sdt_info(dev_info_t *, ddi_info_cmd_t, void *, void **);
+static int sdt_attach(dev_info_t *, ddi_attach_cmd_t);
+static int sdt_detach(dev_info_t *, ddi_detach_cmd_t);
+static int sdt_enable(void *, dtrace_id_t, void *);
+static void sdt_provide_module(void *, struct modctl *);
+static void sdt_disable(void *, dtrace_id_t, void *);
+static void sdt_suspend(void *, dtrace_id_t, void *);
+static void sdt_resume(void *, dtrace_id_t, void *);
+static void sdt_cleanup(dev_info_t *);
+static void sdt_destroy(void *, dtrace_id_t, void *);
+
+/*========================= End of Prototypes ======================*/
+
+/*------------------------------------------------------------------*/
+/*                 G l o b a l   V a r i a b l e s                  */
+/*------------------------------------------------------------------*/
+
 static dev_info_t		*sdt_devi;
-
-int sdt_verbose = 0;
-
-#define	SDT_REG_G0		0
-#define	SDT_REG_O0		8
-#define	SDT_REG_O1		9
-#define	SDT_REG_O2		10
-#define	SDT_REG_O3		11
-#define	SDT_REG_O4		12
-#define	SDT_REG_O5		13
-#define	SDT_REG_I0		24
-#define	SDT_REG_I1		25
-#define	SDT_REG_I2		26
-#define	SDT_REG_I3		27
-#define	SDT_REG_I4		28
-#define	SDT_REG_I5		29
-
-#define	SDT_SIMM13_MASK		0x1fff
-#define	SDT_SIMM13_MAX		((int32_t)0xfff)
-#define	SDT_CALL(from, to)	(((uint32_t)1 << 30) | \
-				(((uintptr_t)(to) - (uintptr_t)(from) >> 2) & \
-				0x3fffffff))
-#define	SDT_SAVE		(0x9de3a000 | (-SA(MINFRAME) & SDT_SIMM13_MASK))
-#define	SDT_RET			0x81c7e008
-#define	SDT_RESTORE		0x81e80000
-
-#define	SDT_OP_SETHI		0x1000000
-#define	SDT_OP_OR		0x80100000
-
-#define	SDT_FMT2_RD_SHIFT	25
-#define	SDT_IMM22_SHIFT		10
-#define	SDT_IMM22_MASK		0x3fffff
-#define	SDT_IMM10_MASK		0x3ff
-
-#define	SDT_FMT3_RD_SHIFT	25
-#define	SDT_FMT3_RS1_SHIFT	14
-#define	SDT_FMT3_RS2_SHIFT	0
-#define	SDT_FMT3_IMM		(1 << 13)
-
-#define	SDT_MOV(rs, rd) \
-	(SDT_OP_OR | (SDT_REG_G0 << SDT_FMT3_RS1_SHIFT) | \
-	((rs) << SDT_FMT3_RS2_SHIFT) | ((rd) << SDT_FMT3_RD_SHIFT))
-
-#define	SDT_ORLO(rs, val, rd) \
-	(SDT_OP_OR | ((rs) << SDT_FMT3_RS1_SHIFT) | \
-	((rd) << SDT_FMT3_RD_SHIFT) | SDT_FMT3_IMM | ((val) & SDT_IMM10_MASK))
-
-#define	SDT_ORSIMM13(rs, val, rd) \
-	(SDT_OP_OR | ((rs) << SDT_FMT3_RS1_SHIFT) | \
-	((rd) << SDT_FMT3_RD_SHIFT) | SDT_FMT3_IMM | ((val) & SDT_SIMM13_MASK))
-
-#define	SDT_SETHI(val, reg)	\
-	(SDT_OP_SETHI | (reg << SDT_FMT2_RD_SHIFT) | \
-	((val >> SDT_IMM22_SHIFT) & SDT_IMM22_MASK))
-
-#define	SDT_ENTRY_SIZE	(11 * sizeof (uint32_t))
-
-static void
-sdt_initialize(sdt_probe_t *sdp, uint32_t **trampoline)
-{
-	uint32_t *instr = *trampoline;
-
-	*instr++ = SDT_SAVE;
-
-	if (sdp->sdp_id > (uint32_t)SDT_SIMM13_MAX)  {
-		*instr++ = SDT_SETHI(sdp->sdp_id, SDT_REG_O0);
-		*instr++ = SDT_ORLO(SDT_REG_O0, sdp->sdp_id, SDT_REG_O0);
-	} else {
-		*instr++ = SDT_ORSIMM13(SDT_REG_G0, sdp->sdp_id, SDT_REG_O0);
-	}
-
-	*instr++ = SDT_MOV(SDT_REG_I0, SDT_REG_O1);
-	*instr++ = SDT_MOV(SDT_REG_I1, SDT_REG_O2);
-	*instr++ = SDT_MOV(SDT_REG_I2, SDT_REG_O3);
-	*instr++ = SDT_MOV(SDT_REG_I3, SDT_REG_O4);
-	*instr = SDT_CALL(instr, dtrace_probe);
-	instr++;
-	*instr++ = SDT_MOV(SDT_REG_I4, SDT_REG_O5);
-
-	*instr++ = SDT_RET;
-	*instr++ = SDT_RESTORE;
-	*trampoline = instr;
-}
-
-/*ARGSUSED*/
-static void
-sdt_provide_module(void *arg, struct modctl *ctl)
-{
-	struct module *mp = ctl->mod_mp;
-	char *modname = ctl->mod_modname;
-	int primary, nprobes = 0;
-	sdt_probedesc_t *sdpd;
-	sdt_probe_t *sdp, *old;
-	uint32_t *tab;
-	sdt_provider_t *prov;
-	int len;
-
-	/*
-	 * One for all, and all for one:  if we haven't yet registered all of
-	 * our providers, we'll refuse to provide anything.
-	 */
-	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
-		if (prov->sdtp_id == DTRACE_PROVNONE)
-			return;
-	}
-
-	if (mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL)
-		return;
-
-	kobj_textwin_alloc(mp);
-
-	/*
-	 * Hack to identify unix/genunix/krtld.
-	 */
-	primary = vmem_contains(heap_arena, (void *)ctl,
-	    sizeof (struct modctl)) == 0;
-
-	/*
-	 * If there hasn't been an sdt table allocated, we'll do so now.
-	 */
-	if (mp->sdt_tab == NULL) {
-		for (; sdpd != NULL; sdpd = sdpd->sdpd_next) {
-			nprobes++;
-		}
-
-		/*
-		 * We could (should?) determine precisely the size of the
-		 * table -- but a reasonable maximum will suffice.
-		 */
-		mp->sdt_size = nprobes * SDT_ENTRY_SIZE;
-		mp->sdt_tab = kobj_texthole_alloc(mp->text, mp->sdt_size);
-
-		if (mp->sdt_tab == NULL) {
-			cmn_err(CE_WARN, "couldn't allocate SDT table "
-			    "for module %s", modname);
-			return;
-		}
-	}
-
-	tab = (uint32_t *)mp->sdt_tab;
-
-	for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) {
-		char *name = sdpd->sdpd_name, *func, *nname;
-		int i, j;
-		sdt_provider_t *prov;
-		ulong_t offs;
-		dtrace_id_t id;
-
-		for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) {
-			char *prefix = prov->sdtp_prefix;
-
-			if (strncmp(name, prefix, strlen(prefix)) == 0) {
-				name += strlen(prefix);
-				break;
-			}
-		}
-
-		nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP);
-
-		for (i = 0, j = 0; name[j] != '\0'; i++) {
-			if (name[j] == '_' && name[j + 1] == '_') {
-				nname[i] = '-';
-				j += 2;
-			} else {
-				nname[i] = name[j++];
-			}
-		}
-
-		nname[i] = '\0';
-
-		sdp = kmem_zalloc(sizeof (sdt_probe_t), KM_SLEEP);
-		sdp->sdp_loadcnt = ctl->mod_loadcnt;
-		sdp->sdp_primary = primary;
-		sdp->sdp_ctl = ctl;
-		sdp->sdp_name = nname;
-		sdp->sdp_namelen = len;
-		sdp->sdp_provider = prov;
-
-		func = kobj_searchsym(mp, sdpd->sdpd_offset +
-		    (uintptr_t)mp->text, &offs);
-
-		if (func == NULL)
-			func = "<unknown>";
-
-		/*
-		 * We have our provider.  Now create the probe.
-		 */
-		if ((id = dtrace_probe_lookup(prov->sdtp_id, modname,
-		    func, nname)) != DTRACE_IDNONE) {
-			old = dtrace_probe_arg(prov->sdtp_id, id);
-			ASSERT(old != NULL);
-
-			sdp->sdp_next = old->sdp_next;
-			sdp->sdp_id = id;
-			old->sdp_next = sdp;
-		} else {
-			sdp->sdp_id = dtrace_probe_create(prov->sdtp_id,
-			    modname, func, nname, 1, sdp);
-
-			mp->sdt_nprobes++;
-		}
-
-		sdp->sdp_patchval = SDT_CALL((uintptr_t)mp->text +
-		    sdpd->sdpd_offset, tab);
-		sdp->sdp_patchpoint = (uint32_t *)((uintptr_t)mp->textwin +
-		    sdpd->sdpd_offset);
-		sdp->sdp_savedval = *sdp->sdp_patchpoint;
-		sdt_initialize(sdp, &tab);
-	}
-}
-
-/*ARGSUSED*/
-static void
-sdt_destroy(void *arg, dtrace_id_t id, void *parg)
-{
-	sdt_probe_t *sdp = parg, *old;
-	struct modctl *ctl = sdp->sdp_ctl;
-
-	if (ctl != NULL && ctl->mod_loadcnt == sdp->sdp_loadcnt) {
-		if ((ctl->mod_loadcnt == sdp->sdp_loadcnt &&
-		    ctl->mod_loaded) || sdp->sdp_primary) {
-			((struct module *)(ctl->mod_mp))->sdt_nprobes--;
-		}
-	}
-
-	while (sdp != NULL) {
-		old = sdp;
-		kmem_free(sdp->sdp_name, sdp->sdp_namelen);
-		sdp = sdp->sdp_next;
-		kmem_free(old, sizeof (sdt_probe_t));
-	}
-}
-
-/*ARGSUSED*/
-static void
-sdt_enable(void *arg, dtrace_id_t id, void *parg)
-{
-	sdt_probe_t *sdp = parg;
-	struct modctl *ctl = sdp->sdp_ctl;
-
-	ctl->mod_nenabled++;
-
-	/*
-	 * If this module has disappeared since we discovered its probes,
-	 * refuse to enable it.
-	 */
-	if (!sdp->sdp_primary && !ctl->mod_loaded) {
-		if (sdt_verbose) {
-			cmn_err(CE_NOTE, "sdt is failing for probe %s "
-			    "(module %s unloaded)",
-			    sdp->sdp_name, ctl->mod_modname);
-		}
-		goto err;
-	}
-
-	/*
-	 * 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->mod_loadcnt != sdp->sdp_loadcnt) {
-		if (sdt_verbose) {
-			cmn_err(CE_NOTE, "sdt is failing for probe %s "
-			    "(module %s reloaded)",
-			    sdp->sdp_name, ctl->mod_modname);
-		}
-		goto err;
-	}
-
-	while (sdp != NULL) {
-		*sdp->sdp_patchpoint = sdp->sdp_patchval;
-		sdp = sdp->sdp_next;
-	}
-
-err:
-	;
-}
-
-/*ARGSUSED*/
-static void
-sdt_disable(void *arg, dtrace_id_t id, void *parg)
-{
-	sdt_probe_t *sdp = parg;
-	struct modctl *ctl = sdp->sdp_ctl;
-
-	ASSERT(ctl->mod_nenabled > 0);
-	ctl->mod_nenabled--;
-
-	if ((!sdp->sdp_primary && !ctl->mod_loaded) ||
-	    (ctl->mod_loadcnt != sdp->sdp_loadcnt))
-		goto err;
-
-	while (sdp != NULL) {
-		*sdp->sdp_patchpoint = sdp->sdp_savedval;
-		sdp = sdp->sdp_next;
-	}
-
-err:
-	;
-}
+static int			sdt_verbose = 0;
+static sdt_probe_t		**sdt_probetab;
+static int			sdt_probetab_size;
+static int			sdt_probetab_mask;
 
 static dtrace_pops_t sdt_pops = {
 	NULL,
@@ -353,88 +134,6 @@
 	sdt_destroy
 };
 
-static int
-sdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
-{
-	sdt_provider_t *prov;
-
-	switch (cmd) {
-	case DDI_ATTACH:
-		break;
-	case DDI_RESUME:
-		return (DDI_SUCCESS);
-	default:
-		return (DDI_FAILURE);
-	}
-
-	if (ddi_create_minor_node(devi, "sdt", S_IFCHR, 0,
-	    DDI_PSEUDO, NULL) == DDI_FAILURE) {
-		ddi_remove_minor_node(devi, NULL);
-		return (DDI_FAILURE);
-	}
-
-	ddi_report_dev(devi);
-	sdt_devi = devi;
-
-	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
-		if (dtrace_register(prov->sdtp_name, prov->sdtp_attr,
-		    DTRACE_PRIV_KERNEL, 0,
-		    &sdt_pops, prov, &prov->sdtp_id) != 0) {
-			cmn_err(CE_WARN, "failed to register sdt provider %s",
-			    prov->sdtp_name);
-		}
-	}
-
-	return (DDI_SUCCESS);
-}
-
-static int
-sdt_detach(dev_info_t *devi, ddi_detach_cmd_t cmd)
-{
-	sdt_provider_t *prov;
-
-	switch (cmd) {
-	case DDI_DETACH:
-		break;
-	case DDI_SUSPEND:
-		return (DDI_SUCCESS);
-	default:
-		return (DDI_FAILURE);
-	}
-
-	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
-		if (prov->sdtp_id != DTRACE_PROVNONE) {
-			if (dtrace_unregister(prov->sdtp_id) != 0)
-				return (DDI_FAILURE);
-			prov->sdtp_id = DTRACE_PROVNONE;
-		}
-	}
-
-	ddi_remove_minor_node(devi, NULL);
-	return (DDI_SUCCESS);
-}
-
-/*ARGSUSED*/
-static int
-sdt_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
-{
-	int error;
-
-	switch (infocmd) {
-	case DDI_INFO_DEVT2DEVINFO:
-		*result = (void *)sdt_devi;
-		error = DDI_SUCCESS;
-		break;
-	case DDI_INFO_DEVT2INSTANCE:
-		*result = (void *)0;
-		error = DDI_SUCCESS;
-		break;
-	default:
-		error = DDI_FAILURE;
-	}
-	return (error);
-}
-
 /*ARGSUSED*/
 static int
 sdt_open(dev_t *devp, int flag, int otyp, cred_t *cred_p)
@@ -471,7 +170,8 @@
 	nodev,			/* reset */
 	&sdt_cb_ops,		/* driver operations */
 	NULL,			/* bus operations */
-	nodev			/* dev power */
+	nodev,			/* dev power */
+	ddi_quiesce_not_needed,		/* quiesce */
 };
 
 /*
@@ -489,20 +189,465 @@
 	NULL
 };
 
+/*====================== End of Global Variables ===================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_invop.                                        */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static int
+sdt_invop(uintptr_t addr, uintptr_t *stack, uintptr_t eax)
+{
+	uintptr_t stack0, stack1, stack2, stack3, stack4;
+	int i = 0;
+	sdt_probe_t *sdt = sdt_probetab[SDT_ADDR2NDX(addr)];
+
+#ifdef __amd64
+	/*
+	 * On amd64, stack[0] contains the dereferenced stack pointer,
+	 * stack[1] contains savfp, stack[2] contains savpc.  We want
+	 * to step over these entries.
+	 */
+	i += 3;
+#endif
+
+	for (; sdt != NULL; sdt = sdt->sdp_hashnext) {
+		if ((uintptr_t)sdt->sdp_patchpoint == addr) {
+			/*
+			 * When accessing the arguments on the stack, we must
+			 * protect against accessing beyond the stack.  We can
+			 * safely set NOFAULT here -- we know that interrupts
+			 * are already disabled.
+			 */
+			DTRACE_CPUFLAG_SET(CPU_DTRACE_NOFAULT);
+			stack0 = stack[i++];
+			stack1 = stack[i++];
+			stack2 = stack[i++];
+			stack3 = stack[i++];
+			stack4 = stack[i++];
+			DTRACE_CPUFLAG_CLEAR(CPU_DTRACE_NOFAULT |
+			    CPU_DTRACE_BADADDR);
+
+			dtrace_probe(sdt->sdp_id, stack0, stack1,
+			    stack2, stack3, stack4);
+
+			return (DTRACE_INVOP_NOP);
+		}
+	}
+
+	return (0);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_provide_module.                               */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static void
+sdt_provide_module(void *arg, struct modctl *ctl)
+{
+	struct module *mp = ctl->mod_mp;
+	char *modname = ctl->mod_modname;
+	sdt_probedesc_t *sdpd;
+	sdt_probe_t *sdp, *old;
+	sdt_provider_t *prov;
+	int len;
+
+	/*
+	 * One for all, and all for one:  if we haven't yet registered all of
+	 * our providers, we'll refuse to provide anything.
+	 */
+	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
+		if (prov->sdtp_id == DTRACE_PROVNONE)
+			return;
+	}
+
+	if (mp->sdt_nprobes != 0 || (sdpd = mp->sdt_probes) == NULL)
+		return;
+
+	for (sdpd = mp->sdt_probes; sdpd != NULL; sdpd = sdpd->sdpd_next) {
+		char *name = sdpd->sdpd_name, *func, *nname;
+		int i, j;
+		sdt_provider_t *prov;
+		ulong_t offs;
+		dtrace_id_t id;
+
+		for (prov = sdt_providers; prov->sdtp_prefix != NULL; prov++) {
+			char *prefix = prov->sdtp_prefix;
+
+			if (strncmp(name, prefix, strlen(prefix)) == 0) {
+				name += strlen(prefix);
+				break;
+			}
+		}
+
+		nname = kmem_alloc(len = strlen(name) + 1, KM_SLEEP);
+
+		for (i = 0, j = 0; name[j] != '\0'; i++) {
+			if (name[j] == '_' && name[j + 1] == '_') {
+				nname[i] = '-';
+				j += 2;
+			} else {
+				nname[i] = name[j++];
+			}
+		}
+
+		nname[i] = '\0';
+
+		sdp		  = kmem_zalloc(sizeof (sdt_probe_t), KM_SLEEP);
+		sdp->sdp_loadcnt  = ctl->mod_loadcnt;
+		sdp->sdp_ctl	  = ctl;
+		sdp->sdp_name	  = nname;
+		sdp->sdp_namelen  = len;
+		sdp->sdp_provider = prov;
+
+		func = kobj_searchsym(mp, sdpd->sdpd_offset, &offs);
+
+		if (func == NULL)
+			func = "<unknown>";
+
+		/*
+		 * We have our provider.  Now create the probe.
+		 */
+		if ((id = dtrace_probe_lookup(prov->sdtp_id, modname,
+		    func, nname)) != DTRACE_IDNONE) {
+			old = dtrace_probe_arg(prov->sdtp_id, id);
+			ASSERT(old != NULL);
+
+			sdp->sdp_next = old->sdp_next;
+			sdp->sdp_id   = id;
+			old->sdp_next = sdp;
+		} else {
+			sdp->sdp_id = dtrace_probe_create(prov->sdtp_id,
+			    modname, func, nname, 3, sdp);
+
+			mp->sdt_nprobes++;
+		}
+
+		sdp->sdp_hashnext =
+		    sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)];
+		sdt_probetab[SDT_ADDR2NDX(sdpd->sdpd_offset)] = sdp;
+
+		sdp->sdp_patchval   = SDT_PATCHVAL;
+		sdp->sdp_patchpoint = (uint8_t *)sdpd->sdpd_offset;
+		sdp->sdp_savedval   = *sdp->sdp_patchpoint;
+	}
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_destroy.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static void
+sdt_destroy(void *arg, dtrace_id_t id, void *parg)
+{
+	sdt_probe_t *sdp = parg, *old, *last, *hash;
+	struct modctl *ctl = sdp->sdp_ctl;
+	int ndx;
+
+	if (ctl != NULL && ctl->mod_loadcnt == sdp->sdp_loadcnt) {
+		if ((ctl->mod_loadcnt == sdp->sdp_loadcnt &&
+		    ctl->mod_loaded)) {
+			((struct module *)(ctl->mod_mp))->sdt_nprobes--;
+		}
+	}
+
+	while (sdp != NULL) {
+		old = sdp;
+
+		/*
+		 * Now we need to remove this probe from the sdt_probetab.
+		 */
+		ndx = SDT_ADDR2NDX(sdp->sdp_patchpoint);
+		last = NULL;
+		hash = sdt_probetab[ndx];
+
+		while (hash != sdp) {
+			ASSERT(hash != NULL);
+			last = hash;
+			hash = hash->sdp_hashnext;
+		}
+
+		if (last != NULL) {
+			last->sdp_hashnext = sdp->sdp_hashnext;
+		} else {
+			sdt_probetab[ndx] = sdp->sdp_hashnext;
+		}
+
+		kmem_free(sdp->sdp_name, sdp->sdp_namelen);
+		sdp = sdp->sdp_next;
+		kmem_free(old, sizeof (sdt_probe_t));
+	}
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_enable.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static int
+sdt_enable(void *arg, dtrace_id_t id, void *parg)
+{
+	sdt_probe_t   *sdp = parg;
+	struct modctl *ctl = sdp->sdp_ctl;
+
+	ctl->mod_nenabled++;
+
+	/*
+	 * If this module has disappeared since we discovered its probes,
+	 * refuse to enable it.
+	 */
+	if (!ctl->mod_loaded) {
+		if (sdt_verbose) {
+			cmn_err(CE_NOTE, "sdt is failing for probe %s "
+			    "(module %s unloaded)",
+			    sdp->sdp_name, ctl->mod_modname);
+		}
+		goto err;
+	}
+
+	/*
+	 * 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->mod_loadcnt != sdp->sdp_loadcnt) {
+		if (sdt_verbose) {
+			cmn_err(CE_NOTE, "sdt is failing for probe %s "
+			    "(module %s reloaded)",
+			    sdp->sdp_name, ctl->mod_modname);
+		}
+		goto err;
+	}
+
+	while (sdp != NULL) {
+		*sdp->sdp_patchpoint = sdp->sdp_patchval;
+		sdp = sdp->sdp_next;
+	}
+err:
+	return (0);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_disable.                                      */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static void
+sdt_disable(void *arg, dtrace_id_t id, void *parg)
+{
+	sdt_probe_t   *sdp = parg;
+	struct modctl *ctl = sdp->sdp_ctl;
+
+	ctl->mod_nenabled--;
+
+	if (!ctl->mod_loaded || ctl->mod_loadcnt != sdp->sdp_loadcnt)
+		goto err;
+
+	while (sdp != NULL) {
+		*sdp->sdp_patchpoint = sdp->sdp_savedval;
+		sdp = sdp->sdp_next;
+	}
+
+err:
+	;
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_attach.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static int
+sdt_attach(dev_info_t *devi, ddi_attach_cmd_t cmd)
+{
+	sdt_provider_t *prov;
+
+	if (ddi_create_minor_node(devi, "sdt", S_IFCHR,
+	    0, DDI_PSEUDO, NULL) == DDI_FAILURE) {
+		cmn_err(CE_NOTE, "/dev/sdt couldn't create minor node");
+		ddi_remove_minor_node(devi, NULL);
+		return (DDI_FAILURE);
+	}
+
+	ddi_report_dev(devi);
+	sdt_devi = devi;
+
+	if (sdt_probetab_size == 0)
+		sdt_probetab_size = SDT_PROBETAB_SIZE;
+
+	sdt_probetab_mask = sdt_probetab_size - 1;
+	sdt_probetab =
+	    kmem_zalloc(sdt_probetab_size * sizeof (sdt_probe_t *), KM_SLEEP);
+	dtrace_invop_add(sdt_invop);
+
+	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
+		if (dtrace_register(prov->sdtp_name, prov->sdtp_attr,
+		    DTRACE_PRIV_KERNEL, NULL,
+		    &sdt_pops, prov, &prov->sdtp_id) != 0) {
+			cmn_err(CE_WARN, "failed to register sdt provider %s",
+			    prov->sdtp_name);
+		}
+	}
+
+	return (DDI_SUCCESS);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_detach.                                       */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static int
+sdt_detach(dev_info_t *dip, ddi_detach_cmd_t cmd)
+{
+	sdt_provider_t *prov;
+
+	switch (cmd) {
+	case DDI_DETACH:
+		break;
+
+	case DDI_SUSPEND:
+		return (DDI_SUCCESS);
+
+	default:
+		return (DDI_FAILURE);
+	}
+
+	for (prov = sdt_providers; prov->sdtp_name != NULL; prov++) {
+		if (prov->sdtp_id != DTRACE_PROVNONE) {
+			if (dtrace_unregister(prov->sdtp_id) != 0)
+				return (DDI_FAILURE);
+
+			prov->sdtp_id = DTRACE_PROVNONE;
+		}
+	}
+
+	dtrace_invop_remove(sdt_invop);
+	kmem_free(sdt_probetab, sdt_probetab_size * sizeof (sdt_probe_t *));
+
+	return (DDI_SUCCESS);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- sdt_info.                                         */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
+/*ARGSUSED*/
+static int
+sdt_info(dev_info_t *dip, ddi_info_cmd_t infocmd, void *arg, void **result)
+{
+	int error;
+
+	switch (infocmd) {
+	case DDI_INFO_DEVT2DEVINFO:
+		*result = (void *)sdt_devi;
+		error = DDI_SUCCESS;
+		break;
+	case DDI_INFO_DEVT2INSTANCE:
+		*result = (void *)0;
+		error = DDI_SUCCESS;
+		break;
+	default:
+		error = DDI_FAILURE;
+	}
+	return (error);
+}
+
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _init.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 _init(void)
 {
 	return (mod_install(&modlinkage));
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _info.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 _info(struct modinfo *modinfop)
 {
 	return (mod_info(&modlinkage, modinfop));
 }
 
+/*========================= End of Function ========================*/
+
+/*------------------------------------------------------------------*/
+/*                                                                  */
+/* Name		- _fini.                                            */
+/*                                                                  */
+/* Function	-                                                   */
+/*		                               		 	    */
+/*------------------------------------------------------------------*/
+
 int
 _fini(void)
 {
 	return (mod_remove(&modlinkage));
 }
+
+/*========================= End of Function ========================*/
--- a/usr/src/uts/zSeries/dtrace/sdt.conf	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/dtrace/sdt.conf	Thu Oct 08 12:44:34 2009 -0400
@@ -23,6 +23,5 @@
 # Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
 # Use is subject to license terms.
 #
-#ident	"@(#)sdt.conf	1.2	05/06/08 SMI"
 
 name="sdt" parent="pseudo" instance=0;
--- a/usr/src/uts/zSeries/fasttrap/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/fasttrap/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -33,7 +33,7 @@
 LINTS		= $(FASTTRAP_OBJS:%.o=$(LINTS_DIR)/%.ln)
 ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
 ROOTLINK	= $(ROOT_DTRACE_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/s390x/dtrace
+CONF_SRCDIR	= $(UTSBASE)/zSeries/dtrace
 
 include $(UTSBASE)/zSeries/Makefile.zSeries
 
@@ -41,7 +41,7 @@
 LINT_TARGET	= $(MODULE).lint
 INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
 
-CFLAGS		+= $(CCVERBOSE)
+CFLAGS		+= $(CCVERBOSE) -I$(SRC)/common/dis/s390 -I$(SRC)/common
 LDFLAGS		+= -Ndrv/dtrace
 LDFLAGS		+= -dy
 
--- a/usr/src/uts/zSeries/fbt/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/fbt/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -33,7 +33,7 @@
 LINTS		= $(FBT_OBJS:%.o=$(LINTS_DIR)/%.ln)
 ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
 ROOTLINK	= $(ROOT_DTRACE_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/s390x/dtrace
+CONF_SRCDIR	= $(UTSBASE)/zSeries/dtrace
 
 include $(UTSBASE)/zSeries/Makefile.zSeries
 
@@ -41,7 +41,7 @@
 LINT_TARGET	= $(MODULE).lint
 INSTALL_TARGET	= $(BINARY) $(ROOTMODULE) $(ROOTLINK) $(ROOT_CONFFILE)
 
-CFLAGS		+= $(CCVERBOSE)
+CFLAGS		+= $(CCVERBOSE) -I$(SRC)/common/dis/s390
 LDFLAGS		+= -Ndrv/dtrace -Nmisc/ctf
 LDFLAGS		+= -dy
 
--- a/usr/src/uts/zSeries/sdt/Makefile	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/sdt/Makefile	Thu Oct 08 12:44:34 2009 -0400
@@ -33,7 +33,7 @@
 LINTS		= $(SDT_OBJS:%.o=$(LINTS_DIR)/%.ln)
 ROOTMODULE	= $(ROOT_DRV_DIR)/$(MODULE)
 ROOTLINK	= $(ROOT_DTRACE_DIR)/$(MODULE)
-CONF_SRCDIR	= $(UTSBASE)/s390x/dtrace
+CONF_SRCDIR	= $(UTSBASE)/zSeries/dtrace
 
 include $(UTSBASE)/zSeries/Makefile.zSeries
 
--- a/usr/src/uts/zSeries/sys/fasttrap_isa.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/sys/fasttrap_isa.h	Thu Oct 08 12:44:34 2009 -0400
@@ -37,58 +37,32 @@
 extern "C" {
 #endif
 
+#define	FASTTRAP_MAX_INSTR_SIZE		256
+
 /*
- * This is our reserved trap instruction: ta 0x38
+ * This is our reserved trap instruction: svc 01
  */
-#define	FASTTRAP_INSTR			0x91d02038
+#define	FASTTRAP_INSTR			0x0a01
 
 #define	FASTTRAP_SUNWDTRACE_SIZE	64
 
-typedef uint32_t	fasttrap_instr_t;
+typedef	uint16_t	fasttrap_instr_t;
 
 typedef struct fasttrap_machtp {
-	fasttrap_instr_t	ftmt_instr;	/* original instruction */
-	uintptr_t		ftmt_dest;	/* destination of DCTI */
-	uint8_t			ftmt_type;	/* emulation type */
-	uint8_t			ftmt_flags;	/* emulation flags */
-	uint8_t			ftmt_cc;	/* which cc to look at */
-	uint8_t			ftmt_code;	/* branch condition */
+	uint8_t		ftmt_instr[FASTTRAP_MAX_INSTR_SIZE]; /* orig. instr. */
+	uint8_t		ftmt_isize;	/* instruction size */
+	uint8_t		ftmt_size;	/* dtrace instruction sequence size */
 } fasttrap_machtp_t;
 
-#define	ftt_instr	ftt_mtp.ftmt_instr
-#define	ftt_dest	ftt_mtp.ftmt_dest
-#define	ftt_type	ftt_mtp.ftmt_type
-#define	ftt_flags	ftt_mtp.ftmt_flags
-#define	ftt_cc		ftt_mtp.ftmt_cc
-#define	ftt_code	ftt_mtp.ftmt_code
-
-#define	FASTTRAP_T_COMMON	0x00	/* common case -- no emulation */
-#define	FASTTRAP_T_CCR		0x01	/* integer condition code branch */
-#define	FASTTRAP_T_FCC		0x02	/* floating-point branch */
-#define	FASTTRAP_T_REG		0x03	/* register predicated branch */
-#define	FASTTRAP_T_ALWAYS	0x04	/* branch always */
-#define	FASTTRAP_T_CALL		0x05	/* call instruction */
-#define	FASTTRAP_T_JMPL		0x06	/* jmpl instruction */
-#define	FASTTRAP_T_RDPC		0x07	/* rdpc instruction */
-#define	FASTTRAP_T_RETURN	0x08	/* return instruction */
-
-/*
- * For performance rather than correctness.
- */
-#define	FASTTRAP_T_SAVE		0x10	/* save instruction (func entry only) */
-#define	FASTTRAP_T_RESTORE	0x11	/* restore instruction */
-#define	FASTTRAP_T_OR		0x12	/* mov instruction */
-#define	FASTTRAP_T_SETHI	0x13	/* sethi instruction (includes nop) */
-
-#define	FASTTRAP_F_ANNUL	0x01	/* branch is annulled */
-#define	FASTTRAP_F_RETMAYBE	0x02	/* not definitely a return site */
+#define ftt_instr	ftt_mtp.ftmt_instr
+#define	ftt_size	ftt_mtp.ftmt_size
+#define	ftt_isize	ftt_mtp.ftmt_isize
 
 #define	FASTTRAP_AFRAMES		3
 #define	FASTTRAP_RETURN_AFRAMES		4
 #define	FASTTRAP_ENTRY_AFRAMES		3
 #define	FASTTRAP_OFFSET_AFRAMES		3
 
-
 #ifdef	__cplusplus
 }
 #endif
--- a/usr/src/uts/zSeries/sys/procfs_isa.h	Mon Oct 05 12:49:41 2009 -0400
+++ b/usr/src/uts/zSeries/sys/procfs_isa.h	Thu Oct 08 12:44:34 2009 -0400
@@ -60,7 +60,7 @@
 typedef	uint32_t	instr_t;
 
 /*
- * General register access (sparc).
+ * General register access (s390x).
  * Don't confuse definitions here with definitions in <sys/regset.h>.
  * Registers are 32 bits for ILP32, 64 bits for LP64.
  * The floating point registers follow the access registers. For convenience
@@ -84,40 +84,41 @@
 #define	R_G13	(15)
 #define	R_G14	(16)
 #define	R_G15	(17)
-#define	R_A0	(18)
-#define	R_A1	(19)
-#define	R_A2	(20)
-#define	R_A3	(21)
-#define	R_A4	(22)
-#define	R_A5	(23)
-#define	R_A6	(24)
-#define	R_A7	(25)
-#define	R_A8	(26)
-#define	R_A9	(27)
-#define	R_A10	(28)
-#define	R_A11	(29)
-#define	R_A12	(30)
-#define	R_A13	(31)
-#define	R_A14	(32)
-#define	R_A15	(33)
-#define	R_FPC	(34)
-#define	R_F0	(35)
-#define	R_F1	(36)
-#define	R_F2	(37)
-#define	R_F3	(38)
-#define	R_F4	(39)
-#define	R_F5	(40)
-#define	R_F6	(41)
-#define	R_F7	(42)
-#define	R_F8	(43)
-#define	R_F9	(44)
-#define	R_F10	(45)
-#define	R_F11	(46)
-#define	R_F12	(47)
-#define	R_F13	(48)
-#define	R_F14	(49)
-#define	R_F15	(50)
-#define	NPRGREG	51
+#define	R_ILC	(18)
+#define	R_A0	(19)
+#define	R_A1	(20)
+#define	R_A2	(21)
+#define	R_A3	(22)
+#define	R_A4	(23)
+#define	R_A5	(24)
+#define	R_A6	(25)
+#define	R_A7	(26)
+#define	R_A8	(27)
+#define	R_A9	(28)
+#define	R_A10	(29)
+#define	R_A11	(30)
+#define	R_A12	(31)
+#define	R_A13	(32)
+#define	R_A14	(33)
+#define	R_A15	(34)
+#define	R_FPC	(35)
+#define	R_F0	(36)
+#define	R_F1	(37)
+#define	R_F2	(38)
+#define	R_F3	(39)
+#define	R_F4	(40)
+#define	R_F5	(41)
+#define	R_F6	(42)
+#define	R_F7	(43)
+#define	R_F8	(44)
+#define	R_F9	(45)
+#define	R_F10	(46)
+#define	R_F11	(47)
+#define	R_F12	(48)
+#define	R_F13	(49)
+#define	R_F14	(50)
+#define	R_F15	(51)
+#define	NPRGREG	52
 
 /*
  * The following defines are for portability (see <sys/regset.h>).