diff options
author | Gleb Natapov <gleb@redhat.com> | 2010-03-18 09:20:23 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2010-05-17 05:16:25 -0400 |
commit | cf8f70bfe38b326bb80b10f76d6544f571040229 (patch) | |
tree | d646456d773a887ca592d174b3d45a57d2779d85 /arch/x86/kvm | |
parent | d9271123a46011af26da680baeb7fdf67b498abf (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')
-rw-r--r-- | arch/x86/kvm/emulate.c | 50 | ||||
-rw-r--r-- | arch/x86/kvm/svm.c | 20 | ||||
-rw-r--r-- | arch/x86/kvm/vmx.c | 18 | ||||
-rw-r--r-- | arch/x86/kvm/x86.c | 213 |
4 files changed, 170 insertions, 131 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; |
diff --git a/arch/x86/kvm/svm.c b/arch/x86/kvm/svm.c index abbc3f9d03b2..e9f79619e185 100644 --- a/arch/x86/kvm/svm.c +++ b/arch/x86/kvm/svm.c | |||
@@ -1494,29 +1494,23 @@ static int shutdown_interception(struct vcpu_svm *svm) | |||
1494 | 1494 | ||
1495 | static int io_interception(struct vcpu_svm *svm) | 1495 | static int io_interception(struct vcpu_svm *svm) |
1496 | { | 1496 | { |
1497 | struct kvm_vcpu *vcpu = &svm->vcpu; | ||
1497 | u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */ | 1498 | u32 io_info = svm->vmcb->control.exit_info_1; /* address size bug? */ |
1498 | int size, in, string; | 1499 | int size, in, string; |
1499 | unsigned port; | 1500 | unsigned port; |
1500 | 1501 | ||
1501 | ++svm->vcpu.stat.io_exits; | 1502 | ++svm->vcpu.stat.io_exits; |
1502 | |||
1503 | svm->next_rip = svm->vmcb->control.exit_info_2; | ||
1504 | |||
1505 | string = (io_info & SVM_IOIO_STR_MASK) != 0; | 1503 | string = (io_info & SVM_IOIO_STR_MASK) != 0; |
1506 | |||
1507 | if (string) { | ||
1508 | if (emulate_instruction(&svm->vcpu, | ||
1509 | 0, 0, 0) == EMULATE_DO_MMIO) | ||
1510 | return 0; | ||
1511 | return 1; | ||
1512 | } | ||
1513 | |||
1514 | in = (io_info & SVM_IOIO_TYPE_MASK) != 0; | 1504 | in = (io_info & SVM_IOIO_TYPE_MASK) != 0; |
1505 | if (string || in) | ||
1506 | return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO); | ||
1507 | |||
1515 | port = io_info >> 16; | 1508 | port = io_info >> 16; |
1516 | size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; | 1509 | size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; |
1517 | 1510 | svm->next_rip = svm->vmcb->control.exit_info_2; | |
1518 | skip_emulated_instruction(&svm->vcpu); | 1511 | skip_emulated_instruction(&svm->vcpu); |
1519 | return kvm_emulate_pio(&svm->vcpu, in, size, port); | 1512 | |
1513 | return kvm_fast_pio_out(vcpu, size, port); | ||
1520 | } | 1514 | } |
1521 | 1515 | ||
1522 | static int nmi_interception(struct vcpu_svm *svm) | 1516 | static int nmi_interception(struct vcpu_svm *svm) |
diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 87b3c6843aac..1cceca1c59be 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c | |||
@@ -2985,22 +2985,20 @@ static int handle_io(struct kvm_vcpu *vcpu) | |||
2985 | int size, in, string; | 2985 | int size, in, string; |
2986 | unsigned port; | 2986 | unsigned port; |
2987 | 2987 | ||
2988 | ++vcpu->stat.io_exits; | ||
2989 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); | 2988 | exit_qualification = vmcs_readl(EXIT_QUALIFICATION); |
2990 | string = (exit_qualification & 16) != 0; | 2989 | string = (exit_qualification & 16) != 0; |
2990 | in = (exit_qualification & 8) != 0; | ||
2991 | 2991 | ||
2992 | if (string) { | 2992 | ++vcpu->stat.io_exits; |
2993 | if (emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO) | ||
2994 | return 0; | ||
2995 | return 1; | ||
2996 | } | ||
2997 | 2993 | ||
2998 | size = (exit_qualification & 7) + 1; | 2994 | if (string || in) |
2999 | in = (exit_qualification & 8) != 0; | 2995 | return !(emulate_instruction(vcpu, 0, 0, 0) == EMULATE_DO_MMIO); |
3000 | port = exit_qualification >> 16; | ||
3001 | 2996 | ||
2997 | port = exit_qualification >> 16; | ||
2998 | size = (exit_qualification & 7) + 1; | ||
3002 | skip_emulated_instruction(vcpu); | 2999 | skip_emulated_instruction(vcpu); |
3003 | return kvm_emulate_pio(vcpu, in, size, port); | 3000 | |
3001 | return kvm_fast_pio_out(vcpu, size, port); | ||
3004 | } | 3002 | } |
3005 | 3003 | ||
3006 | static void | 3004 | static void |
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f69854c8f339..6624ad13ee99 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c | |||
@@ -3404,6 +3404,86 @@ emul_write: | |||
3404 | return emulator_write_emulated(addr, new, bytes, vcpu); | 3404 | return emulator_write_emulated(addr, new, bytes, vcpu); |
3405 | } | 3405 | } |
3406 | 3406 | ||
3407 | static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | ||
3408 | { | ||
3409 | /* TODO: String I/O for in kernel device */ | ||
3410 | int r; | ||
3411 | |||
3412 | if (vcpu->arch.pio.in) | ||
3413 | r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port, | ||
3414 | vcpu->arch.pio.size, pd); | ||
3415 | else | ||
3416 | r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, | ||
3417 | vcpu->arch.pio.port, vcpu->arch.pio.size, | ||
3418 | pd); | ||
3419 | return r; | ||
3420 | } | ||
3421 | |||
3422 | |||
3423 | static int emulator_pio_in_emulated(int size, unsigned short port, void *val, | ||
3424 | unsigned int count, struct kvm_vcpu *vcpu) | ||
3425 | { | ||
3426 | if (vcpu->arch.pio.cur_count) | ||
3427 | goto data_avail; | ||
3428 | |||
3429 | trace_kvm_pio(1, port, size, 1); | ||
3430 | |||
3431 | vcpu->arch.pio.port = port; | ||
3432 | vcpu->arch.pio.in = 1; | ||
3433 | vcpu->arch.pio.string = 0; | ||
3434 | vcpu->arch.pio.down = 0; | ||
3435 | vcpu->arch.pio.rep = 0; | ||
3436 | vcpu->arch.pio.count = vcpu->arch.pio.cur_count = count; | ||
3437 | vcpu->arch.pio.size = size; | ||
3438 | |||
3439 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { | ||
3440 | data_avail: | ||
3441 | memcpy(val, vcpu->arch.pio_data, size * count); | ||
3442 | vcpu->arch.pio.cur_count = 0; | ||
3443 | return 1; | ||
3444 | } | ||
3445 | |||
3446 | vcpu->run->exit_reason = KVM_EXIT_IO; | ||
3447 | vcpu->run->io.direction = KVM_EXIT_IO_IN; | ||
3448 | vcpu->run->io.size = size; | ||
3449 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | ||
3450 | vcpu->run->io.count = count; | ||
3451 | vcpu->run->io.port = port; | ||
3452 | |||
3453 | return 0; | ||
3454 | } | ||
3455 | |||
3456 | static int emulator_pio_out_emulated(int size, unsigned short port, | ||
3457 | const void *val, unsigned int count, | ||
3458 | struct kvm_vcpu *vcpu) | ||
3459 | { | ||
3460 | trace_kvm_pio(0, port, size, 1); | ||
3461 | |||
3462 | vcpu->arch.pio.port = port; | ||
3463 | vcpu->arch.pio.in = 0; | ||
3464 | vcpu->arch.pio.string = 0; | ||
3465 | vcpu->arch.pio.down = 0; | ||
3466 | vcpu->arch.pio.rep = 0; | ||
3467 | vcpu->arch.pio.count = vcpu->arch.pio.cur_count = count; | ||
3468 | vcpu->arch.pio.size = size; | ||
3469 | |||
3470 | memcpy(vcpu->arch.pio_data, val, size * count); | ||
3471 | |||
3472 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { | ||
3473 | vcpu->arch.pio.cur_count = 0; | ||
3474 | return 1; | ||
3475 | } | ||
3476 | |||
3477 | vcpu->run->exit_reason = KVM_EXIT_IO; | ||
3478 | vcpu->run->io.direction = KVM_EXIT_IO_OUT; | ||
3479 | vcpu->run->io.size = size; | ||
3480 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | ||
3481 | vcpu->run->io.count = count; | ||
3482 | vcpu->run->io.port = port; | ||
3483 | |||
3484 | return 0; | ||
3485 | } | ||
3486 | |||
3407 | static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) | 3487 | static unsigned long get_segment_base(struct kvm_vcpu *vcpu, int seg) |
3408 | { | 3488 | { |
3409 | return kvm_x86_ops->get_segment_base(vcpu, seg); | 3489 | return kvm_x86_ops->get_segment_base(vcpu, seg); |
@@ -3597,6 +3677,8 @@ static struct x86_emulate_ops emulate_ops = { | |||
3597 | .read_emulated = emulator_read_emulated, | 3677 | .read_emulated = emulator_read_emulated, |
3598 | .write_emulated = emulator_write_emulated, | 3678 | .write_emulated = emulator_write_emulated, |
3599 | .cmpxchg_emulated = emulator_cmpxchg_emulated, | 3679 | .cmpxchg_emulated = emulator_cmpxchg_emulated, |
3680 | .pio_in_emulated = emulator_pio_in_emulated, | ||
3681 | .pio_out_emulated = emulator_pio_out_emulated, | ||
3600 | .get_cached_descriptor = emulator_get_cached_descriptor, | 3682 | .get_cached_descriptor = emulator_get_cached_descriptor, |
3601 | .set_cached_descriptor = emulator_set_cached_descriptor, | 3683 | .set_cached_descriptor = emulator_set_cached_descriptor, |
3602 | .get_segment_selector = emulator_get_segment_selector, | 3684 | .get_segment_selector = emulator_get_segment_selector, |
@@ -3704,6 +3786,12 @@ int emulate_instruction(struct kvm_vcpu *vcpu, | |||
3704 | if (vcpu->arch.pio.string) | 3786 | if (vcpu->arch.pio.string) |
3705 | return EMULATE_DO_MMIO; | 3787 | return EMULATE_DO_MMIO; |
3706 | 3788 | ||
3789 | if (vcpu->arch.pio.cur_count && !vcpu->arch.pio.string) { | ||
3790 | if (!vcpu->arch.pio.in) | ||
3791 | vcpu->arch.pio.cur_count = 0; | ||
3792 | return EMULATE_DO_MMIO; | ||
3793 | } | ||
3794 | |||
3707 | if (r || vcpu->mmio_is_write) { | 3795 | if (r || vcpu->mmio_is_write) { |
3708 | run->exit_reason = KVM_EXIT_MMIO; | 3796 | run->exit_reason = KVM_EXIT_MMIO; |
3709 | run->mmio.phys_addr = vcpu->mmio_phys_addr; | 3797 | run->mmio.phys_addr = vcpu->mmio_phys_addr; |
@@ -3760,43 +3848,36 @@ int complete_pio(struct kvm_vcpu *vcpu) | |||
3760 | int r; | 3848 | int r; |
3761 | unsigned long val; | 3849 | unsigned long val; |
3762 | 3850 | ||
3763 | if (!io->string) { | 3851 | if (io->in) { |
3764 | if (io->in) { | 3852 | r = pio_copy_data(vcpu); |
3765 | val = kvm_register_read(vcpu, VCPU_REGS_RAX); | 3853 | if (r) |
3766 | memcpy(&val, vcpu->arch.pio_data, io->size); | 3854 | goto out; |
3767 | kvm_register_write(vcpu, VCPU_REGS_RAX, val); | 3855 | } |
3768 | } | ||
3769 | } else { | ||
3770 | if (io->in) { | ||
3771 | r = pio_copy_data(vcpu); | ||
3772 | if (r) | ||
3773 | goto out; | ||
3774 | } | ||
3775 | 3856 | ||
3776 | delta = 1; | 3857 | delta = 1; |
3777 | if (io->rep) { | 3858 | if (io->rep) { |
3778 | delta *= io->cur_count; | 3859 | delta *= io->cur_count; |
3779 | /* | 3860 | /* |
3780 | * The size of the register should really depend on | 3861 | * The size of the register should really depend on |
3781 | * current address size. | 3862 | * current address size. |
3782 | */ | 3863 | */ |
3783 | val = kvm_register_read(vcpu, VCPU_REGS_RCX); | 3864 | val = kvm_register_read(vcpu, VCPU_REGS_RCX); |
3784 | val -= delta; | 3865 | val -= delta; |
3785 | kvm_register_write(vcpu, VCPU_REGS_RCX, val); | 3866 | kvm_register_write(vcpu, VCPU_REGS_RCX, val); |
3786 | } | 3867 | } |
3787 | if (io->down) | 3868 | if (io->down) |
3788 | delta = -delta; | 3869 | delta = -delta; |
3789 | delta *= io->size; | 3870 | delta *= io->size; |
3790 | if (io->in) { | 3871 | if (io->in) { |
3791 | val = kvm_register_read(vcpu, VCPU_REGS_RDI); | 3872 | val = kvm_register_read(vcpu, VCPU_REGS_RDI); |
3792 | val += delta; | 3873 | val += delta; |
3793 | kvm_register_write(vcpu, VCPU_REGS_RDI, val); | 3874 | kvm_register_write(vcpu, VCPU_REGS_RDI, val); |
3794 | } else { | 3875 | } else { |
3795 | val = kvm_register_read(vcpu, VCPU_REGS_RSI); | 3876 | val = kvm_register_read(vcpu, VCPU_REGS_RSI); |
3796 | val += delta; | 3877 | val += delta; |
3797 | kvm_register_write(vcpu, VCPU_REGS_RSI, val); | 3878 | kvm_register_write(vcpu, VCPU_REGS_RSI, val); |
3798 | } | ||
3799 | } | 3879 | } |
3880 | |||
3800 | out: | 3881 | out: |
3801 | io->count -= io->cur_count; | 3882 | io->count -= io->cur_count; |
3802 | io->cur_count = 0; | 3883 | io->cur_count = 0; |
@@ -3804,21 +3885,6 @@ out: | |||
3804 | return 0; | 3885 | return 0; |
3805 | } | 3886 | } |
3806 | 3887 | ||
3807 | static int kernel_pio(struct kvm_vcpu *vcpu, void *pd) | ||
3808 | { | ||
3809 | /* TODO: String I/O for in kernel device */ | ||
3810 | int r; | ||
3811 | |||
3812 | if (vcpu->arch.pio.in) | ||
3813 | r = kvm_io_bus_read(vcpu->kvm, KVM_PIO_BUS, vcpu->arch.pio.port, | ||
3814 | vcpu->arch.pio.size, pd); | ||
3815 | else | ||
3816 | r = kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS, | ||
3817 | vcpu->arch.pio.port, vcpu->arch.pio.size, | ||
3818 | pd); | ||
3819 | return r; | ||
3820 | } | ||
3821 | |||
3822 | static int pio_string_write(struct kvm_vcpu *vcpu) | 3888 | static int pio_string_write(struct kvm_vcpu *vcpu) |
3823 | { | 3889 | { |
3824 | struct kvm_pio_request *io = &vcpu->arch.pio; | 3890 | struct kvm_pio_request *io = &vcpu->arch.pio; |
@@ -3836,36 +3902,6 @@ static int pio_string_write(struct kvm_vcpu *vcpu) | |||
3836 | return r; | 3902 | return r; |
3837 | } | 3903 | } |
3838 | 3904 | ||
3839 | int kvm_emulate_pio(struct kvm_vcpu *vcpu, int in, int size, unsigned port) | ||
3840 | { | ||
3841 | unsigned long val; | ||
3842 | |||
3843 | trace_kvm_pio(!in, port, size, 1); | ||
3844 | |||
3845 | vcpu->run->exit_reason = KVM_EXIT_IO; | ||
3846 | vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | ||
3847 | vcpu->run->io.size = vcpu->arch.pio.size = size; | ||
3848 | vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE; | ||
3849 | vcpu->run->io.count = vcpu->arch.pio.count = vcpu->arch.pio.cur_count = 1; | ||
3850 | vcpu->run->io.port = vcpu->arch.pio.port = port; | ||
3851 | vcpu->arch.pio.in = in; | ||
3852 | vcpu->arch.pio.string = 0; | ||
3853 | vcpu->arch.pio.down = 0; | ||
3854 | vcpu->arch.pio.rep = 0; | ||
3855 | |||
3856 | if (!vcpu->arch.pio.in) { | ||
3857 | val = kvm_register_read(vcpu, VCPU_REGS_RAX); | ||
3858 | memcpy(vcpu->arch.pio_data, &val, 4); | ||
3859 | } | ||
3860 | |||
3861 | if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { | ||
3862 | complete_pio(vcpu); | ||
3863 | return 1; | ||
3864 | } | ||
3865 | return 0; | ||
3866 | } | ||
3867 | EXPORT_SYMBOL_GPL(kvm_emulate_pio); | ||
3868 | |||
3869 | int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, int in, | 3905 | int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, int in, |
3870 | int size, unsigned long count, int down, | 3906 | int size, unsigned long count, int down, |
3871 | gva_t address, int rep, unsigned port) | 3907 | gva_t address, int rep, unsigned port) |
@@ -3931,6 +3967,16 @@ int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, int in, | |||
3931 | } | 3967 | } |
3932 | EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); | 3968 | EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); |
3933 | 3969 | ||
3970 | int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port) | ||
3971 | { | ||
3972 | unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); | ||
3973 | int ret = emulator_pio_out_emulated(size, port, &val, 1, vcpu); | ||
3974 | /* do not return to emulator after return from userspace */ | ||
3975 | vcpu->arch.pio.cur_count = 0; | ||
3976 | return ret; | ||
3977 | } | ||
3978 | EXPORT_SYMBOL_GPL(kvm_fast_pio_out); | ||
3979 | |||
3934 | static void bounce_off(void *info) | 3980 | static void bounce_off(void *info) |
3935 | { | 3981 | { |
3936 | /* nothing */ | 3982 | /* nothing */ |
@@ -4661,9 +4707,12 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | |||
4661 | 4707 | ||
4662 | if (vcpu->arch.pio.cur_count) { | 4708 | if (vcpu->arch.pio.cur_count) { |
4663 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); | 4709 | vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); |
4664 | r = complete_pio(vcpu); | 4710 | if (!vcpu->arch.pio.string) |
4711 | r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE); | ||
4712 | else | ||
4713 | r = complete_pio(vcpu); | ||
4665 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); | 4714 | srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); |
4666 | if (r) | 4715 | if (r == EMULATE_DO_MMIO) |
4667 | goto out; | 4716 | goto out; |
4668 | } | 4717 | } |
4669 | if (vcpu->mmio_needed) { | 4718 | if (vcpu->mmio_needed) { |