]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - virt/kvm/arm/vgic/vgic-v3.c
Merge branch 'i2c/for-current' of git://git.kernel.org/pub/scm/linux/kernel/git/wsa...
[karo-tx-linux.git] / virt / kvm / arm / vgic / vgic-v3.c
index 12e52a06e14691eddb925eccc144a9d04c596654..6fe3f003636a311d055581ee6a8133d0951fd3f2 100644 (file)
@@ -127,6 +127,13 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (irq->hw) {
                val |= ICH_LR_HW;
                val |= ((u64)irq->hwintid) << ICH_LR_PHYS_ID_SHIFT;
+               /*
+                * Never set pending+active on a HW interrupt, as the
+                * pending state is kept at the physical distributor
+                * level.
+                */
+               if (irq->active && irq_is_pending(irq))
+                       val &= ~ICH_LR_PENDING_BIT;
        } else {
                if (irq->config == VGIC_CONFIG_LEVEL)
                        val |= ICH_LR_EOI;
@@ -329,19 +336,30 @@ int vgic_v3_save_pending_tables(struct kvm *kvm)
        return 0;
 }
 
-/* check for overlapping regions and for regions crossing the end of memory */
-static bool vgic_v3_check_base(struct kvm *kvm)
+/*
+ * Check for overlapping regions and for regions crossing the end of memory
+ * for base addresses which have already been set.
+ */
+bool vgic_v3_check_base(struct kvm *kvm)
 {
        struct vgic_dist *d = &kvm->arch.vgic;
        gpa_t redist_size = KVM_VGIC_V3_REDIST_SIZE;
 
        redist_size *= atomic_read(&kvm->online_vcpus);
 
-       if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
+       if (!IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) &&
+           d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE < d->vgic_dist_base)
                return false;
-       if (d->vgic_redist_base + redist_size < d->vgic_redist_base)
+
+       if (!IS_VGIC_ADDR_UNDEF(d->vgic_redist_base) &&
+           d->vgic_redist_base + redist_size < d->vgic_redist_base)
                return false;
 
+       /* Both base addresses must be set to check if they overlap */
+       if (IS_VGIC_ADDR_UNDEF(d->vgic_dist_base) ||
+           IS_VGIC_ADDR_UNDEF(d->vgic_redist_base))
+               return true;
+
        if (d->vgic_dist_base + KVM_VGIC_V3_DIST_SIZE <= d->vgic_redist_base)
                return true;
        if (d->vgic_redist_base + redist_size <= d->vgic_dist_base)
@@ -386,20 +404,6 @@ int vgic_v3_map_resources(struct kvm *kvm)
                goto out;
        }
 
-       ret = vgic_register_redist_iodevs(kvm);
-       if (ret) {
-               kvm_err("Unable to register VGICv3 redist MMIO regions\n");
-               goto out;
-       }
-
-       if (vgic_has_its(kvm)) {
-               ret = vgic_register_its_iodevs(kvm);
-               if (ret) {
-                       kvm_err("Unable to register VGIC ITS MMIO regions\n");
-                       goto out;
-               }
-       }
-
        dist->ready = true;
 
 out: