PERFORCE change 213974 for review

John Baldwin jhb at FreeBSD.org
Fri Jul 6 12:22:18 UTC 2012


http://p4web.freebsd.org/@@213974?ac=10

Change 213974 by jhb at jhb_jhbbsd on 2012/07/06 12:21:44

	Add decoding support for all VMX instructions along with several
	other cleanups and restructuring to the disassembler.

Affected files ...

.. //depot/projects/smpng/sys/amd64/amd64/db_disasm.c#9 edit
.. //depot/projects/smpng/sys/modules/x86dis/Makefile#2 edit
.. //depot/projects/smpng/sys/modules/x86dis/x86dis.c#7 edit

Differences ...

==== //depot/projects/smpng/sys/amd64/amd64/db_disasm.c#9 (text+ko) ====

@@ -31,6 +31,7 @@
  * Instruction disassembler.
  */
 #include <sys/param.h>
+#include <sys/libkern.h>
 
 #include <ddb/ddb.h>
 #include <ddb/db_access.h>
@@ -47,7 +48,9 @@
 #define	DBLR	5
 #define	EXTR	6
 #define	SDEP	7
-#define	NONE	8
+#define	ADEP	8
+#define	ESC	9
+#define	NONE	10
 
 /*
  * REX prefix and bits
@@ -67,6 +70,7 @@
 #define	Eb	4			/* address, byte size */
 #define	R	5			/* register, in 'reg' field */
 #define	Rw	6			/* word register, in 'reg' field */
+#define	Rq	39			/* quad register, in 'reg' field */
 #define	Ri	7			/* register in instruction */
 #define	S	8			/* segment reg, in 'reg' field */
 #define	Si	9			/* segment reg, in instruction */
@@ -120,6 +124,45 @@
 					   (or pointer to table) */
 };
 
+static const struct inst db_inst_0f388x[] = {
+/*80*/	{ "",	   TRUE,  SDEP,  op2(E, Rq),  "invept" },
+/*81*/	{ "",	   TRUE,  SDEP,  op2(E, Rq),  "invvpid" },
+/*82*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*83*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*84*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*85*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*86*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*87*/	{ "",	   FALSE, NONE,  0,	      0 },
+
+/*88*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*89*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8a*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8b*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8c*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8d*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8e*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*8f*/	{ "",	   FALSE, NONE,  0,	      0 },
+};
+
+static const struct inst * const db_inst_0f38[] = {
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	db_inst_0f388x,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0,
+	0
+};
+
 static const char * const db_Grp6[] = {
 	"sldt",
 	"str",
@@ -160,8 +203,8 @@
 	"",
 	"",
 	"",
-	"",
-	""
+	"vmptrld",
+	"vmptrst"
 };
 
 static const char * const db_Grp15[] = {
@@ -236,7 +279,7 @@
 /*36*/	{ "",	   FALSE, NONE,  0,	      0 },
 /*37*/	{ "getsec",FALSE, NONE,  0,	      0 },
 
-/*38*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*38*/	{ "",	   FALSE, ESC,  0,	      db_inst_0f38 },
 /*39*/	{ "",	   FALSE, NONE,  0,	      0 },
 /*3a*/	{ "",	   FALSE, NONE,  0,	      0 },
 /*3b*/	{ "",	   FALSE, NONE,  0,	      0 },
@@ -266,6 +309,26 @@
 /*4f*/	{ "cmovnle",TRUE, NONE,  op2(E, R),   0 },
 };
 
+static const struct inst db_inst_0f7x[] = {
+/*70*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*71*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*72*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*73*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*74*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*75*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*76*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*77*/	{ "",	   FALSE, NONE,  0,	      0 },
+
+/*78*/	{ "vmread", TRUE, NONE,  op2(Rq, E),  0 },
+/*79*/	{ "vmwrite",TRUE, NONE,  op2(E, Rq),  0 },
+/*7a*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*7b*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*7c*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*7d*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*7e*/	{ "",	   FALSE, NONE,  0,	      0 },
+/*7f*/	{ "",	   FALSE, NONE,  0,	      0 },
+};
+
 static const struct inst db_inst_0f8x[] = {
 /*80*/	{ "jo",    FALSE, NONE,  op1(Dl),     0 },
 /*81*/	{ "jno",   FALSE, NONE,  op1(Dl),     0 },
@@ -373,7 +436,7 @@
 	db_inst_0f4x,
 	0,
 	0,
-	0,
+	db_inst_0f7x,
 	db_inst_0f8x,
 	db_inst_0f9x,
 	db_inst_0fax,
@@ -582,7 +645,7 @@
 /*0c*/	{ "or",    FALSE, BYTE,  op2(I, A),  0 },
 /*0d*/	{ "or",    FALSE, LONG,  op2(I, A),  0 },
 /*0e*/	{ "push",  FALSE, NONE,  op1(Si),    0 },
-/*0f*/	{ "",      FALSE, NONE,  0,	     0 },
+/*0f*/	{ "",      FALSE, ESC,   0,	     db_inst_0f },
 
 /*10*/	{ "adc",   TRUE,  BYTE,  op2(R, E),  0 },
 /*11*/	{ "adc",   TRUE,  LONG,  op2(R, E),  0 },
@@ -738,8 +801,8 @@
 /*96*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
 /*97*/	{ "xchg",  FALSE, LONG,  op2(A, Ri),  0 },
 
-/*98*/	{ "cbw",   FALSE, SDEP,  0,	      "cwde" },	/* cbw/cwde */
-/*99*/	{ "cwd",   FALSE, SDEP,  0,	      "cdq"  },	/* cwd/cdq */
+/*98*/	{ "cwde",  FALSE, SDEP,  0,	      "cbw" },
+/*99*/	{ "cdq",   FALSE, SDEP,  0,	      "cwd" },
 /*9a*/	{ "lcall", FALSE, NONE,  op1(OS),     0 },
 /*9b*/	{ "wait",  FALSE, NONE,  0,	      0 },
 /*9c*/	{ "pushf", FALSE, LONG,  0,	      0 },
@@ -822,7 +885,7 @@
 /*e0*/	{ "loopne",FALSE, NONE,  op1(Db),     0 },
 /*e1*/	{ "loope", FALSE, NONE,  op1(Db),     0 },
 /*e2*/	{ "loop",  FALSE, NONE,  op1(Db),     0 },
-/*e3*/	{ "jcxz",  FALSE, SDEP,  op1(Db),     "jecxz" },
+/*e3*/	{ "jrcxz", FALSE, ADEP,  op1(Db),     "jecxz" },
 /*e4*/	{ "in",    FALSE, BYTE,  op2(Ib, A),  0 },
 /*e5*/	{ "in",    FALSE, LONG,  op2(Ib, A) , 0 },
 /*e6*/	{ "out",   FALSE, BYTE,  op2(A, Ib),  0 },
@@ -1208,14 +1271,6 @@
 	    if (prefix) {
 		get_value_inc(inst, loc, 1, FALSE);
 	    }
-	    if (rep == TRUE) {
-		if (inst == 0x90) {
-		    db_printf("pause\n");
-		    return (loc);
-		}
-		db_printf("repe ");	/* XXX repe VS rep */
-		rep = FALSE;
-	    }
 	} while (prefix);
 
 	if (inst >= 0xd8 && inst <= 0xdf) {
@@ -1224,9 +1279,10 @@
 	    return (loc);
 	}
 
-	if (inst == 0x0f) {
+	ip = &db_inst_table[inst];
+	while (ip->i_size == ESC) {
 	    get_value_inc(inst, loc, 1, FALSE);
-	    ip = db_inst_0f[inst>>4];
+	    ip = ((const struct inst * const *)ip->i_extra)[inst>>4];
 	    if (ip == 0) {
 		ip = &db_bad_inst;
 	    }
@@ -1234,8 +1290,6 @@
 		ip = &ip[inst&0xf];
 	    }
 	}
-	else
-	    ip = &db_inst_table[inst];
 
 	if (ip->i_has_modrm) {
 	    get_value_inc(regmodrm, loc, 1, FALSE);
@@ -1327,8 +1381,42 @@
 		i_mode = 0;
 	}
 
+	/* Handle instructions identified by mandatory prefixes. */
+	if (rep == TRUE) {
+	    if (inst == 0x90) {
+		i_name = "pause";
+		i_size = NONE;
+		i_mode = 0;
+		rep = FALSE;
+	    } else if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) != 3 &&
+		f_reg(rex, regmodrm) == 0x6) {
+		i_name = "vmxon";
+		rep = FALSE;
+	    }
+	}
+	if (size == WORD) {
+	    if (ip->i_extra == db_Grp9 && f_mod(rex, regmodrm) != 3 &&
+		f_reg(rex, regmodrm) == 0x6) {
+		i_name = "vmclear";
+	    }
+	}
+	if (rex & REX_W) {
+	    if (strcmp(i_name, "cwde") == 0)
+		i_name = "cdqe";
+	    else if (strcmp(i_name, "cmpxchg8b") == 0)
+		i_name = "cmpxchg16b";
+	}
+
+	if (rep == TRUE)
+	    db_printf("repe ");	/* XXX repe VS rep */
+
 	if (i_size == SDEP) {
-	    if (size == WORD)
+	    if (size == LONG)
+		db_printf("%s", i_name);
+	    else
+		db_printf("%s", (const char *)ip->i_extra);
+	} else if (i_size == ADEP) {
+	    if (short_addr == FALSE)
 		db_printf("%s", i_name);
 	    else
 		db_printf("%s", (const char *)ip->i_extra);
@@ -1401,6 +1489,10 @@
 		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][WORD][f_reg(rex, regmodrm)]);
 		    break;
 
+		case Rq:
+		    db_printf("%s", db_reg[rex != 0 ? 1 : 0][QUAD][f_reg(rex, regmodrm)]);
+		    break;
+
 		case Ri:
 		    db_printf("%s", db_reg[0][QUAD][f_rm(rex, inst)]);
 		    break;

==== //depot/projects/smpng/sys/modules/x86dis/Makefile#2 (text+ko) ====

@@ -4,4 +4,7 @@
 SRCS=	x86dis.c
 KMODDIR=/boot/modules
 
+# To use newer binutils
+#CFLAGS+=	-B /usr/local/bin
+
 .include <bsd.kmod.mk>

==== //depot/projects/smpng/sys/modules/x86dis/x86dis.c#7 (text+ko) ====

@@ -10,13 +10,7 @@
 
 	low = mask;
 	hi = mask >> 32;
-#ifdef NEW_AS
 	__asm __volatile("xrstor %0" : : "m" (*addr), "a" (low), "d" (hi));
-#else
-	/* xrstor (%rdi) */
-	__asm __volatile(".byte	0x0f,0xae,0x2f" : :
-	    "a" (low), "d" (hi), "D" (addr));
-#endif
 }
 
 static __inline void
@@ -26,14 +20,8 @@
 
 	low = mask;
 	hi = mask >> 32;
-#ifdef NEW_AS
 	__asm __volatile("xsave %0" : "=m" (*addr) : "a" (low), "d" (hi) :
 	    "memory");
-#else
-	/* xsave (%rdi) */
-	__asm __volatile(".byte	0x0f,0xae,0x27" : :
-	    "a" (low), "d" (hi), "D" (addr) : "memory");
-#endif
 }
 
 static __inline void
@@ -43,14 +31,8 @@
 
 	low = mask;
 	hi = mask >> 32;
-#ifdef NEW_AS
 	__asm __volatile("xsaveopt %0" : "=m" (*addr) : "a" (low), "d" (hi) :
 	    "memory");
-#else
-	/* xsaveopt (%rdi) */
-	__asm __volatile(".byte	0x0f,0xae,0x37" : :
-	    "a" (low), "d" (hi), "D" (addr) : "memory");
-#endif
 }
 
 static __inline uint64_t
@@ -58,12 +40,7 @@
 {
 	uint32_t low, high;
 
-#ifdef NEW_AS
 	__asm __volatile("xgetbv" : "=a" (low), "=d" (high) : "c" (reg));
-#else
-	__asm __volatile(".byte 0x0f,0x01,0xd0" : "=a" (low), "=d" (high) :
-	    "c" (reg));
-#endif
 	return (low | ((uint64_t)high << 32));
 }
 
@@ -74,12 +51,7 @@
 
 	low = val;
 	hi = val >> 32;
-#ifdef NEW_AS
 	__asm __volatile("xsetbv" : : "c" (reg), "a" (low), "d" (hi));
-#else
-	__asm __volatile(".byte 0x0f,0x01,0xd1" : :
-	    "c" (reg), "a" (low), "d" (hi));
-#endif
 }
 
 static __inline uint64_t
@@ -91,49 +63,69 @@
 	return (low | ((uint64_t)high << 32));
 }
 
-static __inline void
-vmcall(void)
-{
-
-	__asm __volatile(".byte 0x0f,0x01,0xc1");
-}
-
-static __inline void
-vmlaunch(void)
-{
-
-	__asm __volatile(".byte 0x0f,0x01,0xc2");
-}
-
-static __inline void
-vmresume(void)
-{
-
-	__asm __volatile(".byte 0x0f,0x01,0xc3");
-}
-
 extern void
 isn_list(char *addr, uint32_t reg, uint64_t mask, uint64_t val);
 
 void
 isn_list(char *addr, uint32_t reg, uint64_t mask, uint64_t val)
 {
+#if 0
 	uint32_t aux;
 
-	/*
-	 * XXX: More to add?
-	 */
 	rdtscp(&aux);
 	xsaveopt(addr, mask);
 	xrstor(addr, mask);
 	xsave(addr, mask);
 	xgetbv(reg);
 	xsetbv(reg, val);
-	vmcall();
-	vmlaunch();
-	vmresume();
 	__asm __volatile("lfence" ::: "memory");
 	mfence();
 	__asm __volatile("sfence" ::: "memory");
 	clflush((u_long)addr);
+#endif
+	/*
+	 * TODO:
+	 * * invept
+	 * * invvpid
+	 * * vmcall
+	 * * vmclear
+	 * * vmlaunch
+	 * * vmresume
+	 * * vmptrld
+	 * * vmptrst
+	 * * vmread
+	 * * vmwrite
+	 * * vmxoff
+	 * * vmxon
+	 */
+	__asm __volatile("cbw");
+	__asm __volatile("cwde");
+	__asm __volatile("cdqe");
+	__asm __volatile("cwd");
+	__asm __volatile("cdq");
+	__asm __volatile("jecxz 1f; 1:");
+	__asm __volatile("jrcxz 1f; 1:");
+	__asm __volatile("pause");
+	__asm __volatile("cmpxchg8b %0" : "+m" (*addr));
+	__asm __volatile("cmpxchg16b %0" : "+m" (*addr));
+	__asm __volatile("rep stosl");
+#ifdef NEW_AS
+	__asm __volatile("invept %0,%1" :: "m" (*addr), "r" ((uint64_t)reg));
+	__asm __volatile("invvpid %0,%1" :: "m" (*addr), "r" ((uint64_t)reg));
+#else
+	/* invept (%rdi),%rax */
+	__asm __volatile(".byte 0x66,0x0f,0x38,0x80,0x07" :: "D" (*addr), "a" (reg));
+	/* invvpid (%rdi),%rax */
+	__asm __volatile(".byte 0x66,0x0f,0x38,0x81,0x07" :: "D" (*addr), "a" (reg));
+#endif
+	__asm __volatile("vmcall");
+	__asm __volatile("vmclear %0" : "=m" (*addr));
+	__asm __volatile("vmlaunch");
+	__asm __volatile("vmresume");
+	__asm __volatile("vmptrld %0" :: "m" (*addr));
+	__asm __volatile("vmptrst %0" :: "m" (*addr));
+	__asm __volatile("vmread %1,%0" : "=m" (*addr) : "r" ((uint64_t)reg));
+	__asm __volatile("vmwrite %0,%1" :: "m" (*addr), "r" ((uint64_t)reg));
+	__asm __volatile("vmxoff");
+	__asm __volatile("vmxon %0" :: "m" (*addr));
 }


More information about the p4-projects mailing list