summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2011-06-29 11:07:20 -0700
committerLinus Torvalds <torvalds@linux-foundation.org>2011-06-29 11:07:20 -0700
commitc017d0d1351f916c0ced3f358afc491fdcf490b4 (patch)
tree047c833e33d96e7ae500a155c1e59adbde1aaf51 /arch
parentc7735471837b35a6205f6052a34ded3bdc1db505 (diff)
parentcb16c348760ad2bc79b67b20aefac05529569ed7 (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
Diffstat (limited to 'arch')
-rw-r--r--arch/x86/kvm/emulate.c12
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;
}