diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-29 11:07:20 -0700 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-29 11:07:20 -0700 |
commit | c017d0d1351f916c0ced3f358afc491fdcf490b4 (patch) | |
tree | 047c833e33d96e7ae500a155c1e59adbde1aaf51 | |
parent | c7735471837b35a6205f6052a34ded3bdc1db505 (diff) | |
parent | cb16c348760ad2bc79b67b20aefac05529569ed7 (diff) |
Merge branch 'kvm-updates/3.0' of git://git.kernel.org/pub/scm/virt/kvm/kvm
* 'kvm-updates/3.0' of git://git.kernel.org/pub/scm/virt/kvm/kvm:
KVM: x86 emulator: fix %rip-relative addressing with immediate source operand
-rw-r--r-- | arch/x86/kvm/emulate.c | 12 |
1 files changed, 7 insertions, 5 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 6df88c7885c..adc98675cda 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c @@ -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; bool op_prefix = false; struct opcode opcode; - struct operand memop = { .type = OP_NONE }; + struct operand memop = { .type = OP_NONE }, *memopp = NULL; c->eip = ctxt->eip; c->fetch.start = c->eip; @@ -3547,9 +3547,6 @@ done_prefixes: if (memop.type == OP_MEM && c->ad_bytes != 8) 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 * or immediate. @@ -3571,6 +3568,7 @@ done_prefixes: c->op_bytes; srcmem_common: c->src = memop; + memopp = &c->src; break; case SrcImmU16: rc = decode_imm(ctxt, &c->src, 2, false); @@ -3667,6 +3665,7 @@ done_prefixes: case DstMem: case DstMem64: c->dst = memop; + memopp = &c->dst; if ((c->d & DstMask) == DstMem64) c->dst.bytes = 8; else @@ -3700,10 +3699,13 @@ done_prefixes: /* Special instructions do their own operand decoding. */ default: c->dst.type = OP_NONE; /* Disable writeback. */ - return 0; + break; } done: + if (memopp && memopp->type == OP_MEM && c->rip_relative) + memopp->addr.mem.ea += c->eip; + return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; } |