@@ -3963,6 +3963,8 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt)
39633963 I2bv(((_f) | DstReg | SrcMem | ModRM) & ~Lock, _e), \
39643964 I2bv(((_f) & ~Lock) | DstAcc | SrcImm, _e)
39653965
3966+ static const struct opcode ud = I (SrcNone , emulate_ud );
3967+
39663968static const struct opcode group7_rm0 [] = {
39673969 N ,
39683970 I (SrcNone | Priv | EmulateOnUD , em_hypercall ),
@@ -4762,11 +4764,87 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
47624764 return rc ;
47634765}
47644766
4767+ static int x86_decode_avx (struct x86_emulate_ctxt * ctxt ,
4768+ u8 vex_1st , u8 vex_2nd , struct opcode * opcode )
4769+ {
4770+ u8 vex_3rd , map , pp , l , v ;
4771+ int rc = X86EMUL_CONTINUE ;
4772+
4773+ if (ctxt -> rep_prefix || ctxt -> op_prefix || ctxt -> rex_prefix )
4774+ goto ud ;
4775+
4776+ if (vex_1st == 0xc5 ) {
4777+ /* Expand RVVVVlpp to VEX3 format */
4778+ vex_3rd = vex_2nd & ~0x80 ; /* VVVVlpp from VEX2, w=0 */
4779+ vex_2nd = (vex_2nd & 0x80 ) | 0x61 ; /* R from VEX2, X=1 B=1 mmmmm=00001 */
4780+ } else {
4781+ vex_3rd = insn_fetch (u8 , ctxt );
4782+ }
4783+
4784+ /* vex_2nd = RXBmmmmm, vex_3rd = wVVVVlpp. Fix polarity */
4785+ vex_2nd ^= 0xE0 ; /* binary 11100000 */
4786+ vex_3rd ^= 0x78 ; /* binary 01111000 */
4787+
4788+ ctxt -> rex_prefix = REX_PREFIX ;
4789+ ctxt -> rex_bits = (vex_2nd & 0xE0 ) >> 5 ; /* RXB */
4790+ ctxt -> rex_bits |= (vex_3rd & 0x80 ) >> 4 ; /* w */
4791+ if (ctxt -> rex_bits && ctxt -> mode != X86EMUL_MODE_PROT64 )
4792+ goto ud ;
4793+
4794+ map = vex_2nd & 0x1f ;
4795+ v = (vex_3rd >> 3 ) & 0xf ;
4796+ l = vex_3rd & 0x4 ;
4797+ pp = vex_3rd & 0x3 ;
4798+
4799+ ctxt -> b = insn_fetch (u8 , ctxt );
4800+ switch (map ) {
4801+ case 1 :
4802+ ctxt -> opcode_len = 2 ;
4803+ * opcode = twobyte_table [ctxt -> b ];
4804+ break ;
4805+ case 2 :
4806+ ctxt -> opcode_len = 3 ;
4807+ * opcode = opcode_map_0f_38 [ctxt -> b ];
4808+ break ;
4809+ case 3 :
4810+ /* no 0f 3a instructions are supported yet */
4811+ return X86EMUL_UNHANDLEABLE ;
4812+ default :
4813+ goto ud ;
4814+ }
4815+
4816+ /*
4817+ * No three operand instructions are supported yet; those that
4818+ * *are* marked with the Avx flag reserve the VVVV flag.
4819+ */
4820+ if (v )
4821+ goto ud ;
4822+
4823+ if (l )
4824+ ctxt -> op_bytes = 32 ;
4825+ else
4826+ ctxt -> op_bytes = 16 ;
4827+
4828+ switch (pp ) {
4829+ case 0 : break ;
4830+ case 1 : ctxt -> op_prefix = true; break ;
4831+ case 2 : ctxt -> rep_prefix = 0xf3 ; break ;
4832+ case 3 : ctxt -> rep_prefix = 0xf2 ; break ;
4833+ }
4834+
4835+ done :
4836+ return rc ;
4837+ ud :
4838+ * opcode = ud ;
4839+ return rc ;
4840+ }
4841+
47654842int x86_decode_insn (struct x86_emulate_ctxt * ctxt , void * insn , int insn_len , int emulation_type )
47664843{
47674844 int rc = X86EMUL_CONTINUE ;
47684845 int mode = ctxt -> mode ;
47694846 int def_op_bytes , def_ad_bytes , goffset , simd_prefix ;
4847+ bool vex_prefix = false;
47704848 bool has_seg_override = false;
47714849 struct opcode opcode ;
47724850 u16 dummy ;
@@ -4883,7 +4961,21 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
48834961 ctxt -> op_bytes = 8 ;
48844962
48854963 /* Opcode byte(s). */
4886- if (ctxt -> b == 0x0f ) {
4964+ if (ctxt -> b == 0xc4 || ctxt -> b == 0xc5 ) {
4965+ /* VEX or LDS/LES */
4966+ u8 vex_2nd = insn_fetch (u8 , ctxt );
4967+ if (mode != X86EMUL_MODE_PROT64 && (vex_2nd & 0xc0 ) != 0xc0 ) {
4968+ opcode = opcode_table [ctxt -> b ];
4969+ ctxt -> modrm = vex_2nd ;
4970+ /* the Mod/RM byte has been fetched already! */
4971+ goto done_modrm ;
4972+ }
4973+
4974+ vex_prefix = true;
4975+ rc = x86_decode_avx (ctxt , ctxt -> b , vex_2nd , & opcode );
4976+ if (rc != X86EMUL_CONTINUE )
4977+ goto done ;
4978+ } else if (ctxt -> b == 0x0f ) {
48874979 /* Two- or three-byte opcode */
48884980 ctxt -> opcode_len = 2 ;
48894981 ctxt -> b = insn_fetch (u8 , ctxt );
@@ -4899,17 +4991,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
48994991 /* Opcode byte(s). */
49004992 opcode = opcode_table [ctxt -> b ];
49014993 }
4902- ctxt -> d = opcode .flags ;
49034994
4904- if (ctxt -> d & ModRM )
4995+ if (opcode . flags & ModRM )
49054996 ctxt -> modrm = insn_fetch (u8 , ctxt );
49064997
4907- /* vex-prefix instructions are not implemented */
4908- if (ctxt -> opcode_len == 1 && (ctxt -> b == 0xc5 || ctxt -> b == 0xc4 ) &&
4909- (mode == X86EMUL_MODE_PROT64 || (ctxt -> modrm & 0xc0 ) == 0xc0 )) {
4910- ctxt -> d = NotImpl ;
4911- }
4912-
4998+ done_modrm :
4999+ ctxt -> d = opcode .flags ;
49135000 while (ctxt -> d & GroupMask ) {
49145001 switch (ctxt -> d & GroupMask ) {
49155002 case Group :
@@ -4975,6 +5062,19 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
49755062 if (ctxt -> d == 0 )
49765063 return EMULATION_FAILED ;
49775064
5065+ if (unlikely (vex_prefix )) {
5066+ /*
5067+ * Only specifically marked instructions support VEX. Since many
5068+ * instructions support it but are not annotated, return not implemented
5069+ * rather than #UD.
5070+ */
5071+ if (!(ctxt -> d & Avx ))
5072+ return EMULATION_FAILED ;
5073+
5074+ if (!(ctxt -> d & AlignMask ))
5075+ ctxt -> d |= Unaligned ;
5076+ }
5077+
49785078 ctxt -> execute = opcode .u .execute ;
49795079
49805080 /*
@@ -5045,7 +5145,9 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len, int
50455145 if ((ctxt -> d & No16 ) && ctxt -> op_bytes == 2 )
50465146 ctxt -> op_bytes = 4 ;
50475147
5048- if (ctxt -> d & Sse )
5148+ if (vex_prefix )
5149+ ;
5150+ else if (ctxt -> d & Sse )
50495151 ctxt -> op_bytes = 16 , ctxt -> d &= ~Avx ;
50505152 else if (ctxt -> d & Mmx )
50515153 ctxt -> op_bytes = 8 ;
0 commit comments