aboutsummaryrefslogtreecommitdiff
path: root/sys
diff options
context:
space:
mode:
authorPeter Grehan <grehan@FreeBSD.org>2014-05-15 01:06:27 +0000
committerPeter Grehan <grehan@FreeBSD.org>2014-05-15 01:06:27 +0000
commitc3ddb60e2d7b68e2e1c6b00d520939ae2609d1b3 (patch)
tree3b0532cdedc985dd0a9010e7402b5303267de3d7 /sys
parentf3db4c53e64e3bd60e88afd9dec01175bbc647dc (diff)
downloadsrc-c3ddb60e2d7b68e2e1c6b00d520939ae2609d1b3.tar.gz
src-c3ddb60e2d7b68e2e1c6b00d520939ae2609d1b3.zip
Update dis_tables.c to the latest Illumos version.
This includes decodes of recent Intel instructions, in particular VT-x and related instructions. This allows the FBT provider to locate the exit points of routines that include these new instructions. Illumos issues: 3414 Need a new word of AT_SUN_HWCAP bits 3415 Add isainfo support for f16c and rdrand 3416 Need disassembler support for rdrand and f16c 3413 isainfo -v overflows 80 columns 3417 mdb disassembler confuses rdtscp for invlpg 1518 dis should support AMD SVM/AMD-V/Pacifica instructions 1096 i386 disassembler should understand complex nops 1362 add kvmstat for monitoring of KVM statistics 1363 add vmregs[] variable to DTrace 1364 need disassembler support for VMX instructions 1365 mdb needs 16-bit disassembler support This corresponds to Illumos-gate (github) version eb23829ff08a873c612ac45d191d559394b4b408 Reviewed by: markj MFC after: 1 week
Notes
Notes: svn path=/head/; revision=266103
Diffstat (limited to 'sys')
-rw-r--r--sys/cddl/dev/dtrace/x86/dis_tables.c205
1 files changed, 188 insertions, 17 deletions
diff --git a/sys/cddl/dev/dtrace/x86/dis_tables.c b/sys/cddl/dev/dtrace/x86/dis_tables.c
index 72fa4bffcfcb..aabbf71cb79d 100644
--- a/sys/cddl/dev/dtrace/x86/dis_tables.c
+++ b/sys/cddl/dev/dtrace/x86/dis_tables.c
@@ -21,6 +21,7 @@
*/
/*
* Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2012, Joyent, Inc. All rights reserved.
*/
/*
@@ -104,16 +105,18 @@ enum {
Mv,
Mw,
M, /* register or memory */
+ MG9, /* register or memory in group 9 (prefix optional) */
Mb, /* register or memory, always byte sized */
MO, /* memory only (no registers) */
PREF,
- SWAPGS,
+ SWAPGS_RDTSCP,
MONITOR_MWAIT,
R,
RA,
SEG,
MR,
RM,
+ RM_66r, /* RM, but with a required 0x66 prefix */
IA,
MA,
SD,
@@ -228,7 +231,10 @@ enum {
VEX_RRi, /* VEX mod_rm, imm8 -> mod_reg */
VEX_RM, /* VEX mod_reg -> mod_rm */
VEX_RRM, /* VEX VEX.vvvv, mod_reg -> mod_rm */
- VEX_RMX /* VEX VEX.vvvv, mod_rm -> mod_reg */
+ VEX_RMX, /* VEX VEX.vvvv, mod_rm -> mod_reg */
+ VMx, /* vmcall/vmlaunch/vmresume/vmxoff */
+ VMxo, /* VMx instruction with optional prefix */
+ SVM /* AMD SVM instructions */
};
/*
@@ -496,8 +502,8 @@ const instable_t dis_op0F00[8] = {
*/
const instable_t dis_op0F01[8] = {
-/* [0] */ TNSZ("sgdt",MO,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",MO,6),
-/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS),
+/* [0] */ TNSZ("sgdt",VMx,6), TNSZ("sidt",MONITOR_MWAIT,6), TNSZ("lgdt",XGETBV_XSETBV,6), TNSZ("lidt",SVM,6),
+/* [4] */ TNSZ("smsw",M,2), INVALID, TNSZ("lmsw",M,2), TNS("invlpg",SWAPGS_RDTSCP),
};
/*
@@ -528,15 +534,44 @@ const instable_t dis_op0FBA[8] = {
};
/*
- * Decode table for 0x0FC7 opcode
+ * Decode table for 0x0FC7 opcode (group 9)
*/
const instable_t dis_op0FC7[8] = {
/* [0] */ INVALID, TNS("cmpxchg8b",M), INVALID, INVALID,
-/* [4] */ INVALID, INVALID, INVALID, INVALID,
+/* [4] */ INVALID, INVALID, TNS("vmptrld",MG9), TNS("vmptrst",MG9),
};
+/*
+ * Decode table for 0x0FC7 opcode (group 9) mode 3
+ */
+
+const instable_t dis_op0FC7m3[8] = {
+
+/* [0] */ INVALID, INVALID, INVALID, INVALID,
+/* [4] */ INVALID, INVALID, TNS("rdrand",MG9), INVALID,
+};
+
+/*
+ * Decode table for 0x0FC7 opcode with 0x66 prefix
+ */
+
+const instable_t dis_op660FC7[8] = {
+
+/* [0] */ INVALID, INVALID, INVALID, INVALID,
+/* [4] */ INVALID, INVALID, TNS("vmclear",M), INVALID,
+};
+
+/*
+ * Decode table for 0x0FC7 opcode with 0xF3 prefix
+ */
+
+const instable_t dis_opF30FC7[8] = {
+
+/* [0] */ INVALID, INVALID, INVALID, INVALID,
+/* [4] */ INVALID, INVALID, TNS("vmxon",M), INVALID,
+};
/*
* Decode table for 0x0FC8 opcode -- 486 bswap instruction
@@ -1147,7 +1182,7 @@ const instable_t dis_op0F38[256] = {
/* [78] */ INVALID, INVALID, INVALID, INVALID,
/* [7C] */ INVALID, INVALID, INVALID, INVALID,
-/* [80] */ INVALID, INVALID, INVALID, INVALID,
+/* [80] */ TNSy("invept", RM_66r), TNSy("invvpid", RM_66r),INVALID, INVALID,
/* [84] */ INVALID, INVALID, INVALID, INVALID,
/* [88] */ INVALID, INVALID, INVALID, INVALID,
/* [8C] */ INVALID, INVALID, INVALID, INVALID,
@@ -1193,7 +1228,7 @@ const instable_t dis_opAVX660F38[256] = {
/* [08] */ TNSZ("vpsignb",VEX_RMrX,16),TNSZ("vpsignw",VEX_RMrX,16),TNSZ("vpsignd",VEX_RMrX,16),TNSZ("vpmulhrsw",VEX_RMrX,16),
/* [0C] */ TNSZ("vpermilps",VEX_RMrX,8),TNSZ("vpermilpd",VEX_RMrX,16),TNSZ("vtestps",VEX_RRI,8), TNSZ("vtestpd",VEX_RRI,16),
-/* [10] */ INVALID, INVALID, INVALID, INVALID,
+/* [10] */ INVALID, INVALID, INVALID, TNSZ("vcvtph2ps",VEX_MX,16),
/* [14] */ INVALID, INVALID, INVALID, TNSZ("vptest",VEX_RRI,16),
/* [18] */ TNSZ("vbroadcastss",VEX_MX,4),TNSZ("vbroadcastsd",VEX_MX,8),TNSZ("vbroadcastf128",VEX_MX,16),INVALID,
/* [1C] */ TNSZ("vpabsb",VEX_MX,16),TNSZ("vpabsw",VEX_MX,16),TNSZ("vpabsd",VEX_MX,16),INVALID,
@@ -1359,7 +1394,7 @@ const instable_t dis_opAVX660F3A[256] = {
/* [10] */ INVALID, INVALID, INVALID, INVALID,
/* [14] */ TNSZ("vpextrb",VEX_RRi,8),TNSZ("vpextrw",VEX_RRi,16),TNSZ("vpextrd",VEX_RRi,16),TNSZ("vextractps",VEX_RM,16),
/* [18] */ TNSZ("vinsertf128",VEX_RMRX,16),TNSZ("vextractf128",VEX_RX,16),INVALID, INVALID,
-/* [1C] */ INVALID, INVALID, INVALID, INVALID,
+/* [1C] */ INVALID, TNSZ("vcvtps2ph",VEX_RX,16), INVALID, INVALID,
/* [20] */ TNSZ("vpinsrb",VEX_RMRX,8),TNSZ("vinsertps",VEX_RMRX,16),TNSZ("vpinsrd",VEX_RMRX,16),INVALID,
/* [24] */ INVALID, INVALID, INVALID, INVALID,
@@ -1446,7 +1481,7 @@ const instable_t dis_op0F[16][16] = {
/* [10] */ TNSZ("movups",XMMO,16), TNSZ("movups",XMMOS,16),TNSZ("movlps",XMMO,8), TNSZ("movlps",XMMOS,8),
/* [14] */ TNSZ("unpcklps",XMMO,16),TNSZ("unpckhps",XMMO,16),TNSZ("movhps",XMMOM,8),TNSZ("movhps",XMMOMS,8),
/* [18] */ IND(dis_op0F18), INVALID, INVALID, INVALID,
-/* [1C] */ INVALID, INVALID, INVALID, TS("nopw", Mw),
+/* [1C] */ INVALID, INVALID, INVALID, TS("nop",Mw),
}, {
/* [20] */ TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG), TSy("mov",SREG),
/* [24] */ TSx("mov",SREG), INVALID, TSx("mov",SREG), INVALID,
@@ -1475,7 +1510,7 @@ const instable_t dis_op0F[16][16] = {
}, {
/* [70] */ TNSZ("pshufw",MMOPM,8), TNS("psrXXX",MR), TNS("psrXXX",MR), TNS("psrXXX",MR),
/* [74] */ TNSZ("pcmpeqb",MMO,8), TNSZ("pcmpeqw",MMO,8), TNSZ("pcmpeqd",MMO,8), TNS("emms",NORM),
-/* [78] */ TNS("INVALID",XMMO), TNS("INVALID",XMMO), INVALID, INVALID,
+/* [78] */ TNSy("vmread",RM), TNSy("vmwrite",MR), INVALID, INVALID,
/* [7C] */ INVALID, INVALID, TNSZ("movd",MMOS,4), TNSZ("movq",MMOS,8),
}, {
/* [80] */ TNS("jo",D), TNS("jno",D), TNS("jb",D), TNS("jae",D),
@@ -1859,14 +1894,14 @@ const instable_t dis_distable[16][16] = {
/* [1,C] */ TNS("sbbb",IA), TS("sbb",IA), TSx("push",SEG), TSx("pop",SEG),
}, {
/* [2,0] */ TNS("andb",RMw), TS("and",RMw), TNS("andb",MRw), TS("and",MRw),
-/* [2,4] */ TNS("andb",IA), TS("and",IA), TNS("%es:",OVERRIDE), TNSx("daa",NORM),
+/* [2,4] */ TNS("andb",IA), TS("and",IA), TNSx("%es:",OVERRIDE), TNSx("daa",NORM),
/* [2,8] */ TNS("subb",RMw), TS("sub",RMw), TNS("subb",MRw), TS("sub",MRw),
/* [2,C] */ TNS("subb",IA), TS("sub",IA), TNS("%cs:",OVERRIDE), TNSx("das",NORM),
}, {
/* [3,0] */ TNS("xorb",RMw), TS("xor",RMw), TNS("xorb",MRw), TS("xor",MRw),
-/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNS("%ss:",OVERRIDE), TNSx("aaa",NORM),
+/* [3,4] */ TNS("xorb",IA), TS("xor",IA), TNSx("%ss:",OVERRIDE), TNSx("aaa",NORM),
/* [3,8] */ TNS("cmpb",RMw), TS("cmp",RMw), TNS("cmpb",MRw), TS("cmp",MRw),
-/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNS("%ds:",OVERRIDE), TNSx("aas",NORM),
+/* [3,C] */ TNS("cmpb",IA), TS("cmp",IA), TNSx("%ds:",OVERRIDE), TNSx("aas",NORM),
}, {
/* [4,0] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
/* [4,4] */ TSx("inc",R), TSx("inc",R), TSx("inc",R), TSx("inc",R),
@@ -2905,6 +2940,7 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
goto error;
#endif
switch (dp->it_adrmode) {
+ case RM_66r:
case XMM_66r:
case XMMM_66r:
if (opnd_size_prefix == 0) {
@@ -3054,6 +3090,59 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
}
break;
+ case MG9:
+ /*
+ * More horribleness: the group 9 (0xF0 0xC7) instructions are
+ * allowed an optional prefix of 0x66 or 0xF3. This is similar
+ * to the SIMD business described above, but with a different
+ * addressing mode (and an indirect table), so we deal with it
+ * separately (if similarly).
+ *
+ * Intel further complicated this with the release of Ivy Bridge
+ * where they overloaded these instructions based on the ModR/M
+ * bytes. The VMX instructions have a mode of 0 since they are
+ * memory instructions but rdrand instructions have a mode of
+ * 0b11 (REG_ONLY) because they only operate on registers. While
+ * there are different prefix formats, for now it is sufficient
+ * to use a single different table.
+ */
+
+ /*
+ * Calculate our offset in dis_op0FC7 (the group 9 table)
+ */
+ if ((uintptr_t)dp - (uintptr_t)dis_op0FC7 > sizeof (dis_op0FC7))
+ goto error;
+
+ off = ((uintptr_t)dp - (uintptr_t)dis_op0FC7) /
+ sizeof (instable_t);
+
+ /*
+ * If we have a mode of 0b11 then we have to rewrite this.
+ */
+ dtrace_get_modrm(x, &mode, &reg, &r_m);
+ if (mode == REG_ONLY) {
+ dp = (instable_t *)&dis_op0FC7m3[off];
+ break;
+ }
+
+ /*
+ * Rewrite if this instruction used one of the magic prefixes.
+ */
+ if (rep_prefix) {
+ if (rep_prefix == 0xf3)
+ dp = (instable_t *)&dis_opF30FC7[off];
+ else
+ goto error;
+ rep_prefix = 0;
+ } else if (opnd_size_prefix) {
+ dp = (instable_t *)&dis_op660FC7[off];
+ opnd_size_prefix = 0;
+ if (opnd_size == SIZE16)
+ opnd_size = SIZE32;
+ }
+ break;
+
+
case MMOSH:
/*
* As with the "normal" SIMD instructions, the MMX
@@ -3434,14 +3523,21 @@ just_mem:
dtrace_get_operand(x, mode, r_m, wbit, 0);
break;
- case SWAPGS:
+ case SWAPGS_RDTSCP:
if (cpu_mode == SIZE64 && mode == 3 && r_m == 0) {
#ifdef DIS_TEXT
(void) strncpy(x->d86_mnem, "swapgs", OPLEN);
#endif
NOMEM;
break;
+ } else if (mode == 3 && r_m == 1) {
+#ifdef DIS_TEXT
+ (void) strncpy(x->d86_mnem, "rdtscp", OPLEN);
+#endif
+ NOMEM;
+ break;
}
+
/*FALLTHROUGH*/
/* prefetch instruction - memory operand, but no memory acess */
@@ -3451,6 +3547,7 @@ just_mem:
/* single memory or register operand */
case M:
+ case MG9:
wbit = LONG_OPND;
goto just_mem;
@@ -3459,6 +3556,76 @@ just_mem:
wbit = BYTE_OPND;
goto just_mem;
+ case VMx:
+ if (mode == 3) {
+#ifdef DIS_TEXT
+ char *vminstr;
+
+ switch (r_m) {
+ case 1:
+ vminstr = "vmcall";
+ break;
+ case 2:
+ vminstr = "vmlaunch";
+ break;
+ case 3:
+ vminstr = "vmresume";
+ break;
+ case 4:
+ vminstr = "vmxoff";
+ break;
+ default:
+ goto error;
+ }
+
+ (void) strncpy(x->d86_mnem, vminstr, OPLEN);
+#else
+ if (r_m < 1 || r_m > 4)
+ goto error;
+#endif
+
+ NOMEM;
+ break;
+ }
+ /*FALLTHROUGH*/
+ case SVM:
+ if (mode == 3) {
+#ifdef DIS_TEXT
+ char *vinstr;
+
+ switch (r_m) {
+ case 0:
+ vinstr = "vmrun";
+ break;
+ case 1:
+ vinstr = "vmmcall";
+ break;
+ case 2:
+ vinstr = "vmload";
+ break;
+ case 3:
+ vinstr = "vmsave";
+ break;
+ case 4:
+ vinstr = "stgi";
+ break;
+ case 5:
+ vinstr = "clgi";
+ break;
+ case 6:
+ vinstr = "skinit";
+ break;
+ case 7:
+ vinstr = "invlpga";
+ break;
+ }
+
+ (void) strncpy(x->d86_mnem, vinstr, OPLEN);
+#endif
+ NOMEM;
+ break;
+ }
+ /*FALLTHROUGH*/
case MONITOR_MWAIT:
if (mode == 3) {
if (r_m == 0) {
@@ -3597,6 +3764,7 @@ just_mem:
break;
case RM:
+ case RM_66r:
wbit = LONG_OPND;
STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 1);
break;
@@ -4300,7 +4468,8 @@ L_VEX_MX:
dtrace_get_operand(x, REG_ONLY, reg, XMM_OPND, 1);
dtrace_get_operand(x, mode, r_m, wbit, 0);
} else if ((dp == &dis_opAVXF30F[0xE6]) ||
- (dp == &dis_opAVX0F[0x5][0xA])) {
+ (dp == &dis_opAVX0F[0x5][0xA]) ||
+ (dp == &dis_opAVX660F38[0x13])) {
/* vcvtdq2pd <xmm>, <ymm> */
/* or vcvtps2pd <xmm>, <ymm> */
dtrace_get_operand(x, REG_ONLY, reg, wbit, 1);
@@ -4385,7 +4554,9 @@ L_VEX_MX:
case VEX_RX:
/* ModR/M.rm := op(ModR/M.reg) */
- if (dp == &dis_opAVX660F3A[0x19]) { /* vextractf128 */
+ /* vextractf128 || vcvtps2ph */
+ if (dp == &dis_opAVX660F3A[0x19] ||
+ dp == &dis_opAVX660F3A[0x1d]) {
x->d86_numopnds = 3;
dtrace_get_modrm(x, &mode, &reg, &r_m);