KVM: x86: BSF and BSR emulation change register unnecassarily

If the source of BSF and BSR is zero, the destination register should not
change. That is how real hardware behaves.  If we set the destination even with
the same value that we had before, we may clear bits [63:32] unnecassarily.

Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Message-Id: <1427719163-5429-4-git-send-email-namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
Nadav Amit 2015-03-30 15:39:21 +03:00 committed by Paolo Bonzini
parent 6fd8e12757
commit 900efe200e

View File

@ -962,6 +962,22 @@ FASTOP2(xadd);
FASTOP2R(cmp, cmp_r); FASTOP2R(cmp, cmp_r);
static int em_bsf_c(struct x86_emulate_ctxt *ctxt)
{
/* If src is zero, do not writeback, but update flags */
if (ctxt->src.val == 0)
ctxt->dst.type = OP_NONE;
return fastop(ctxt, em_bsf);
}
static int em_bsr_c(struct x86_emulate_ctxt *ctxt)
{
/* If src is zero, do not writeback, but update flags */
if (ctxt->src.val == 0)
ctxt->dst.type = OP_NONE;
return fastop(ctxt, em_bsr);
}
static u8 test_cc(unsigned int condition, unsigned long flags) static u8 test_cc(unsigned int condition, unsigned long flags)
{ {
u8 rc; u8 rc;
@ -4188,7 +4204,8 @@ static const struct opcode twobyte_table[256] = {
N, N, N, N,
G(BitOp, group8), G(BitOp, group8),
F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc), F(DstMem | SrcReg | ModRM | BitOp | Lock | PageTable, em_btc),
F(DstReg | SrcMem | ModRM, em_bsf), F(DstReg | SrcMem | ModRM, em_bsr), I(DstReg | SrcMem | ModRM, em_bsf_c),
I(DstReg | SrcMem | ModRM, em_bsr_c),
D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), D(DstReg | SrcMem8 | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
/* 0xC0 - 0xC7 */ /* 0xC0 - 0xC7 */
F2bv(DstMem | SrcReg | ModRM | SrcWrite | Lock, em_xadd), F2bv(DstMem | SrcReg | ModRM | SrcWrite | Lock, em_xadd),