diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-29 14:07:20 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-06-29 14:07:20 -0400 |
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 6df88c7885c0..adc98675cda0 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) | |||
3372 | int def_op_bytes, def_ad_bytes, goffset, simd_prefix; | 3372 | int def_op_bytes, def_ad_bytes, goffset, simd_prefix; |
3373 | bool op_prefix = false; | 3373 | bool op_prefix = false; |
3374 | struct opcode opcode; | 3374 | struct opcode opcode; |
3375 | struct operand memop = { .type = OP_NONE }; | 3375 | struct operand memop = { .type = OP_NONE }, *memopp = NULL; |
3376 | 3376 | ||
3377 | c->eip = ctxt->eip; | 3377 | c->eip = ctxt->eip; |
3378 | c->fetch.start = c->eip; | 3378 | c->fetch.start = c->eip; |
@@ -3547,9 +3547,6 @@ done_prefixes: | |||
3547 | if (memop.type == OP_MEM && c->ad_bytes != 8) | 3547 | if (memop.type == OP_MEM && c->ad_bytes != 8) |
3548 | memop.addr.mem.ea = (u32)memop.addr.mem.ea; | 3548 | memop.addr.mem.ea = (u32)memop.addr.mem.ea; |
3549 | 3549 | ||
3550 | if (memop.type == OP_MEM && c->rip_relative) | ||
3551 | memop.addr.mem.ea += c->eip; | ||
3552 | |||
3553 | /* | 3550 | /* |
3554 | * Decode and fetch the source operand: register, memory | 3551 | * Decode and fetch the source operand: register, memory |
3555 | * or immediate. | 3552 | * or immediate. |
@@ -3571,6 +3568,7 @@ done_prefixes: | |||
3571 | c->op_bytes; | 3568 | c->op_bytes; |
3572 | srcmem_common: | 3569 | srcmem_common: |
3573 | c->src = memop; | 3570 | c->src = memop; |
3571 | memopp = &c->src; | ||
3574 | break; | 3572 | break; |
3575 | case SrcImmU16: | 3573 | case SrcImmU16: |
3576 | rc = decode_imm(ctxt, &c->src, 2, false); | 3574 | rc = decode_imm(ctxt, &c->src, 2, false); |
@@ -3667,6 +3665,7 @@ done_prefixes: | |||
3667 | case DstMem: | 3665 | case DstMem: |
3668 | case DstMem64: | 3666 | case DstMem64: |
3669 | c->dst = memop; | 3667 | c->dst = memop; |
3668 | memopp = &c->dst; | ||
3670 | if ((c->d & DstMask) == DstMem64) | 3669 | if ((c->d & DstMask) == DstMem64) |
3671 | c->dst.bytes = 8; | 3670 | c->dst.bytes = 8; |
3672 | else | 3671 | else |
@@ -3700,10 +3699,13 @@ done_prefixes: | |||
3700 | /* Special instructions do their own operand decoding. */ | 3699 | /* Special instructions do their own operand decoding. */ |
3701 | default: | 3700 | default: |
3702 | c->dst.type = OP_NONE; /* Disable writeback. */ | 3701 | c->dst.type = OP_NONE; /* Disable writeback. */ |
3703 | return 0; | 3702 | break; |
3704 | } | 3703 | } |
3705 | 3704 | ||
3706 | done: | 3705 | done: |
3706 | if (memopp && memopp->type == OP_MEM && c->rip_relative) | ||
3707 | memopp->addr.mem.ea += c->eip; | ||
3708 | |||
3707 | return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; | 3709 | return (rc == X86EMUL_UNHANDLEABLE) ? EMULATION_FAILED : EMULATION_OK; |
3708 | } | 3710 | } |
3709 | 3711 | ||