aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/x86.c
diff options
context:
space:
mode:
authorGleb Natapov <gleb@redhat.com>2010-03-18 09:20:24 -0400
committerAvi Kivity <avi@redhat.com>2010-05-17 05:16:26 -0400
commit7972995b0c346de76fe260ce0fd6bcc8ffab724a (patch)
treea2522988d8cd465b836c0a32399d8eeb7a3ed545 /arch/x86/kvm/x86.c
parentcf8f70bfe38b326bb80b10f76d6544f571040229 (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/x86.c')
-rw-r--r--arch/x86/kvm/x86.c206
1 files changed, 17 insertions, 189 deletions
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 6624ad13ee99..658e8e8155cb 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3150,18 +3150,17 @@ static int kvm_read_guest_virt_system(gva_t addr, void *val, unsigned int bytes,
3150 return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error); 3150 return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
3151} 3151}
3152 3152
3153static int kvm_write_guest_virt_helper(gva_t addr, void *val, 3153static int kvm_write_guest_virt_system(gva_t addr, void *val,
3154 unsigned int bytes, 3154 unsigned int bytes,
3155 struct kvm_vcpu *vcpu, u32 access, 3155 struct kvm_vcpu *vcpu,
3156 u32 *error) 3156 u32 *error)
3157{ 3157{
3158 void *data = val; 3158 void *data = val;
3159 int r = X86EMUL_CONTINUE; 3159 int r = X86EMUL_CONTINUE;
3160 3160
3161 access |= PFERR_WRITE_MASK;
3162
3163 while (bytes) { 3161 while (bytes) {
3164 gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr, access, error); 3162 gpa_t gpa = vcpu->arch.mmu.gva_to_gpa(vcpu, addr,
3163 PFERR_WRITE_MASK, error);
3165 unsigned offset = addr & (PAGE_SIZE-1); 3164 unsigned offset = addr & (PAGE_SIZE-1);
3166 unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset); 3165 unsigned towrite = min(bytes, (unsigned)PAGE_SIZE - offset);
3167 int ret; 3166 int ret;
@@ -3184,20 +3183,6 @@ out:
3184 return r; 3183 return r;
3185} 3184}
3186 3185
3187static int kvm_write_guest_virt(gva_t addr, void *val, unsigned int bytes,
3188 struct kvm_vcpu *vcpu, u32 *error)
3189{
3190 u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
3191 return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, access, error);
3192}
3193
3194static int kvm_write_guest_virt_system(gva_t addr, void *val,
3195 unsigned int bytes,
3196 struct kvm_vcpu *vcpu, u32 *error)
3197{
3198 return kvm_write_guest_virt_helper(addr, val, bytes, vcpu, 0, error);
3199}
3200
3201static int emulator_read_emulated(unsigned long addr, 3186static int emulator_read_emulated(unsigned long addr,
3202 void *val, 3187 void *val,
3203 unsigned int bytes, 3188 unsigned int bytes,
@@ -3423,23 +3408,20 @@ static int kernel_pio(struct kvm_vcpu *vcpu, void *pd)
3423static int emulator_pio_in_emulated(int size, unsigned short port, void *val, 3408static int emulator_pio_in_emulated(int size, unsigned short port, void *val,
3424 unsigned int count, struct kvm_vcpu *vcpu) 3409 unsigned int count, struct kvm_vcpu *vcpu)
3425{ 3410{
3426 if (vcpu->arch.pio.cur_count) 3411 if (vcpu->arch.pio.count)
3427 goto data_avail; 3412 goto data_avail;
3428 3413
3429 trace_kvm_pio(1, port, size, 1); 3414 trace_kvm_pio(1, port, size, 1);
3430 3415
3431 vcpu->arch.pio.port = port; 3416 vcpu->arch.pio.port = port;
3432 vcpu->arch.pio.in = 1; 3417 vcpu->arch.pio.in = 1;
3433 vcpu->arch.pio.string = 0; 3418 vcpu->arch.pio.count = count;
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; 3419 vcpu->arch.pio.size = size;
3438 3420
3439 if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { 3421 if (!kernel_pio(vcpu, vcpu->arch.pio_data)) {
3440 data_avail: 3422 data_avail:
3441 memcpy(val, vcpu->arch.pio_data, size * count); 3423 memcpy(val, vcpu->arch.pio_data, size * count);
3442 vcpu->arch.pio.cur_count = 0; 3424 vcpu->arch.pio.count = 0;
3443 return 1; 3425 return 1;
3444 } 3426 }
3445 3427
@@ -3461,16 +3443,13 @@ static int emulator_pio_out_emulated(int size, unsigned short port,
3461 3443
3462 vcpu->arch.pio.port = port; 3444 vcpu->arch.pio.port = port;
3463 vcpu->arch.pio.in = 0; 3445 vcpu->arch.pio.in = 0;
3464 vcpu->arch.pio.string = 0; 3446 vcpu->arch.pio.count = count;
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; 3447 vcpu->arch.pio.size = size;
3469 3448
3470 memcpy(vcpu->arch.pio_data, val, size * count); 3449 memcpy(vcpu->arch.pio_data, val, size * count);
3471 3450
3472 if (!kernel_pio(vcpu, vcpu->arch.pio_data)) { 3451 if (!kernel_pio(vcpu, vcpu->arch.pio_data)) {
3473 vcpu->arch.pio.cur_count = 0; 3452 vcpu->arch.pio.count = 0;
3474 return 1; 3453 return 1;
3475 } 3454 }
3476 3455
@@ -3717,7 +3696,6 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3717 cache_all_regs(vcpu); 3696 cache_all_regs(vcpu);
3718 3697
3719 vcpu->mmio_is_write = 0; 3698 vcpu->mmio_is_write = 0;
3720 vcpu->arch.pio.string = 0;
3721 3699
3722 if (!(emulation_type & EMULTYPE_NO_DECODE)) { 3700 if (!(emulation_type & EMULTYPE_NO_DECODE)) {
3723 int cs_db, cs_l; 3701 int cs_db, cs_l;
@@ -3783,12 +3761,9 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3783 if (r == 0) 3761 if (r == 0)
3784 kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask); 3762 kvm_x86_ops->set_interrupt_shadow(vcpu, shadow_mask);
3785 3763
3786 if (vcpu->arch.pio.string) 3764 if (vcpu->arch.pio.count) {
3787 return EMULATE_DO_MMIO;
3788
3789 if (vcpu->arch.pio.cur_count && !vcpu->arch.pio.string) {
3790 if (!vcpu->arch.pio.in) 3765 if (!vcpu->arch.pio.in)
3791 vcpu->arch.pio.cur_count = 0; 3766 vcpu->arch.pio.count = 0;
3792 return EMULATE_DO_MMIO; 3767 return EMULATE_DO_MMIO;
3793 } 3768 }
3794 3769
@@ -3821,158 +3796,12 @@ int emulate_instruction(struct kvm_vcpu *vcpu,
3821} 3796}
3822EXPORT_SYMBOL_GPL(emulate_instruction); 3797EXPORT_SYMBOL_GPL(emulate_instruction);
3823 3798
3824static int pio_copy_data(struct kvm_vcpu *vcpu)
3825{
3826 void *p = vcpu->arch.pio_data;
3827 gva_t q = vcpu->arch.pio.guest_gva;
3828 unsigned bytes;
3829 int ret;
3830 u32 error_code;
3831
3832 bytes = vcpu->arch.pio.size * vcpu->arch.pio.cur_count;
3833 if (vcpu->arch.pio.in)
3834 ret = kvm_write_guest_virt(q, p, bytes, vcpu, &error_code);
3835 else
3836 ret = kvm_read_guest_virt(q, p, bytes, vcpu, &error_code);
3837
3838 if (ret == X86EMUL_PROPAGATE_FAULT)
3839 kvm_inject_page_fault(vcpu, q, error_code);
3840
3841 return ret;
3842}
3843
3844int complete_pio(struct kvm_vcpu *vcpu)
3845{
3846 struct kvm_pio_request *io = &vcpu->arch.pio;
3847 long delta;
3848 int r;
3849 unsigned long val;
3850
3851 if (io->in) {
3852 r = pio_copy_data(vcpu);
3853 if (r)
3854 goto out;
3855 }
3856
3857 delta = 1;
3858 if (io->rep) {
3859 delta *= io->cur_count;
3860 /*
3861 * The size of the register should really depend on
3862 * current address size.
3863 */
3864 val = kvm_register_read(vcpu, VCPU_REGS_RCX);
3865 val -= delta;
3866 kvm_register_write(vcpu, VCPU_REGS_RCX, val);
3867 }
3868 if (io->down)
3869 delta = -delta;
3870 delta *= io->size;
3871 if (io->in) {
3872 val = kvm_register_read(vcpu, VCPU_REGS_RDI);
3873 val += delta;
3874 kvm_register_write(vcpu, VCPU_REGS_RDI, val);
3875 } else {
3876 val = kvm_register_read(vcpu, VCPU_REGS_RSI);
3877 val += delta;
3878 kvm_register_write(vcpu, VCPU_REGS_RSI, val);
3879 }
3880
3881out:
3882 io->count -= io->cur_count;
3883 io->cur_count = 0;
3884
3885 return 0;
3886}
3887
3888static int pio_string_write(struct kvm_vcpu *vcpu)
3889{
3890 struct kvm_pio_request *io = &vcpu->arch.pio;
3891 void *pd = vcpu->arch.pio_data;
3892 int i, r = 0;
3893
3894 for (i = 0; i < io->cur_count; i++) {
3895 if (kvm_io_bus_write(vcpu->kvm, KVM_PIO_BUS,
3896 io->port, io->size, pd)) {
3897 r = -EOPNOTSUPP;
3898 break;
3899 }
3900 pd += io->size;
3901 }
3902 return r;
3903}
3904
3905int kvm_emulate_pio_string(struct kvm_vcpu *vcpu, int in,
3906 int size, unsigned long count, int down,
3907 gva_t address, int rep, unsigned port)
3908{
3909 unsigned now, in_page;
3910 int ret = 0;
3911
3912 trace_kvm_pio(!in, port, size, count);
3913
3914 vcpu->run->exit_reason = KVM_EXIT_IO;
3915 vcpu->run->io.direction = in ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT;
3916 vcpu->run->io.size = vcpu->arch.pio.size = size;
3917 vcpu->run->io.data_offset = KVM_PIO_PAGE_OFFSET * PAGE_SIZE;
3918 vcpu->run->io.count = vcpu->arch.pio.count = vcpu->arch.pio.cur_count = count;
3919 vcpu->run->io.port = vcpu->arch.pio.port = port;
3920 vcpu->arch.pio.in = in;
3921 vcpu->arch.pio.string = 1;
3922 vcpu->arch.pio.down = down;
3923 vcpu->arch.pio.rep = rep;
3924
3925 if (!count) {
3926 kvm_x86_ops->skip_emulated_instruction(vcpu);
3927 return 1;
3928 }
3929
3930 if (!down)
3931 in_page = PAGE_SIZE - offset_in_page(address);
3932 else
3933 in_page = offset_in_page(address) + size;
3934 now = min(count, (unsigned long)in_page / size);
3935 if (!now)
3936 now = 1;
3937 if (down) {
3938 /*
3939 * String I/O in reverse. Yuck. Kill the guest, fix later.
3940 */
3941 pr_unimpl(vcpu, "guest string pio down\n");
3942 kvm_inject_gp(vcpu, 0);
3943 return 1;
3944 }
3945 vcpu->run->io.count = now;
3946 vcpu->arch.pio.cur_count = now;
3947
3948 if (vcpu->arch.pio.cur_count == vcpu->arch.pio.count)
3949 kvm_x86_ops->skip_emulated_instruction(vcpu);
3950
3951 vcpu->arch.pio.guest_gva = address;
3952
3953 if (!vcpu->arch.pio.in) {
3954 /* string PIO write */
3955 ret = pio_copy_data(vcpu);
3956 if (ret == X86EMUL_PROPAGATE_FAULT)
3957 return 1;
3958 if (ret == 0 && !pio_string_write(vcpu)) {
3959 complete_pio(vcpu);
3960 if (vcpu->arch.pio.count == 0)
3961 ret = 1;
3962 }
3963 }
3964 /* no string PIO read support yet */
3965
3966 return ret;
3967}
3968EXPORT_SYMBOL_GPL(kvm_emulate_pio_string);
3969
3970int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port) 3799int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port)
3971{ 3800{
3972 unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX); 3801 unsigned long val = kvm_register_read(vcpu, VCPU_REGS_RAX);
3973 int ret = emulator_pio_out_emulated(size, port, &val, 1, vcpu); 3802 int ret = emulator_pio_out_emulated(size, port, &val, 1, vcpu);
3974 /* do not return to emulator after return from userspace */ 3803 /* do not return to emulator after return from userspace */
3975 vcpu->arch.pio.cur_count = 0; 3804 vcpu->arch.pio.count = 0;
3976 return ret; 3805 return ret;
3977} 3806}
3978EXPORT_SYMBOL_GPL(kvm_fast_pio_out); 3807EXPORT_SYMBOL_GPL(kvm_fast_pio_out);
@@ -4705,15 +4534,14 @@ int kvm_arch_vcpu_ioctl_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
4705 if (!irqchip_in_kernel(vcpu->kvm)) 4534 if (!irqchip_in_kernel(vcpu->kvm))
4706 kvm_set_cr8(vcpu, kvm_run->cr8); 4535 kvm_set_cr8(vcpu, kvm_run->cr8);
4707 4536
4708 if (vcpu->arch.pio.cur_count) { 4537 if (vcpu->arch.pio.count) {
4709 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu); 4538 vcpu->srcu_idx = srcu_read_lock(&vcpu->kvm->srcu);
4710 if (!vcpu->arch.pio.string) 4539 r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE);
4711 r = emulate_instruction(vcpu, 0, 0, EMULTYPE_NO_DECODE);
4712 else
4713 r = complete_pio(vcpu);
4714 srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx); 4540 srcu_read_unlock(&vcpu->kvm->srcu, vcpu->srcu_idx);
4715 if (r == EMULATE_DO_MMIO) 4541 if (r == EMULATE_DO_MMIO) {
4542 r = 0;
4716 goto out; 4543 goto out;
4544 }
4717 } 4545 }
4718 if (vcpu->mmio_needed) { 4546 if (vcpu->mmio_needed) {
4719 memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8); 4547 memcpy(vcpu->mmio_data, kvm_run->mmio.data, 8);