Quantcast

PERFORCE change 213974 for review

classic Classic list List threaded Threaded
1 message Options
Reply | Threaded
Open this post in threaded view
|  
Report Content as Inappropriate
star

PERFORCE change 213974 for review

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

Change 213974 by jhb@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));
 }
_______________________________________________
[hidden email] mailing list
http://lists.freebsd.org/mailman/listinfo/p4-projects
To unsubscribe, send any mail to "[hidden email]"
Loading...