diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:24 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:26 -0400 |
commit | 7972995b0c346de76fe260ce0fd6bcc8ffab724a (patch) | |
tree | a2522988d8cd465b836c0a32399d8eeb7a3ed545 /arch/x86/kvm/emulate.c | |
parent | cf8f70bfe38b326bb80b10f76d6544f571040229 (diff) |
KVM: x86 emulator: Move string pio emulation into emulator.c
Currently emulation is done outside of emulator so things like doing
ins/outs to/from mmio are broken it also makes it hard (if not impossible)
to implement single stepping in the future. The implementation in this
patch is not efficient since it exits to userspace for each IO while
previous implementation did 'ins' in batches. Further patch that
implements pio in string read ahead address this problem.
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.c | 48 |
1 files changed, 15 insertions, 33 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 2d095ce9dc87..2c66e097d916 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -153,8 +153,8 @@ static u32 opcode_table[256] = { | |||
153 | 0, 0, 0, 0, | 153 | 0, 0, 0, 0, |
154 | /* 0x68 - 0x6F */ | 154 | /* 0x68 - 0x6F */ |
155 | SrcImm | Mov | Stack, 0, SrcImmByte | Mov | Stack, 0, | 155 | SrcImm | Mov | Stack, 0, SrcImmByte | Mov | Stack, 0, |
156 | SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* insb, insw/insd */ | 156 | DstDI | ByteOp | Mov | String, DstDI | Mov | String, /* insb, insw/insd */ |
157 | SrcNone | ByteOp | ImplicitOps, SrcNone | ImplicitOps, /* outsb, outsw/outsd */ | 157 | SrcSI | ByteOp | ImplicitOps | String, SrcSI | ImplicitOps | String, /* outsb, outsw/outsd */ |
158 | /* 0x70 - 0x77 */ | 158 | /* 0x70 - 0x77 */ |
159 | SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, | 159 | SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, |
160 | SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, | 160 | SrcImmByte, SrcImmByte, SrcImmByte, SrcImmByte, |
@@ -2615,47 +2615,29 @@ special_insn: | |||
2615 | break; | 2615 | break; |
2616 | case 0x6c: /* insb */ | 2616 | case 0x6c: /* insb */ |
2617 | case 0x6d: /* insw/insd */ | 2617 | case 0x6d: /* insw/insd */ |
2618 | c->dst.bytes = min(c->dst.bytes, 4u); | ||
2618 | if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], | 2619 | if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], |
2619 | (c->d & ByteOp) ? 1 : c->op_bytes)) { | 2620 | c->dst.bytes)) { |
2620 | kvm_inject_gp(ctxt->vcpu, 0); | 2621 | kvm_inject_gp(ctxt->vcpu, 0); |
2621 | goto done; | 2622 | goto done; |
2622 | } | 2623 | } |
2623 | if (kvm_emulate_pio_string(ctxt->vcpu, | 2624 | if (!ops->pio_in_emulated(c->dst.bytes, c->regs[VCPU_REGS_RDX], |
2624 | 1, | 2625 | &c->dst.val, 1, ctxt->vcpu)) |
2625 | (c->d & ByteOp) ? 1 : c->op_bytes, | 2626 | goto done; /* IO is needed, skip writeback */ |
2626 | c->rep_prefix ? | 2627 | break; |
2627 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, | ||
2628 | (ctxt->eflags & EFLG_DF), | ||
2629 | register_address(c, es_base(ctxt), | ||
2630 | c->regs[VCPU_REGS_RDI]), | ||
2631 | c->rep_prefix, | ||
2632 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
2633 | c->eip = saved_eip; | ||
2634 | return -1; | ||
2635 | } | ||
2636 | return 0; | ||
2637 | case 0x6e: /* outsb */ | 2628 | case 0x6e: /* outsb */ |
2638 | case 0x6f: /* outsw/outsd */ | 2629 | case 0x6f: /* outsw/outsd */ |
2630 | c->src.bytes = min(c->src.bytes, 4u); | ||
2639 | if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], | 2631 | if (!emulator_io_permited(ctxt, ops, c->regs[VCPU_REGS_RDX], |
2640 | (c->d & ByteOp) ? 1 : c->op_bytes)) { | 2632 | c->src.bytes)) { |
2641 | kvm_inject_gp(ctxt->vcpu, 0); | 2633 | kvm_inject_gp(ctxt->vcpu, 0); |
2642 | goto done; | 2634 | goto done; |
2643 | } | 2635 | } |
2644 | if (kvm_emulate_pio_string(ctxt->vcpu, | 2636 | ops->pio_out_emulated(c->src.bytes, c->regs[VCPU_REGS_RDX], |
2645 | 0, | 2637 | &c->src.val, 1, ctxt->vcpu); |
2646 | (c->d & ByteOp) ? 1 : c->op_bytes, | 2638 | |
2647 | c->rep_prefix ? | 2639 | c->dst.type = OP_NONE; /* nothing to writeback */ |
2648 | address_mask(c, c->regs[VCPU_REGS_RCX]) : 1, | 2640 | break; |
2649 | (ctxt->eflags & EFLG_DF), | ||
2650 | register_address(c, | ||
2651 | seg_override_base(ctxt, c), | ||
2652 | c->regs[VCPU_REGS_RSI]), | ||
2653 | c->rep_prefix, | ||
2654 | c->regs[VCPU_REGS_RDX]) == 0) { | ||
2655 | c->eip = saved_eip; | ||
2656 | return -1; | ||
2657 | } | ||
2658 | return 0; | ||
2659 | case 0x70 ... 0x7f: /* jcc (short) */ | 2641 | case 0x70 ... 0x7f: /* jcc (short) */ |
2660 | if (test_cc(c->b, ctxt->eflags)) | 2642 | if (test_cc(c->b, ctxt->eflags)) |
2661 | jmp_rel(c, c->src.val); | 2643 | jmp_rel(c, c->src.val); |