diff options
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r-- | drivers/kvm/svm.c | 40 |
1 files changed, 19 insertions, 21 deletions
diff --git a/drivers/kvm/svm.c b/drivers/kvm/svm.c index 2396ada23777..64afc5cf890d 100644 --- a/drivers/kvm/svm.c +++ b/drivers/kvm/svm.c | |||
@@ -984,7 +984,7 @@ static int io_get_override(struct kvm_vcpu *vcpu, | |||
984 | return 0; | 984 | return 0; |
985 | } | 985 | } |
986 | 986 | ||
987 | static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address) | 987 | static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, gva_t *address) |
988 | { | 988 | { |
989 | unsigned long addr_mask; | 989 | unsigned long addr_mask; |
990 | unsigned long *reg; | 990 | unsigned long *reg; |
@@ -1028,40 +1028,38 @@ static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address) | |||
1028 | static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1028 | static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |
1029 | { | 1029 | { |
1030 | u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug? | 1030 | u32 io_info = vcpu->svm->vmcb->control.exit_info_1; //address size bug? |
1031 | int _in = io_info & SVM_IOIO_TYPE_MASK; | 1031 | int size, down, in, string, rep; |
1032 | unsigned port; | ||
1033 | unsigned long count; | ||
1034 | gva_t address = 0; | ||
1032 | 1035 | ||
1033 | ++kvm_stat.io_exits; | 1036 | ++kvm_stat.io_exits; |
1034 | 1037 | ||
1035 | vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; | 1038 | vcpu->svm->next_rip = vcpu->svm->vmcb->control.exit_info_2; |
1036 | 1039 | ||
1037 | kvm_run->exit_reason = KVM_EXIT_IO; | 1040 | in = (io_info & SVM_IOIO_TYPE_MASK) != 0; |
1038 | kvm_run->io.port = io_info >> 16; | 1041 | port = io_info >> 16; |
1039 | kvm_run->io.direction = (_in) ? KVM_EXIT_IO_IN : KVM_EXIT_IO_OUT; | 1042 | size = (io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT; |
1040 | kvm_run->io.size = ((io_info & SVM_IOIO_SIZE_MASK) >> SVM_IOIO_SIZE_SHIFT); | 1043 | string = (io_info & SVM_IOIO_STR_MASK) != 0; |
1041 | kvm_run->io.string = (io_info & SVM_IOIO_STR_MASK) != 0; | 1044 | rep = (io_info & SVM_IOIO_REP_MASK) != 0; |
1042 | kvm_run->io.rep = (io_info & SVM_IOIO_REP_MASK) != 0; | 1045 | count = 1; |
1043 | kvm_run->io.count = 1; | 1046 | down = (vcpu->svm->vmcb->save.rflags & X86_EFLAGS_DF) != 0; |
1044 | 1047 | ||
1045 | if (kvm_run->io.string) { | 1048 | if (string) { |
1046 | unsigned addr_mask; | 1049 | unsigned addr_mask; |
1047 | 1050 | ||
1048 | addr_mask = io_adress(vcpu, _in, &kvm_run->io.address); | 1051 | addr_mask = io_adress(vcpu, in, &address); |
1049 | if (!addr_mask) { | 1052 | if (!addr_mask) { |
1050 | printk(KERN_DEBUG "%s: get io address failed\n", | 1053 | printk(KERN_DEBUG "%s: get io address failed\n", |
1051 | __FUNCTION__); | 1054 | __FUNCTION__); |
1052 | return 1; | 1055 | return 1; |
1053 | } | 1056 | } |
1054 | 1057 | ||
1055 | if (kvm_run->io.rep) { | 1058 | if (rep) |
1056 | kvm_run->io.count | 1059 | count = vcpu->regs[VCPU_REGS_RCX] & addr_mask; |
1057 | = vcpu->regs[VCPU_REGS_RCX] & addr_mask; | 1060 | } |
1058 | kvm_run->io.string_down = (vcpu->svm->vmcb->save.rflags | 1061 | return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down, |
1059 | & X86_EFLAGS_DF) != 0; | 1062 | address, rep, port); |
1060 | } | ||
1061 | } else | ||
1062 | kvm_run->io.value = vcpu->svm->vmcb->save.rax; | ||
1063 | vcpu->pio_pending = 1; | ||
1064 | return 0; | ||
1065 | } | 1063 | } |
1066 | 1064 | ||
1067 | static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1065 | static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) |