KVM: Add "exiting guest mode" state
[linux-2.6-block.git] / arch / x86 / kvm / x86.c
index bcc0efce85bf05aaf87893b721a8569ff1cac44f..a7f65aa6eef6a860dcde9e13d90ce4c387f6754f 100644 (file)
@@ -2575,9 +2575,6 @@ static int kvm_vcpu_ioctl_x86_set_mce(struct kvm_vcpu *vcpu,
        if (mce->status & MCI_STATUS_UC) {
                if ((vcpu->arch.mcg_status & MCG_STATUS_MCIP) ||
                    !kvm_read_cr4_bits(vcpu, X86_CR4_MCE)) {
-                       printk(KERN_DEBUG "kvm: set_mce: "
-                              "injects mce exception while "
-                              "previous one is in progress!\n");
                        kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
                        return 0;
                }
@@ -5213,14 +5210,18 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
                kvm_load_guest_fpu(vcpu);
        kvm_load_guest_xcr0(vcpu);
 
-       atomic_set(&vcpu->guest_mode, 1);
-       smp_wmb();
+       vcpu->mode = IN_GUEST_MODE;
+
+       /* We should set ->mode before check ->requests,
+        * see the comment in make_all_cpus_request.
+        */
+       smp_mb();
 
        local_irq_disable();
 
-       if (!atomic_read(&vcpu->guest_mode) || vcpu->requests
+       if (vcpu->mode == EXITING_GUEST_MODE || vcpu->requests
            || need_resched() || signal_pending(current)) {
-               atomic_set(&vcpu->guest_mode, 0);
+               vcpu->mode = OUTSIDE_GUEST_MODE;
                smp_wmb();
                local_irq_enable();
                preempt_enable();
@@ -5256,7 +5257,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
 
        kvm_get_msr(vcpu, MSR_IA32_TSC, &vcpu->arch.last_guest_tsc);
 
-       atomic_set(&vcpu->guest_mode, 0);
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        smp_wmb();
        local_irq_enable();
 
@@ -5574,7 +5575,7 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
                                  struct kvm_sregs *sregs)
 {
        int mmu_reset_needed = 0;
-       int pending_vec, max_bits;
+       int pending_vec, max_bits, idx;
        struct desc_ptr dt;
 
        dt.size = sregs->idt.limit;
@@ -5603,10 +5604,13 @@ int kvm_arch_vcpu_ioctl_set_sregs(struct kvm_vcpu *vcpu,
        kvm_x86_ops->set_cr4(vcpu, sregs->cr4);
        if (sregs->cr4 & X86_CR4_OSXSAVE)
                update_cpuid(vcpu);
+
+       idx = srcu_read_lock(&vcpu->kvm->srcu);
        if (!is_long_mode(vcpu) && is_pae(vcpu)) {
                load_pdptrs(vcpu, vcpu->arch.walk_mmu, kvm_read_cr3(vcpu));
                mmu_reset_needed = 1;
        }
+       srcu_read_unlock(&vcpu->kvm->srcu, idx);
 
        if (mmu_reset_needed)
                kvm_mmu_reset_context(vcpu);
@@ -6157,7 +6161,7 @@ void kvm_vcpu_kick(struct kvm_vcpu *vcpu)
 
        me = get_cpu();
        if (cpu != me && (unsigned)cpu < nr_cpu_ids && cpu_online(cpu))
-               if (atomic_xchg(&vcpu->guest_mode, 0))
+               if (kvm_vcpu_exiting_guest_mode(vcpu) == IN_GUEST_MODE)
                        smp_send_reschedule(cpu);
        put_cpu();
 }