diff options
author | Avi Kivity <avi@qumranet.com> | 2007-03-20 06:46:50 -0400 |
---|---|---|
committer | Avi Kivity <avi@qumranet.com> | 2007-05-03 03:52:25 -0400 |
commit | 039576c03c35e2f990ad9bb9c39e1bad3cd60d34 (patch) | |
tree | fa6c81a40a36d2c0da1cf20c5deb45cb9bd7ba95 /drivers/kvm/vmx.c | |
parent | f0fe510864a4520a85dfa35ae14f5f376c56efc7 (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.c | 40 |
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 | ||
1397 | static int get_io_count(struct kvm_vcpu *vcpu, u64 *count) | 1397 | static 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) | |||
1439 | done: | 1439 | done: |
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 | ||
1445 | static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) | 1446 | static 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 | ||
1473 | static void | 1473 | static void |