aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-03-18 09:20:23 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:25 -0400
commitcf8f70bfe38b326bb80b10f76d6544f571040229 (patch)
treed646456d773a887ca592d174b3d45a57d2779d85 /arch/x86/kvm/emulate.c
parentd9271123a46011af26da680baeb7fdf67b498abf (diff)
KVM: x86 emulator: fix in/out emulation.
in/out emulation is broken now. The breakage is different depending on where IO device resides. If it is in userspace emulator reports emulation failure since it incorrectly interprets kvm_emulate_pio() return value. If IO device is in the kernel emulation of 'in' will do nothing since kvm_emulate_pio() stores result directly into vcpu registers, so emulator will overwrite result of emulation during commit of shadowed register. Signed-off-by: Gleb Natapov <gleb@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c50
1 files changed, 24 insertions, 26 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 594574d8b9e9..2d095ce9dc87 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -210,13 +210,13 @@ static u32 opcode_table[256] = {
210 0, 0, 0, 0, 0, 0, 0, 0, 210 0, 0, 0, 0, 0, 0, 0, 0,
211 /* 0xE0 - 0xE7 */ 211 /* 0xE0 - 0xE7 */
212 0, 0, 0, 0, 212 0, 0, 0, 0,
213 ByteOp | SrcImmUByte, SrcImmUByte, 213 ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc,
214 ByteOp | SrcImmUByte, SrcImmUByte, 214 ByteOp | SrcImmUByte | DstAcc, SrcImmUByte | DstAcc,
215 /* 0xE8 - 0xEF */ 215 /* 0xE8 - 0xEF */
216 SrcImm | Stack, SrcImm | ImplicitOps, 216 SrcImm | Stack, SrcImm | ImplicitOps,
217 SrcImmU | Src2Imm16 | No64, SrcImmByte | ImplicitOps, 217 SrcImmU | Src2Imm16 | No64, SrcImmByte | ImplicitOps,
218 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, 218 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
219 SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, 219 SrcNone | ByteOp | DstAcc, SrcNone | DstAcc,
220 /* 0xF0 - 0xF7 */ 220 /* 0xF0 - 0xF7 */
221 0, 0, 0, 0, 221 0, 0, 0, 0,
222 ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3, 222 ImplicitOps | Priv, ImplicitOps, Group | Group3_Byte, Group | Group3,
@@ -2426,8 +2426,6 @@ x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
2426 u64 msr_data; 2426 u64 msr_data;
2427 unsigned long saved_eip = 0; 2427 unsigned long saved_eip = 0;
2428 struct decode_cache *c = &ctxt->decode; 2428 struct decode_cache *c = &ctxt->decode;
2429 unsigned int port;
2430 int io_dir_in;
2431 int rc = X86EMUL_CONTINUE; 2429 int rc = X86EMUL_CONTINUE;
2432 2430
2433 ctxt->interruptibility = 0; 2431 ctxt->interruptibility = 0;
@@ -2823,14 +2821,10 @@ special_insn:
2823 break; 2821 break;
2824 case 0xe4: /* inb */ 2822 case 0xe4: /* inb */
2825 case 0xe5: /* in */ 2823 case 0xe5: /* in */
2826 port = c->src.val; 2824 goto do_io_in;
2827 io_dir_in = 1;
2828 goto do_io;
2829 case 0xe6: /* outb */ 2825 case 0xe6: /* outb */
2830 case 0xe7: /* out */ 2826 case 0xe7: /* out */
2831 port = c->src.val; 2827 goto do_io_out;
2832 io_dir_in = 0;
2833 goto do_io;
2834 case 0xe8: /* call (near) */ { 2828 case 0xe8: /* call (near) */ {
2835 long int rel = c->src.val; 2829 long int rel = c->src.val;
2836 c->src.val = (unsigned long) c->eip; 2830 c->src.val = (unsigned long) c->eip;
@@ -2855,25 +2849,29 @@ special_insn:
2855 break; 2849 break;
2856 case 0xec: /* in al,dx */ 2850 case 0xec: /* in al,dx */
2857 case 0xed: /* in (e/r)ax,dx */ 2851 case 0xed: /* in (e/r)ax,dx */
2858 port = c->regs[VCPU_REGS_RDX]; 2852 c->src.val = c->regs[VCPU_REGS_RDX];
2859 io_dir_in = 1; 2853 do_io_in:
2860 goto do_io; 2854 c->dst.bytes = min(c->dst.bytes, 4u);
2855 if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) {
2856 kvm_inject_gp(ctxt->vcpu, 0);
2857 goto done;
2858 }
2859 if (!ops->pio_in_emulated(c->dst.bytes, c->src.val,
2860 &c->dst.val, 1, ctxt->vcpu))
2861 goto done; /* IO is needed */
2862 break;
2861 case 0xee: /* out al,dx */ 2863 case 0xee: /* out al,dx */
2862 case 0xef: /* out (e/r)ax,dx */ 2864 case 0xef: /* out (e/r)ax,dx */
2863 port = c->regs[VCPU_REGS_RDX]; 2865 c->src.val = c->regs[VCPU_REGS_RDX];
2864 io_dir_in = 0; 2866 do_io_out:
2865 do_io: 2867 c->dst.bytes = min(c->dst.bytes, 4u);
2866 if (!emulator_io_permited(ctxt, ops, port, 2868 if (!emulator_io_permited(ctxt, ops, c->src.val, c->dst.bytes)) {
2867 (c->d & ByteOp) ? 1 : c->op_bytes)) {
2868 kvm_inject_gp(ctxt->vcpu, 0); 2869 kvm_inject_gp(ctxt->vcpu, 0);
2869 goto done; 2870 goto done;
2870 } 2871 }
2871 if (kvm_emulate_pio(ctxt->vcpu, io_dir_in, 2872 ops->pio_out_emulated(c->dst.bytes, c->src.val, &c->dst.val, 1,
2872 (c->d & ByteOp) ? 1 : c->op_bytes, 2873 ctxt->vcpu);
2873 port) != 0) { 2874 c->dst.type = OP_NONE; /* Disable writeback. */
2874 c->eip = saved_eip;
2875 goto cannot_emulate;
2876 }
2877 break; 2875 break;
2878 case 0xf4: /* hlt */ 2876 case 0xf4: /* hlt */
2879 ctxt->vcpu->arch.halt_request = 1; 2877 ctxt->vcpu->arch.halt_request = 1;