Commit cb16c348 authored by Avi Kivity's avatar Avi Kivity

KVM: x86 emulator: fix %rip-relative addressing with immediate source operand

%rip-relative addressing is relative to the first byte of the next instruction,
so we need to add %rip only after we've fetched any immediate bytes.

Based on original patch by Li Xin <xin.li@intel.com>.
Signed-off-by: default avatarAvi Kivity <avi@redhat.com>
Acked-by: default avatarLi Xin <xin.li@intel.com>
Signed-off-by: default avatarMarcelo Tosatti <mtosatti@redhat.com>
parent b0af8dfd
...@@ -3372,7 +3372,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -3372,7 +3372,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
int def_op_bytes, def_ad_bytes, goffset, simd_prefix; int def_op_bytes, def_ad_bytes, goffset, simd_prefix;
bool op_prefix = false; bool op_prefix = false;
struct opcode opcode; struct opcode opcode;
struct operand memop = { .type = OP_NONE }; struct operand memop = { .type = OP_NONE }, *memopp = NULL;
c->eip = ctxt->eip; c->eip = ctxt->eip;
c->fetch.start = c->eip; c->fetch.start = c->eip;
...@@ -3547,9 +3547,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -3547,9 +3547,6 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
if (memop.type == OP_MEM && c->ad_bytes != 8) if (memop.type == OP_MEM && c->ad_bytes != 8)
memop.addr.mem.ea = (u32)memop.addr.mem.ea; memop.addr.mem.ea = (u32)memop.addr.mem.ea;
if (memop.type == OP_MEM && c->rip_relative)
memop.addr.mem.ea += c->eip;
/* /*
* Decode and fetch the source operand: register, memory * Decode and fetch the source operand: register, memory
* or immediate. * or immediate.
...@@ -3571,6 +3568,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -3571,6 +3568,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
c->op_bytes; c->op_bytes;
srcmem_common: srcmem_common:
c->src = memop; c->src = memop;
memopp = &c->src;
break; break;
case SrcImmU16: case SrcImmU16:
rc = decode_imm(ctxt, &c->src, 2, false); rc = decode_imm(ctxt, &c->src, 2, false);
...@@ -3667,6 +3665,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -3667,6 +3665,7 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
case DstMem: case DstMem:
case DstMem64: case DstMem64:
c->dst = memop; c->dst = memop;
memopp = &c->dst;
if ((c->d & DstMask) == DstMem64) if ((c->d & DstMask) == DstMem64)
c->dst.bytes = 8; c->dst.bytes = 8;
else else
...@@ -3700,10 +3699,13 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -3700,10 +3699,13 @@ x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
/* Special instructions do their own operand decoding. */ /* Special instructions do their own operand decoding. */
default: default:
c->dst.type = OP_NONE; /* Disable writeback. */ c->dst.type = OP_NONE; /* Disable writeback. */
return 0; break;
} }
done: done:
if (memopp && memopp->type == OP_MEM && c->rip_relative)
memopp->addr.mem.ea += c->eip;
return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK;
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment