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