KVM: Avoid guest virtual addresses in string pio userspace interface
[deliverable/linux.git] / drivers / kvm / vmx.c
index fbbf9d6b299fa16bed8f89a677dc393bc1c55ee1..0d9bf0b36d3759f698cc6783e6d77bfa5c8dc5b1 100644 (file)
@@ -1394,7 +1394,7 @@ static int handle_triple_fault(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
        return 0;
 }
 
-static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
+static int get_io_count(struct kvm_vcpu *vcpu, unsigned long *count)
 {
        u64 inst;
        gva_t rip;
@@ -1439,33 +1439,35 @@ static int get_io_count(struct kvm_vcpu *vcpu, u64 *count)
 done:
        countr_size *= 8;
        *count = vcpu->regs[VCPU_REGS_RCX] & (~0ULL >> (64 - countr_size));
+       //printk("cx: %lx\n", vcpu->regs[VCPU_REGS_RCX]);
        return 1;
 }
 
 static int handle_io(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
        u64 exit_qualification;
+       int size, down, in, string, rep;
+       unsigned port;
+       unsigned long count;
+       gva_t address;
 
        ++kvm_stat.io_exits;
        exit_qualification = vmcs_read64(EXIT_QUALIFICATION);
-       kvm_run->exit_reason = KVM_EXIT_IO;
-       if (exit_qualification & 8)
-               kvm_run->io.direction = KVM_EXIT_IO_IN;
-       else
-               kvm_run->io.direction = KVM_EXIT_IO_OUT;
-       kvm_run->io.size = (exit_qualification & 7) + 1;
-       kvm_run->io.string = (exit_qualification & 16) != 0;
-       kvm_run->io.string_down
-               = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
-       kvm_run->io.rep = (exit_qualification & 32) != 0;
-       kvm_run->io.port = exit_qualification >> 16;
-       if (kvm_run->io.string) {
-               if (!get_io_count(vcpu, &kvm_run->io.count))
+       in = (exit_qualification & 8) != 0;
+       size = (exit_qualification & 7) + 1;
+       string = (exit_qualification & 16) != 0;
+       down = (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_DF) != 0;
+       count = 1;
+       rep = (exit_qualification & 32) != 0;
+       port = exit_qualification >> 16;
+       address = 0;
+       if (string) {
+               if (rep && !get_io_count(vcpu, &count))
                        return 1;
-               kvm_run->io.address = vmcs_readl(GUEST_LINEAR_ADDRESS);
-       } else
-               kvm_run->io.value = vcpu->regs[VCPU_REGS_RAX]; /* rax */
-       return 0;
+               address = vmcs_readl(GUEST_LINEAR_ADDRESS);
+       }
+       return kvm_setup_pio(vcpu, kvm_run, in, size, count, string, down,
+                            address, rep, port);
 }
 
 static void
@@ -1583,8 +1585,8 @@ static int handle_dr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_cpuid(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       kvm_run->exit_reason = KVM_EXIT_CPUID;
-       return 0;
+       kvm_emulate_cpuid(vcpu);
+       return 1;
 }
 
 static int handle_rdmsr(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
@@ -1658,7 +1660,7 @@ static int handle_halt(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 
 static int handle_vmcall(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
 {
-       vmcs_writel(GUEST_RIP, vmcs_readl(GUEST_RIP)+3);
+       skip_emulated_instruction(vcpu);
        return kvm_hypercall(vcpu, kvm_run);
 }
 
@@ -1920,10 +1922,10 @@ again:
 
        asm ("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS));
 
-       kvm_run->exit_type = 0;
        if (fail) {
-               kvm_run->exit_type = KVM_EXIT_TYPE_FAIL_ENTRY;
-               kvm_run->exit_reason = vmcs_read32(VM_INSTRUCTION_ERROR);
+               kvm_run->exit_reason = KVM_EXIT_FAIL_ENTRY;
+               kvm_run->fail_entry.hardware_entry_failure_reason
+                       = vmcs_read32(VM_INSTRUCTION_ERROR);
                r = 0;
        } else {
                /*
@@ -1933,19 +1935,20 @@ again:
                        profile_hit(KVM_PROFILING, (void *)vmcs_readl(GUEST_RIP));
 
                vcpu->launched = 1;
-               kvm_run->exit_type = KVM_EXIT_TYPE_VM_EXIT;
                r = kvm_handle_exit(kvm_run, vcpu);
                if (r > 0) {
                        /* Give scheduler a change to reschedule. */
                        if (signal_pending(current)) {
                                ++kvm_stat.signal_exits;
                                post_kvm_run_save(vcpu, kvm_run);
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
                                return -EINTR;
                        }
 
                        if (dm_request_for_irq_injection(vcpu, kvm_run)) {
                                ++kvm_stat.request_irq_exits;
                                post_kvm_run_save(vcpu, kvm_run);
+                               kvm_run->exit_reason = KVM_EXIT_INTR;
                                return -EINTR;
                        }
 
This page took 0.030454 seconds and 5 git commands to generate.