aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/svm.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@qumranet.com>2007-03-20 06:46:50 -0400
committerAvi Kivity <avi@qumranet.com>2007-05-03 03:52:25 -0400
commit039576c03c35e2f990ad9bb9c39e1bad3cd60d34 (patch)
treefa6c81a40a36d2c0da1cf20c5deb45cb9bd7ba95 /drivers/kvm/svm.c
parentf0fe510864a4520a85dfa35ae14f5f376c56efc7 (diff)
KVM: Avoid guest virtual addresses in string pio userspace interface
The current string pio interface communicates using guest virtual addresses, relying on userspace to translate addresses and to check permissions. This interface cannot fully support guest smp, as the check needs to take into account two pages at one in case an unaligned string transfer straddles a page boundary. Change the interface not to communicate guest addresses at all; instead use a buffer page (mmaped by userspace) and do transfers there. The kernel manages the virtual to physical translation and can perform the checks atomically by taking the appropriate locks. Signed-off-by: Avi Kivity <avi@qumranet.com>
Diffstat (limited to 'drivers/kvm/svm.c')
-rw-r--r--drivers/kvm/svm.c40
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
987static unsigned long io_adress(struct kvm_vcpu *vcpu, int ins, u64 *address) 987static 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)
1028static int io_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1028static 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
1067static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1065static int nop_on_interception(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)