Author: cem
Date: Tue Apr 21 21:33:06 2020
New Revision: 360176
URL: https://svnweb.freebsd.org/changeset/base/360176

Log:
  vmm(4): Decode 3-byte VEX-prefixed instructions
  
  Reviewed by:  grehan
  Differential Revision:        https://reviews.freebsd.org/D24462

Modified:
  head/sys/amd64/include/vmm.h
  head/sys/amd64/vmm/vmm_instruction_emul.c

Modified: head/sys/amd64/include/vmm.h
==============================================================================
--- head/sys/amd64/include/vmm.h        Tue Apr 21 19:38:32 2020        
(r360175)
+++ head/sys/amd64/include/vmm.h        Tue Apr 21 21:33:06 2020        
(r360176)
@@ -541,7 +541,8 @@ struct vie {
                        rm:4;
 
        uint8_t         ss:2,                   /* SIB byte */
-                       _sparebits:2,
+                       vex_present:1,          /* VEX prefixed */
+                       vex_l:1,                /* L bit */
                        index:4,                /* SIB byte */
                        base:4;                 /* SIB byte */
 
@@ -550,7 +551,11 @@ struct vie {
 
        uint8_t         scale;
 
-       uint8_t         _sparebytes[3];
+       uint8_t         vex_reg:4,              /* vvvv: first source register 
specifier */
+                       vex_pp:2,               /* pp */
+                       _sparebits:2;
+
+       uint8_t         _sparebytes[2];
 
        int             base_register;          /* VM_REG_GUEST_xyz */
        int             index_register;         /* VM_REG_GUEST_xyz */

Modified: head/sys/amd64/vmm/vmm_instruction_emul.c
==============================================================================
--- head/sys/amd64/vmm/vmm_instruction_emul.c   Tue Apr 21 19:38:32 2020        
(r360175)
+++ head/sys/amd64/vmm/vmm_instruction_emul.c   Tue Apr 21 21:33:06 2020        
(r360176)
@@ -94,10 +94,13 @@ enum {
 #define        VIE_OP_F_NO_MODRM       (1 << 3)
 #define        VIE_OP_F_NO_GLA_VERIFICATION (1 << 4)
 
+static const struct vie_op three_byte_opcodes_0f38[256] = {
+};
+
 static const struct vie_op two_byte_opcodes[256] = {
        [0xAE] = {
-                 .op_byte = 0xAE,
-                 .op_type = VIE_OP_TYPE_TWOB_GRP15,
+               .op_byte = 0xAE,
+               .op_type = VIE_OP_TYPE_TWOB_GRP15,
        },
        [0xB6] = {
                .op_byte = 0xB6,
@@ -2286,6 +2289,81 @@ decode_prefixes(struct vie *vie, enum vm_cpu_mode cpu_
        }
 
        /*
+        * ยง 2.3.5, "The VEX Prefix", SDM Vol 2.
+        */
+       if ((cpu_mode == CPU_MODE_64BIT || cpu_mode == CPU_MODE_COMPATIBILITY)
+           && x == 0xC4) {
+               const struct vie_op *optab;
+
+               /* 3-byte VEX prefix. */
+               vie->vex_present = 1;
+
+               vie_advance(vie);
+               if (vie_peek(vie, &x))
+                       return (-1);
+
+               /*
+                * 2nd byte: [R', X', B', mmmmm[4:0]].  Bits are inverted
+                * relative to REX encoding.
+                */
+               vie->rex_r = x & 0x80 ? 0 : 1;
+               vie->rex_x = x & 0x40 ? 0 : 1;
+               vie->rex_b = x & 0x20 ? 0 : 1;
+
+               switch (x & 0x1F) {
+               case 0x2:
+                       /* 0F 38. */
+                       optab = three_byte_opcodes_0f38;
+                       break;
+               case 0x1:
+                       /* 0F class - nothing handled here yet. */
+                       /* FALLTHROUGH */
+               case 0x3:
+                       /* 0F 3A class - nothing handled here yet. */
+                       /* FALLTHROUGH */
+               default:
+                       /* Reserved (#UD). */
+                       return (-1);
+               }
+
+               vie_advance(vie);
+               if (vie_peek(vie, &x))
+                       return (-1);
+
+               /* 3rd byte: [W, vvvv[6:3], L, pp[1:0]]. */
+               vie->rex_w = x & 0x80 ? 1 : 0;
+
+               vie->vex_reg = ((~(unsigned)x & 0x78u) >> 3);
+               vie->vex_l = !!(x & 0x4);
+               vie->vex_pp = (x & 0x3);
+
+               /* PP: 1=66 2=F3 3=F2 prefixes. */
+               switch (vie->vex_pp) {
+               case 0x1:
+                       vie->opsize_override = 1;
+                       break;
+               case 0x2:
+                       vie->repz_present = 1;
+                       break;
+               case 0x3:
+                       vie->repnz_present = 1;
+                       break;
+               }
+
+               vie_advance(vie);
+
+               /* Opcode, sans literal prefix prefix. */
+               if (vie_peek(vie, &x))
+                       return (-1);
+
+               vie->op = optab[x];
+               if (vie->op.op_type == VIE_OP_TYPE_NONE)
+                       return (-1);
+
+               vie_advance(vie);
+       }
+
+       /*
         * Section "Operand-Size And Address-Size Attributes", Intel SDM, Vol 1
         */
        if (cpu_mode == CPU_MODE_64BIT) {
@@ -2336,6 +2414,10 @@ decode_opcode(struct vie *vie)
 
        if (vie_peek(vie, &x))
                return (-1);
+
+       /* Already did this via VEX prefix. */
+       if (vie->op.op_type != VIE_OP_TYPE_NONE)
+               return (0);
 
        vie->op = one_byte_opcodes[x];
 
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to