[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [PATCH 2/2] 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 the memory access, if any, is correctly carried out as 32-bit regardless of VEX.W. Internal state also isn't leaked, as the field the memory value is read into (which is then wrongly accessed as a 64-bit quantity when executing the stub) is pre-initialized to zero. Fixes: 771daacd197a ("x86emul: support BMI1 insns") Signed-off-by: Jan Beulich <jbeulich@xxxxxxxx> --- 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 --- 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) */
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |