diff options
author | Robert Mustacchi <rm@joyent.com> | 2016-06-09 11:51:57 -0700 |
---|---|---|
committer | Robert Mustacchi <rm@joyent.com> | 2016-08-04 19:54:28 -0700 |
commit | 8889c875bfb3c5aec61e4e417d6f66cf24a7255a (patch) | |
tree | e89b2d3452b7813e7fa08d24c483200139837d62 /usr/src | |
parent | 0af1cc2c200dcee1cb119ba8e280ebacdbfcf839 (diff) | |
download | illumos-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.c | 80 | ||||
-rw-r--r-- | usr/src/common/elfcap/elfcap.c | 8 | ||||
-rw-r--r-- | usr/src/common/elfcap/elfcap.h | 2 | ||||
-rw-r--r-- | usr/src/uts/common/sys/auxv_386.h | 4 | ||||
-rw-r--r-- | usr/src/uts/i86pc/os/cpuid.c | 18 | ||||
-rw-r--r-- | usr/src/uts/intel/sys/x86_archext.h | 10 |
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); |