aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/kvm/vmx.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/vmx.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/vmx.c')
-rw-r--r--drivers/kvm/vmx.c40
1 files changed, 20 insertions, 20 deletions
diff --git a/drivers/kvm/vmx.c b/drivers/kvm/vmx.c
index e69bab6d811d..0d9bf0b36d37 100644
--- a/drivers/kvm/vmx.c
+++ b/drivers/kvm/vmx.c
@@ -1394,7 +1394,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1394 return 0; 1394 return 0;
1395} 1395}
1396 1396
1397static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) 1397static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
1398{ 1398{
1399 u64 inst; 1399 u64 inst;
1400 gva_t rip; 1400 gva_t rip;
@@ -1439,35 +1439,35 @@ static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
1439done: 1439done:
1440 countr_size *= 8; 1440 countr_size *= 8;
1441 *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size)); 1441 *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
1442 //printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
1442 return 1; 1443 return 1;
1443} 1444}
1444 1445
1445static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) 1446static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
1446{ 1447{
1447 u64 exit_qualification; 1448 u64 exit_qualification;
1449 int size, down, in, string, rep;
1450 unsigned port;
1451 unsigned long count;
1452 gva_t address;
1448 1453
1449 ++kvm_stat.io_exits; 1454 ++kvm_stat.io_exits;
1450 exit_qualification = vmcs_read64(EXIT_QUALIFICATION); 1455 exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
1451 kvm_run->exit_reason = KVM_EXIT_IO; 1456 in = (exit_qualification & 8) != 0;
1452 if (exit_qualification & 8) 1457 size = (exit_qualification & 7) + 1;
1453 kvm_run->io.direction = KVM_EXIT_IO_IN; 1458 string = (exit_qualification & 16) != 0;
1454 else 1459 down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
1455 kvm_run->io.direction = KVM_EXIT_IO_OUT; 1460 count = 1;
1456 kvm_run->io.size = (exit_qualification & 7) + 1; 1461 rep = (exit_qualification & 32) != 0;
1457 kvm_run->io.string = (exit_qualification & 16) != 0; 1462 port = exit_qualification >> 16;
1458 kvm_run->io.string_down 1463 address = 0;
1459 = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0; 1464 if (string) {
1460 kvm_run->io.rep = (exit_qualification & 32) != 0; 1465 if (rep && !get_io_count(vcpu, &count))
1461 kvm_run->io.port = exit_qualification >> 16;
1462 kvm_run->io.count = 1;
1463 if (kvm_run->io.string) {
1464 if (!get_io_count(vcpu, &kvm_run->io.count))
1465 return 1; 1466 return 1;
1466 kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS); 1467 address = vmcs_readl(GUEST_LINEAR_ADDRESS);
1467 } else 1468 }
1468 kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */ 1469 return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
1469 vcpu->pio_pending = 1; 1470 address, rep, port);
1470 return 0;
1471} 1471}
1472 1472
1473static void 1473static void