summaryrefslogtreecommitdiff
path: root/usr/src
diff options
context:
space:
mode:
authorRobert Mustacchi <rm@joyent.com>2016-06-09 11:51:57 -0700
committerRobert Mustacchi <rm@joyent.com>2016-08-04 19:54:28 -0700
commit8889c875bfb3c5aec61e4e417d6f66cf24a7255a (patch)
treee89b2d3452b7813e7fa08d24c483200139837d62 /usr/src
parent0af1cc2c200dcee1cb119ba8e280ebacdbfcf839 (diff)
downloadillumos-joyent-8889c875bfb3c5aec61e4e417d6f66cf24a7255a.tar.gz
7204 Want broadwell rdseed and adx support
7208 Want stac/clac disasm support Reviewed by: Patrick Mooney <patrick.mooney@joyent.com> Reviewed by: Richard Lowe <richlowe@richlowe.net> Reviewed by: Jason King <jason.brian.king@gmail.com> Approved by: Dan McDonald <danmcd@omniti.com>
Diffstat (limited to 'usr/src')
-rw-r--r--usr/src/common/dis/i386/dis_tables.c80
-rw-r--r--usr/src/common/elfcap/elfcap.c8
-rw-r--r--usr/src/common/elfcap/elfcap.h2
-rw-r--r--usr/src/uts/common/sys/auxv_386.h4
-rw-r--r--usr/src/uts/i86pc/os/cpuid.c18
-rw-r--r--usr/src/uts/intel/sys/x86_archext.h10
6 files changed, 110 insertions, 12 deletions
diff --git a/usr/src/common/dis/i386/dis_tables.c b/usr/src/common/dis/i386/dis_tables.c
index 9e63143ef6..c21c392d77 100644
--- a/usr/src/common/dis/i386/dis_tables.c
+++ b/usr/src/common/dis/i386/dis_tables.c
@@ -237,7 +237,8 @@ enum {
VMxo, /* VMx instruction with optional prefix */
SVM, /* AMD SVM instructions */
BLS, /* BLSR, BLSMSK, BLSI */
- FMA /* FMA instructions, all VEX_RMrX */
+ FMA, /* FMA instructions, all VEX_RMrX */
+ ADX /* ADX instructions, support REX.w, mod_rm->mod_reg */
};
/*
@@ -569,7 +570,7 @@ const instable_t dis_op0FC7[8] = {
const instable_t dis_op0FC7m3[8] = {
/* [0] */ INVALID, INVALID, INVALID, INVALID,
-/* [4] */ INVALID, INVALID, TNS("rdrand",MG9), INVALID,
+/* [4] */ INVALID, INVALID, TNS("rdrand",MG9), TNS("rdseed", MG9),
};
/*
@@ -1405,6 +1406,15 @@ const instable_t dis_op0F38F1[2] = {
TS("movbe",MOVBE),
};
+/*
+ * The following table is used to distinguish between adox and adcx which share
+ * the same opcodes.
+ */
+const instable_t dis_op0F38F6[2] = {
+/* [00] */ TNS("adcx",ADX),
+ TNS("adox",ADX),
+};
+
const instable_t dis_op0F38[256] = {
/* [00] */ TNSZ("pshufb",XMM_66o,16),TNSZ("phaddw",XMM_66o,16),TNSZ("phaddd",XMM_66o,16),TNSZ("phaddsw",XMM_66o,16),
/* [04] */ TNSZ("pmaddubsw",XMM_66o,16),TNSZ("phsubw",XMM_66o,16), TNSZ("phsubd",XMM_66o,16),TNSZ("phsubsw",XMM_66o,16),
@@ -1481,7 +1491,7 @@ const instable_t dis_op0F38[256] = {
/* [E8] */ INVALID, INVALID, INVALID, INVALID,
/* [EC] */ INVALID, INVALID, INVALID, INVALID,
/* [F0] */ IND(dis_op0F38F0), IND(dis_op0F38F1), INVALID, INVALID,
-/* [F4] */ INVALID, INVALID, INVALID, INVALID,
+/* [F4] */ INVALID, INVALID, IND(dis_op0F38F6), INVALID,
/* [F8] */ INVALID, INVALID, INVALID, INVALID,
/* [FC] */ INVALID, INVALID, INVALID, INVALID,
};
@@ -1532,8 +1542,6 @@ const instable_t dis_opAVX660F38[256] = {
/* [88] */ INVALID, INVALID, INVALID, INVALID,
/* [8C] */ TSaZ("vpmaskmov",VEX_RMrX,16),INVALID, TSaZ("vpmaskmov",VEX_RRM,16),INVALID,
-/* XXX All of the gather things are a bit wrong. We're not properly changing the last character */
-
/* [90] */ TNSZ("vpgatherd",VEX_SbVM,16),TNSZ("vpgatherq",VEX_SbVM,16),TNSZ("vgatherdp",VEX_SbVM,16),TNSZ("vgatherqp",VEX_SbVM,16),
/* [94] */ INVALID, INVALID, TNSZ("vfmaddsub132p",FMA,16),TNSZ("vfmsubadd132p",FMA,16),
/* [98] */ TNSZ("vfmadd132p",FMA,16),TNSZ("vfmadd132s",FMA,16),TNSZ("vfmsub132p",FMA,16),TNSZ("vfmsub132s",FMA,16),
@@ -1734,6 +1742,15 @@ const instable_t dis_opAVX660F3A[256] = {
};
/*
+ * Decode table for 0x0F0D which uses the first byte of the mod_rm to
+ * indicate a sub-code.
+ */
+const instable_t dis_op0F0D[8] = {
+/* [00] */ INVALID, TNS("prefetchw",PREF), TNS("prefetchwt1",PREF),INVALID,
+/* [04] */ INVALID, INVALID, INVALID, INVALID,
+};
+
+/*
* Decode table for 0x0F opcodes
*/
@@ -1742,7 +1759,7 @@ const instable_t dis_op0F[16][16] = {
/* [00] */ IND(dis_op0F00), IND(dis_op0F01), TNS("lar",MR), TNS("lsl",MR),
/* [04] */ INVALID, TNS("syscall",NORM), TNS("clts",NORM), TNS("sysret",NORM),
/* [08] */ TNS("invd",NORM), TNS("wbinvd",NORM), INVALID, TNS("ud2",NORM),
-/* [0C] */ INVALID, INVALID, INVALID, INVALID,
+/* [0C] */ INVALID, IND(dis_op0F0D), INVALID, INVALID,
}, {
/* [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),
@@ -3310,11 +3327,49 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
dp++;
}
}
+
+ /*
+ * The adx family of instructions (adcx and adox)
+ * continue the classic Intel tradition of abusing
+ * arbitrary prefixes without actually meaning the
+ * prefix bit. Therefore, if we find either the
+ * opnd_size_prefix or rep_prefix we end up zeroing it
+ * out after making our determination so as to ensure
+ * that we don't get confused and accidentally print
+ * repz prefixes and the like on these instructions.
+ *
+ * In addition, these instructions are actually much
+ * closer to AVX instructions in semantics. Importantly,
+ * they always default to having 32-bit operands.
+ * However, if the CPU is in 64-bit mode, then and only
+ * then, does it use REX.w promotes things to 64-bits
+ * and REX.r allows 64-bit mode to use register r8-r15.
+ */
+ if (dp->it_indirect == (instable_t *)dis_op0F38F6) {
+ dp = dp->it_indirect;
+ if (opnd_size_prefix == 0 &&
+ rep_prefix == 0xf3) {
+ /* It is adox */
+ dp++;
+ } else if (opnd_size_prefix != 0x66 &&
+ rep_prefix != 0) {
+ /* It isn't adcx */
+ goto error;
+ }
+ opnd_size_prefix = 0;
+ rep_prefix = 0;
+ opnd_size = SIZE32;
+ if (rex_prefix & REX_W)
+ opnd_size = SIZE64;
+ }
+
#ifdef DIS_TEXT
if (strcmp(dp->it_name, "INVALID") == 0)
goto error;
#endif
switch (dp->it_adrmode) {
+ case ADX:
+ break;
case RM_66r:
case XMM_66r:
case XMMM_66r:
@@ -3719,6 +3774,7 @@ dtrace_disx86(dis86_t *x, uint_t cpu_mode)
/* memory or register operand to register, with 'w' bit */
case MRw:
+ case ADX:
wbit = WBIT(opcode2);
STANDARD_MODRM(x, mode, reg, r_m, rex_prefix, wbit, 0);
break;
@@ -4018,6 +4074,18 @@ just_mem:
#endif
NOMEM;
break;
+ } else if (r_m == 2) {
+#ifdef DIS_TEXT
+ (void) strncpy(x->d86_mnem, "clac", OPLEN);
+#endif
+ NOMEM;
+ break;
+ } else if (r_m == 3) {
+#ifdef DIS_TEXT
+ (void) strncpy(x->d86_mnem, "stac", OPLEN);
+#endif
+ NOMEM;
+ break;
} else {
goto error;
}
diff --git a/usr/src/common/elfcap/elfcap.c b/usr/src/common/elfcap/elfcap.c
index 25cef1e307..d63db8e981 100644
--- a/usr/src/common/elfcap/elfcap.c
+++ b/usr/src/common/elfcap/elfcap.c
@@ -332,6 +332,14 @@ static const elfcap_desc_t hw2_386[ELFCAP_NUM_HW2_386] = {
AV_386_2_AVX2, STRDESC("AV_386_2_AVX2"),
STRDESC("AVX2"), STRDESC("avx2"),
},
+ { /* 0x00000040 */
+ AV_386_2_ADX, STRDESC("AV_386_2_ADX"),
+ STRDESC("ADX"), STRDESC("adx"),
+ },
+ { /* 0x00000080 */
+ AV_386_2_RDSEED, STRDESC("AV_386_2_RDSEED"),
+ STRDESC("RDSEED"), STRDESC("rdseed"),
+ }
};
/*
diff --git a/usr/src/common/elfcap/elfcap.h b/usr/src/common/elfcap/elfcap.h
index fc2101ac87..f3e29a6a97 100644
--- a/usr/src/common/elfcap/elfcap.h
+++ b/usr/src/common/elfcap/elfcap.h
@@ -115,7 +115,7 @@ typedef enum {
#define ELFCAP_NUM_SF1 3
#define ELFCAP_NUM_HW1_SPARC 17
#define ELFCAP_NUM_HW1_386 32
-#define ELFCAP_NUM_HW2_386 6
+#define ELFCAP_NUM_HW2_386 8
/*
diff --git a/usr/src/uts/common/sys/auxv_386.h b/usr/src/uts/common/sys/auxv_386.h
index ec4c8b0f19..a3256a464f 100644
--- a/usr/src/uts/common/sys/auxv_386.h
+++ b/usr/src/uts/common/sys/auxv_386.h
@@ -89,10 +89,12 @@ extern "C" {
#define AV_386_2_BMI2 0x00008 /* BMI2 insns */
#define AV_386_2_FMA 0x00010 /* FMA insns */
#define AV_386_2_AVX2 0x00020 /* AVX2 insns */
+#define AV_386_2_ADX 0x00040 /* ADX insns */
+#define AV_386_2_RDSEED 0x00080 /* RDSEED insn */
#define FMT_AV_386_2 \
"\020" \
- "\06avx2\05fma\04bmi2\03bmi1\02rdrand\01f16c"
+ "\10rdseed\07adx\06avx2\05fma\04bmi2\03bmi1\02rdrand\01f16c"
#ifdef __cplusplus
}
diff --git a/usr/src/uts/i86pc/os/cpuid.c b/usr/src/uts/i86pc/os/cpuid.c
index 44e475f328..dfb72dacf4 100644
--- a/usr/src/uts/i86pc/os/cpuid.c
+++ b/usr/src/uts/i86pc/os/cpuid.c
@@ -171,7 +171,9 @@ static char *x86_feature_names[NUM_X86_FEATURES] = {
"bmi2",
"fma",
"smep",
- "smap"
+ "smap",
+ "adx",
+ "rdseed"
};
boolean_t
@@ -1264,6 +1266,11 @@ cpuid_pass1(cpu_t *cpu, uchar_t *featureset)
disable_smap == 0)
add_x86_feature(featureset, X86FSET_SMAP);
#endif
+ if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_RDSEED)
+ add_x86_feature(featureset, X86FSET_RDSEED);
+
+ if (ecp->cp_ebx & CPUID_INTC_EBX_7_0_ADX)
+ add_x86_feature(featureset, X86FSET_ADX);
}
/*
@@ -2739,6 +2746,10 @@ cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
*ebx &= ~CPUID_INTC_EBX_7_0_BMI2;
if (!is_x86_feature(x86_featureset, X86FSET_AVX2))
*ebx &= ~CPUID_INTC_EBX_7_0_AVX2;
+ if (!is_x86_feature(x86_featureset, X86FSET_RDSEED))
+ *ebx &= ~CPUID_INTC_EBX_7_0_RDSEED;
+ if (!is_x86_feature(x86_featureset, X86FSET_ADX))
+ *ebx &= ~CPUID_INTC_EBX_7_0_ADX;
/*
* [no explicit support required beyond x87 fp context]
@@ -2808,6 +2819,11 @@ cpuid_pass4(cpu_t *cpu, uint_t *hwcap_out)
if (*ecx & CPUID_INTC_ECX_RDRAND)
hwcap_flags_2 |= AV_386_2_RDRAND;
+ if (*ebx & CPUID_INTC_EBX_7_0_ADX)
+ hwcap_flags_2 |= AV_386_2_ADX;
+ if (*ebx & CPUID_INTC_EBX_7_0_RDSEED)
+ hwcap_flags_2 |= AV_386_2_RDSEED;
+
}
if (cpi->cpi_xmaxeax < 0x80000001)
diff --git a/usr/src/uts/intel/sys/x86_archext.h b/usr/src/uts/intel/sys/x86_archext.h
index 4aedd08a53..8dba3414ae 100644
--- a/usr/src/uts/intel/sys/x86_archext.h
+++ b/usr/src/uts/intel/sys/x86_archext.h
@@ -28,7 +28,7 @@
* All rights reserved.
*/
/*
- * Copyright (c) 2015, Joyent, Inc.
+ * Copyright 2015 Joyent, Inc.
* Copyright 2012 Jens Elkner <jel+illumos@cs.uni-magdeburg.de>
* Copyright 2012 Hans Rosenfeld <rosenfeld@grumpf.hope-2000.org>
* Copyright 2014 Josef 'Jeff' Sipek <jeffpc@josefsipek.net>
@@ -194,7 +194,9 @@ extern "C" {
#define CPUID_INTC_EBX_7_0_BMI1 0x00000008 /* BMI1 instrs */
#define CPUID_INTC_EBX_7_0_AVX2 0x00000020 /* AVX2 supported */
#define CPUID_INTC_EBX_7_0_SMEP 0x00000080 /* SMEP in CR4 */
-#define CPUID_INTC_EBX_7_0_BMI2 0x00000100 /* BMI2 Instrs */
+#define CPUID_INTC_EBX_7_0_BMI2 0x00000100 /* BMI2 instrs */
+#define CPUID_INTC_EBX_7_0_RDSEED 0x00040000 /* RDSEED instr */
+#define CPUID_INTC_EBX_7_0_ADX 0x00080000 /* ADX instrs */
#define CPUID_INTC_EBX_7_0_SMAP 0x00100000 /* SMAP in CR 4 */
#define P5_MCHADDR 0x0
@@ -372,6 +374,8 @@ extern "C" {
#define X86FSET_FMA 44
#define X86FSET_SMEP 45
#define X86FSET_SMAP 46
+#define X86FSET_ADX 47
+#define X86FSET_RDSEED 48
/*
* flags to patch tsc_read routine.
@@ -632,7 +636,7 @@ extern "C" {
#if defined(_KERNEL) || defined(_KMEMUSER)
-#define NUM_X86_FEATURES 47
+#define NUM_X86_FEATURES 49
extern uchar_t x86_featureset[];
extern void free_x86_featureset(void *featureset);