]> err.no Git - linux-2.6/blobdiff - drivers/kvm/kvm_main.c
KVM: Don't assign vcpu->cr3 if it's invalid: check first, set last
[linux-2.6] / drivers / kvm / kvm_main.c
index bfb1b6de05843beb95a80d31f0547b4d5bde89f1..5dc60170278241235d34009b6094b63fcd10c7b3 100644 (file)
@@ -579,7 +579,6 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
                }
        }
 
-       vcpu->cr3 = cr3;
        mutex_lock(&vcpu->kvm->lock);
        /*
         * Does the new cr3 value map to physical memory? (Note, we
@@ -592,8 +591,10 @@ void set_cr3(struct kvm_vcpu *vcpu, unsigned long cr3)
         */
        if (unlikely(!gfn_to_memslot(vcpu->kvm, cr3 >> PAGE_SHIFT)))
                inject_gp(vcpu);
-       else
+       else {
+               vcpu->cr3 = cr3;
                vcpu->mmu.new_cr3(vcpu);
+       }
        mutex_unlock(&vcpu->kvm->lock);
 }
 EXPORT_SYMBOL_GPL(set_cr3);
@@ -803,11 +804,14 @@ static int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
        if (copy_to_user(log->dirty_bitmap, memslot->dirty_bitmap, n))
                goto out;
 
-       mutex_lock(&kvm->lock);
-       kvm_mmu_slot_remove_write_access(kvm, log->slot);
-       kvm_flush_remote_tlbs(kvm);
-       memset(memslot->dirty_bitmap, 0, n);
-       mutex_unlock(&kvm->lock);
+       /* If nothing is dirty, don't bother messing with page tables. */
+       if (any) {
+               mutex_lock(&kvm->lock);
+               kvm_mmu_slot_remove_write_access(kvm, log->slot);
+               kvm_flush_remote_tlbs(kvm);
+               memset(memslot->dirty_bitmap, 0, n);
+               mutex_unlock(&kvm->lock);
+       }
 
        r = 0;
 
@@ -3099,6 +3103,7 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size,
                  struct module *module)
 {
        int r;
+       int cpu;
 
        if (kvm_arch_ops) {
                printk(KERN_ERR "kvm: already loaded the other module\n");
@@ -3120,6 +3125,14 @@ int kvm_init_arch(struct kvm_arch_ops *ops, unsigned int vcpu_size,
        if (r < 0)
                goto out;
 
+       for_each_online_cpu(cpu) {
+               smp_call_function_single(cpu,
+                               kvm_arch_ops->check_processor_compatibility,
+                               &r, 0, 1);
+               if (r < 0)
+                       goto out_free_0;
+       }
+
        on_each_cpu(hardware_enable, NULL, 0, 1);
        r = register_cpu_notifier(&kvm_cpu_notifier);
        if (r)
@@ -3166,6 +3179,7 @@ out_free_2:
        unregister_cpu_notifier(&kvm_cpu_notifier);
 out_free_1:
        on_each_cpu(hardware_disable, NULL, 0, 1);
+out_free_0:
        kvm_arch_ops->hardware_unsetup();
 out:
        kvm_arch_ops = NULL;