KVM: Ensure all vcpus are consistent with in-kernel irqchip settings
[linux-flexiantxendom0.git] / arch / ia64 / kvm / kvm-ia64.c
index d85b5d2..7073185 100644 (file)
@@ -33,6 +33,7 @@
 #include <linux/uaccess.h>
 #include <linux/iommu.h>
 #include <linux/intel-iommu.h>
+#include <linux/pci.h>
 
 #include <asm/pgtable.h>
 #include <asm/gcc_intrin.h>
@@ -204,7 +205,7 @@ int kvm_dev_ioctl_check_extension(long ext)
                r = KVM_COALESCED_MMIO_PAGE_OFFSET;
                break;
        case KVM_CAP_IOMMU:
-               r = iommu_found();
+               r = iommu_present(&pci_bus_type);
                break;
        default:
                r = 0;
@@ -662,6 +663,7 @@ again:
                goto vcpu_run_fail;
 
        srcu_read_unlock(&vcpu->kvm->srcu, idx);
+       vcpu->mode = IN_GUEST_MODE;
        kvm_guest_enter();
 
        /*
@@ -683,6 +685,7 @@ again:
         */
        barrier();
        kvm_guest_exit();
+       vcpu->mode = OUTSIDE_GUEST_MODE;
        preempt_enable();
 
        idx = srcu_read_lock(&vcpu->kvm->srcu);
@@ -749,7 +752,7 @@ out:
        return r;
 }
 
