[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[xen master] x86emul: ignore VEX.W for BMI{1,2} insns in 32-bit mode



commit 1179d51dcb7d93111bfb35172c75eb5a73fe6a43
Author:     Jan Beulich <jbeulich@xxxxxxxx>
AuthorDate: Thu Nov 14 13:00:57 2024 +0100
Commit:     Jan Beulich <jbeulich@xxxxxxxx>
CommitDate: Thu Nov 14 13:00:57 2024 +0100

    x86emul: ignore VEX.W for BMI{1,2} insns in 32-bit mode
    
    While result values and other status flags are unaffected as long as we
    can ignore the case of registers having their upper 32 bits non-zero
    outside of 64-bit mode, EFLAGS.SF may obtain a wrong value when we
    mistakenly re-execute the original insn with VEX.W set.
    
    Note that guest the memory access, if any, is correctly carried out as
    32-bit regardless of VEX.W. The emulator-local memory operand will be
    accessed as a 64-bit quantity, but it is pre-initialised to zero so no
    internal state can leak.
    
    Fixes: 771daacd197a ("x86emul: support BMI1 insns")
    Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx>
    Reviewed-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
 tools/tests/x86_emulator/test_x86_emulator.c | 24 ++++++++++++++++++++++++
 xen/arch/x86/x86_emulate/x86_emulate.c       |  4 ++++
 2 files changed, 28 insertions(+)

diff --git a/tools/tests/x86_emulator/test_x86_emulator.c 
b/tools/tests/x86_emulator/test_x86_emulator.c
index 66bb184ccd..39e8056d77 100644
--- a/tools/tests/x86_emulator/test_x86_emulator.c
+++ b/tools/tests/x86_emulator/test_x86_emulator.c
@@ -2021,6 +2021,30 @@ int main(int argc, char **argv)
               (EFLAGS_ALWAYS_SET | X86_EFLAGS_SF) ||
              !check_eip(blsr) )
             goto fail;
+
+#ifdef __x86_64__
+        /* Re-test with VEX.W set while emulating 32-bit mode. */
+        ctxt.lma       = 0;
+        ctxt.addr_size = 32;
+        ctxt.sp_size   = 32;
+
+        memcpy(instr, blsr, blsr_end - blsr);
+        instr[2] |= 0x80;
+        regs.rip = (unsigned long)&instr[0];
+        regs.eflags = EFLAGS_ALWAYS_SET | X86_EFLAGS_OF | X86_EFLAGS_ZF | \
+                      X86_EFLAGS_CF;
+        rc = x86_emulate(&ctxt, &emulops);
+        if ( (rc != X86EMUL_OKAY) || regs.ecx != 0xfedcba90 ||
+             (regs.eflags & (EFLAGS_MASK & ~(X86_EFLAGS_AF | X86_EFLAGS_PF))) 
!=
+              (EFLAGS_ALWAYS_SET | X86_EFLAGS_SF) ||
+             (regs.rip != (unsigned long)&instr[blsr_end - blsr]) )
+            goto fail;
+
+        ctxt.lma       = 1;
+        ctxt.addr_size = 64;
+        ctxt.sp_size   = 64;
+#endif
+
         printf("okay\n");
     }
     else
diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c 
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 30674ec301..ecfb62b003 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -6896,6 +6896,8 @@ x86_emulate(
         *pvex = vex;
         pvex->b = 1;
         pvex->r = 1;
+        if ( !mode_64bit() )
+            pvex->w = 0;
         pvex->reg = 0xf; /* rAX */
         buf[3] = b;
         buf[4] = 0x09; /* reg=rCX r/m=(%rCX) */
@@ -6930,6 +6932,8 @@ x86_emulate(
         *pvex = vex;
         pvex->b = 1;
         pvex->r = 1;
+        if ( !mode_64bit() )
+            pvex->w = 0;
         pvex->reg = 0xf; /* rAX */
         buf[3] = b;
         buf[4] = (modrm & 0x38) | 0x01; /* r/m=(%rCX) */
--
generated by git-patchbot for /home/xen/git/xen.git#master



 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.