2
0
mirror of https://github.com/edk2-porting/linux-next.git synced 2024-12-26 22:24:09 +08:00

KVM: x86 emulator: fix negative bit offset BitOp instruction emulation

If bit offset operands is a negative number, BitOp instruction
will return wrong value. This patch fix it.

Signed-off-by: Wei Yongjun <yjwei@cn.fujitsu.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Signed-off-by: Avi Kivity <avi@redhat.com>
This commit is contained in:
Wei Yongjun 2010-08-09 11:34:56 +08:00 committed by Avi Kivity
parent 8744aa9aad
commit 35c843c485

View File

@ -723,6 +723,22 @@ done:
return rc; return rc;
} }
static void fetch_bit_operand(struct decode_cache *c)
{
long sv, mask;
if (c->dst.type == OP_MEM) {
mask = ~(c->dst.bytes * 8 - 1);
if (c->src.bytes == 2)
sv = (s16)c->src.val & (s16)mask;
else if (c->src.bytes == 4)
sv = (s32)c->src.val & (s32)mask;
c->dst.addr.mem += (sv >> 3);
}
}
static int read_emulated(struct x86_emulate_ctxt *ctxt, static int read_emulated(struct x86_emulate_ctxt *ctxt,
struct x86_emulate_ops *ops, struct x86_emulate_ops *ops,
unsigned long addr, void *dest, unsigned size) unsigned long addr, void *dest, unsigned size)
@ -2638,12 +2654,8 @@ done_prefixes:
c->dst.bytes = 8; c->dst.bytes = 8;
else else
c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes; c->dst.bytes = (c->d & ByteOp) ? 1 : c->op_bytes;
if (c->dst.type == OP_MEM && (c->d & BitOp)) { if (c->d & BitOp)
unsigned long mask = ~(c->dst.bytes * 8 - 1); fetch_bit_operand(c);
c->dst.addr.mem = c->dst.addr.mem +
(c->src.val & mask) / 8;
}
c->dst.orig_val = c->dst.val; c->dst.orig_val = c->dst.val;
break; break;
case DstAcc: case DstAcc: