Date: Fri, 6 Jul 2012 12:22:17 GMT From: John Baldwin <jhb@FreeBSD.org> To: Perforce Change Reviews <perforce@freebsd.org> Subject: PERFORCE change 213974 for review Message-ID: <201207061222.q66CMH38058707@skunkworks.freebsd.org>
next in thread | raw e-mail | index | archive | help
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)); }
Want to link to this message? Use this URL: <https://mail-archive.FreeBSD.org/cgi/mid.cgi?201207061222.q66CMH38058707>
