]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/x86/kvm/svm.c
Merge branches 'sched/devel', 'sched/cpu-hotplug', 'sched/cpusets' and 'sched/urgent...
[linux-2.6-omap-h63xx.git] / arch / x86 / kvm / svm.c
index b756e876dce391b222c6e4ec84c7dd6447e738de..8233b86c778cfd0a01b2ca96dbe7d27776381037 100644 (file)
@@ -62,6 +62,7 @@ static int npt = 1;
 module_param(npt, int, S_IRUGO);
 
 static void kvm_reput_irq(struct vcpu_svm *svm);
+static void svm_flush_tlb(struct kvm_vcpu *vcpu);
 
 static inline struct vcpu_svm *to_svm(struct kvm_vcpu *vcpu)
 {
@@ -453,7 +454,8 @@ static __init int svm_hardware_setup(void)
        if (npt_enabled) {
                printk(KERN_INFO "kvm: Nested Paging enabled\n");
                kvm_enable_tdp();
-       }
+       } else
+               kvm_disable_tdp();
 
        return 0;
 
@@ -877,6 +879,10 @@ set:
 static void svm_set_cr4(struct kvm_vcpu *vcpu, unsigned long cr4)
 {
        unsigned long host_cr4_mce = read_cr4() & X86_CR4_MCE;
+       unsigned long old_cr4 = to_svm(vcpu)->vmcb->save.cr4;
+
+       if (npt_enabled && ((old_cr4 ^ cr4) & X86_CR4_PGE))
+               force_new_asid(vcpu);
 
        vcpu->arch.cr4 = cr4;
        if (!npt_enabled)
@@ -1007,10 +1013,13 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
        struct kvm *kvm = svm->vcpu.kvm;
        u64 fault_address;
        u32 error_code;
+       bool event_injection = false;
 
        if (!irqchip_in_kernel(kvm) &&
-               is_external_interrupt(exit_int_info))
+           is_external_interrupt(exit_int_info)) {
+               event_injection = true;
                push_irq(&svm->vcpu, exit_int_info & SVM_EVTINJ_VEC_MASK);
+       }
 
        fault_address  = svm->vmcb->control.exit_info_2;
        error_code = svm->vmcb->control.exit_info_1;
@@ -1023,7 +1032,16 @@ static int pf_interception(struct vcpu_svm *svm, struct kvm_run *kvm_run)
                KVMTRACE_3D(TDP_FAULT, &svm->vcpu, error_code,
                            (u32)fault_address, (u32)(fault_address >> 32),
                            handler);
+       /*
+        * FIXME: Tis shouldn't be necessary here, but there is a flush
+        * missing in the MMU code. Until we find this bug, flush the
+        * complete TLB here on an NPF
+        */
+       if (npt_enabled)
+               svm_flush_tlb(&svm->vcpu);
 
+       if (event_injection)
+               kvm_mmu_unprotect_page_virt(&svm->vcpu, fault_address);
        return kvm_mmu_page_fault(&svm->vcpu, fault_address, error_code);
 }