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: 771daacd19 ("x86emul: support BMI1 insns")
Signed-off-by: Jan Beulich <jbeulich@suse.com>
Reviewed-by: Andrew Cooper <andrew.cooper3@citrix.com>
This commit is contained in:
Jan Beulich committed 2024-11-14 13:00:57 +01:00
1 parent 5b8780869e
commit 1179d51dcb
2 files changed
+28

No files matched your search

@@ -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
+4
View File
@@ -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) */
Reference in new issue
Block a user
Blocking a user prevents them from interacting with repositories, such as opening or commenting on pull requests or issues. Learn more about blocking a user.