summaryrefslogtreecommitdiffstats
path: root/virt/kvm/arm/vgic/vgic-mmio.c
diff options
context:
space:
mode:
authorPaolo Bonzini2019-08-09 16:53:50 +0200
committerPaolo Bonzini2019-08-09 16:53:50 +0200
commita738b5e75b4c13be3485c82eb62c30047aa9f164 (patch)
treef47fca53ee79938be283e13cf5d48def68f9dad2 /virt/kvm/arm/vgic/vgic-mmio.c
parentMerge tag 'kvmarm-fixes-for-5.3' of git://git.kernel.org/pub/scm/linux/kernel... (diff)
parentKVM: arm/arm64: vgic: Reevaluate level sensitive interrupts on enable (diff)
downloadkernel-qcow2-linux-a738b5e75b4c13be3485c82eb62c30047aa9f164.tar.gz
kernel-qcow2-linux-a738b5e75b4c13be3485c82eb62c30047aa9f164.tar.xz
kernel-qcow2-linux-a738b5e75b4c13be3485c82eb62c30047aa9f164.zip
Merge tag 'kvmarm-fixes-for-5.3-2' of git://git.kernel.org/pub/scm/linux/kernel/git/kvmarm/kvmarm into HEAD
KVM/arm fixes for 5.3, take #2 - Fix our system register reset so that we stop writing non-sensical values to them, and track which registers get reset instead. - Sync VMCR back from the GIC on WFI so that KVM has an exact vue of PMR. - Reevaluate state of HW-mapped, level triggered interrupts on enable.
Diffstat (limited to 'virt/kvm/arm/vgic/vgic-mmio.c')
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 3ba7278fb533..44efc2ff863f 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -113,6 +113,22 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
raw_spin_lock_irqsave(&irq->irq_lock, flags);
+ if (vgic_irq_is_mapped_level(irq)) {
+ bool was_high = irq->line_level;
+
+ /*
+ * We need to update the state of the interrupt because
+ * the guest might have changed the state of the device
+ * while the interrupt was disabled at the VGIC level.
+ */
+ irq->line_level = vgic_get_phys_line_level(irq);
+ /*
+ * Deactivate the physical interrupt so the GIC will let
+ * us know when it is asserted again.
+ */
+ if (!irq->active && was_high && !irq->line_level)
+ vgic_irq_set_phys_active(irq, false);
+ }
irq->enabled = true;
vgic_queue_irq_unlock(vcpu->kvm, irq, flags);