diff options
Diffstat (limited to 'arch/x86/kvm/x86.c')
-rw-r--r-- | arch/x86/kvm/x86.c | 206 |
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 | ||
3153 | static int kvm_write_guest_virt_helper(gva_t addr, void *val, | 3153 | static 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 | ||
3187 | static 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 | |||
3194 | static 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 | |||
3201 | static int emulator_read_emulated(unsigned long addr, | 3186 | static 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) | |||
3423 | static int emulator_pio_in_emulated(int size, unsigned short port, void *val, | 3408 | static 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 | } |
3822 | EXPORT_SYMBOL_GPL(emulate_instruction); | 3797 | EXPORT_SYMBOL_GPL(emulate_instruction); |
3823 | 3798 | ||
3824 | static 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 | |||
3844 | int 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 | |||
3881 | out: | ||
3882 | io->count -= io->cur_count; | ||
3883 | io->cur_count = 0; | ||
3884 | |||
3885 | return 0; | ||
3886 | } | ||
3887 | |||
3888 | static 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 | |||
3905 | int 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 | } | ||
3968 | EXPORT_SYMBOL_GPL(kvm_emulate_pio_string); | ||
3969 | |||
3970 | int kvm_fast_pio_out(struct kvm_vcpu *vcpu, int size, unsigned short port) | 3799 | int 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 | } |
3978 | EXPORT_SYMBOL_GPL(kvm_fast_pio_out); | 3807 | EXPORT_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); |