-static struct kvm *kvm_alloc_kvm(void)
+struct kvm *kvm_arch_alloc_vm(void)
 {
 
        struct kvm *kvm;
@@ -760,7 +763,7 @@ static struct kvm *kvm_alloc_kvm(void)
        vm_base = __get_free_pages(GFP_KERNEL, get_order(KVM_VM_DATA_SIZE));
 
        if (!vm_base)
-               return ERR_PTR(-ENOMEM);
+               return NULL;
 
        memset((void *)vm_base, 0, KVM_VM_DATA_SIZE);
        kvm = (struct kvm *)(vm_base +
@@ -806,10 +809,12 @@ static void kvm_build_io_pmt(struct kvm *kvm)
 #define GUEST_PHYSICAL_RR4     0x2739
 #define VMM_INIT_RR            0x1660
 
-static void kvm_init_vm(struct kvm *kvm)
+int kvm_arch_init_vm(struct kvm *kvm)
 {
        BUG_ON(!kvm);
 
+       kvm->arch.is_sn2 = ia64_platform_is("sn2");
+
        kvm->arch.metaphysical_rr0 = GUEST_PHYSICAL_RR0;
        kvm->arch.metaphysical_rr4 = GUEST_PHYSICAL_RR4;
        kvm->arch.vmm_init_rr = VMM_INIT_RR;
@@ -823,21 +828,8 @@ static void kvm_init_vm(struct kvm *kvm)
 
        /* Reserve bit 0 of irq_sources_bitmap for userspace irq source */
        set_bit(KVM_USERSPACE_IRQ_SOURCE_ID, &kvm->arch.irq_sources_bitmap);
-}
-
-struct  kvm *kvm_arch_create_vm(void)
-{
-       struct kvm *kvm = kvm_alloc_kvm();
-
-       if (IS_ERR(kvm))
-               return ERR_PTR(-ENOMEM);
-
-       kvm->arch.is_sn2 = ia64_platform_is("sn2");
-
-       kvm_init_vm(kvm);
-
-       return kvm;
 
+       return 0;
 }
 
 static int kvm_vm_ioctl_get_irqchip(struct kvm *kvm,
@@ -962,7 +954,9 @@ long kvm_arch_vm_ioctl(struct file *filp,
                        goto out;
                r = kvm_setup_default_irq_routing(kvm);
                if (r) {
+                       mutex_lock(&kvm->slots_lock);
                        kvm_ioapic_destroy(kvm);
+                       mutex_unlock(&kvm->slots_lock);
                        goto out;
                }
                break;
@@ -1175,6 +1169,11 @@ out:
 
 #define PALE_RESET_ENTRY    0x80000000ffffffb0UL
 
+bool kvm_vcpu_compatible(struct kvm_vcpu *vcpu)
+{
+       return irqchip_in_kernel(vcpu->kcm) == (vcpu->arch.apic != NULL);
+}
+
 int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
 {
        struct kvm_vcpu *v;
@@ -1230,7 +1229,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        p_ctx->cr[2] = (unsigned long)kvm_vmm_info->vmm_ivt;
        p_ctx->cr[8] = 0x3c;
 
-       /*Initilize region register*/
+       /*Initialize region register*/
        p_ctx->rr[0] = 0x30;
        p_ctx->rr[1] = 0x30;
        p_ctx->rr[2] = 0x30;
@@ -1239,7 +1238,7 @@ int kvm_arch_vcpu_init(struct kvm_vcpu *vcpu)
        p_ctx->rr[5] = 0x30;
        p_ctx->rr[7] = 0x30;
 
-       /*Initilize branch register 0*/
+       /*Initialize branch register 0*/
        p_ctx->br[0] = *(unsigned long *)kvm_vmm_info->vmm_entry;
 
        vcpu->arch.vmm_rr = kvm->arch.vmm_init_rr;
@@ -1357,7 +1356,7 @@ int kvm_arch_vcpu_ioctl_set_guest_debug(struct kvm_vcpu *vcpu,
        return -EINVAL;
 }
 
-static void free_kvm(struct kvm *kvm)
+void kvm_arch_free_vm(struct kvm *kvm)
 {
        unsigned long vm_base = kvm->arch.vm_base;
 
@@ -1399,9 +1398,6 @@ void kvm_arch_destroy_vm(struct kvm *kvm)
 #endif
        kfree(kvm->arch.vioapic);
        kvm_release_vm_pages(kvm);
-       kvm_free_physmem(kvm);
-       cleanup_srcu_struct(&kvm->srcu);
-       free_kvm(kvm);
 }
 
 void kvm_arch_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1700,7 +1696,7 @@ static int kvm_relocate_vmm(struct kvm_vmm_info *vmm_info,
        BUG_ON(!module);
 
        if (!kvm_vmm_base) {
-               printk("kvm: kvm area hasn't been initilized yet!!\n");
+               printk("kvm: kvm area hasn't been initialized yet!!\n");
                return -EFAULT;
        }
 
@@ -1795,25 +1791,15 @@ void kvm_arch_exit(void)
        kvm_vmm_info = NULL;
 }
 
-static int kvm_ia64_sync_dirty_log(struct kvm *kvm,
-               struct kvm_dirty_log *log)
+static void kvm_ia64_sync_dirty_log(struct kvm *kvm,
+                                   struct kvm_memory_slot *memslot)
 {
-       struct kvm_memory_slot *memslot;
-       int r, i;
+       int i;
        long base;
        unsigned long n;
        unsigned long *dirty_bitmap = (unsigned long *)(kvm->arch.vm_base +
                        offsetof(struct kvm_vm_data, kvm_mem_dirty_log));
 
-       r = -EINVAL;
-       if (log->slot >= KVM_MEMORY_SLOTS)
-               goto out;
-
-       memslot = &kvm->memslots->memslots[log->slot];
-       r = -ENOENT;
-       if (!memslot->dirty_bitmap)
-               goto out;
-
        n = kvm_dirty_bitmap_bytes(memslot);
        base = memslot->base_gfn / BITS_PER_LONG;
 
@@ -1823,9 +1809,6 @@ static int kvm_ia64_sync_dirty_log(struct kvm *kvm,
                dirty_bitmap[base + i] = 0;
        }
        spin_unlock(&kvm->arch.dirty_log_lock);
-       r = 0;
-out:
-       return r;
 }
 
 int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
@@ -1838,10 +1821,16 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
 
        mutex_lock(&kvm->slots_lock);
 
-       r = kvm_ia64_sync_dirty_log(kvm, log);
-       if (r)
+       r = -EINVAL;
+       if (log->slot >= KVM_MEMORY_SLOTS)
+               goto out;
+
+       memslot = &kvm->memslots->memslots[log->slot];
+       r = -ENOENT;
+       if (!memslot->dirty_bitmap)
                goto out;
 
+       kvm_ia64_sync_dirty_log(kvm, memslot);
        r = kvm_get_dirty_log(kvm, log, &is_dirty);
        if (r)
                goto out;
@@ -1849,7 +1838,6 @@ int kvm_vm_ioctl_get_dirty_log(struct kvm *kvm,
        /* If nothing is dirty, don't bother messing with page tables. */
        if (is_dirty) {
                kvm_flush_remote_tlbs(kvm);
-               memslot = &kvm->memslots->memslots[log->slot];
                n = kvm_dirty_bitmap_bytes(memslot);
                memset(memslot->dirty_bitmap, 0, n);
        }