x86emul: VEX.B is ignored in compatibility mode
authorJan Beulich <jbeulich@suse.com>
Tue, 17 Jan 2017 09:32:25 +0000 (10:32 +0100)
committerJan Beulich <jbeulich@suse.com>
Tue, 17 Jan 2017 09:32:25 +0000 (10:32 +0100)
While VEX.R and VEX.X are guaranteed to be 1 in compatibility mode
(and hence a respective mode_64bit() check can be dropped), VEX.B can
be encoded as zero, but would be ignored by the processor. Since we
emulate instructions in 64-bit mode (except possibly in the test
harness), we need to force the bit to 1 in order to not act on the
wrong {X,Y,Z}MM register (which has no bad effect on 32-bit test
harness builds, as there the bit would again be ignored by the
hardware, and would by default be expected to be 1 anyway).

We must not, however, fiddle with the high bit of VEX.VVVV in the
decode phase, as that would undermine the checking of instructions
requiring the field to be all ones independent of mode. This is
being enforced in copy_REX_VEX() instead.

Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
xen/arch/x86/x86_emulate/x86_emulate.c

index de239b6f2185f0774806cda64215172d84f09c51..20285b2206a8e85bbfecbd0c57e385aa6df0e87d 100644 (file)
@@ -332,7 +332,11 @@ union vex {
 
 #define copy_REX_VEX(ptr, rex, vex) do { \
     if ( (vex).opcx != vex_none ) \
+    { \
+        if ( !mode_64bit() ) \
+            vex.reg |= 8; \
         ptr[0] = 0xc4, ptr[1] = (vex).raw[0], ptr[2] = (vex).raw[1]; \
+    } \
     else if ( mode_64bit() ) \
         ptr[1] = rex | REX_PREFIX; \
 } while (0)
@@ -2309,6 +2313,8 @@ x86_decode(
                             op_bytes = 8;
                         }
                     }
+                    else
+                        vex.b = 1;
                     switch ( b )
                     {
                     case 0x62:
@@ -2327,7 +2333,7 @@ x86_decode(
                         break;
                     }
                 }
-                if ( mode_64bit() && !vex.r )
+                if ( !vex.r )
                     rex_prefix |= REX_R;
 
                 ext = vex.opcx;