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;
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)
goto out;
}
- ret = vgic_register_redist_iodevs(kvm, dist->vgic_redist_base);
- 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: