KVM: arm/arm64: vgic-v3: Do not use Active+Pending state for a HW interrupt
authorMarc Zyngier <marc.zyngier@arm.com>
Tue, 2 May 2017 13:30:40 +0000 (14:30 +0100)
committerChristoffer Dall <cdall@linaro.org>
Mon, 15 May 2017 09:31:51 +0000 (11:31 +0200)
When an interrupt is injected with the HW bit set (indicating that
deactivation should be propagated to the physical distributor),
special care must be taken so that we never mark the corresponding
LR with the Active+Pending state (as the pending state is kept in
the physycal distributor).

Cc: stable@vger.kernel.org
Fixes: 59529f69f504 ("KVM: arm/arm64: vgic-new: Add GICv3 world switch backend")
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Reviewed-by: Christoffer Dall <cdall@linaro.org>
Signed-off-by: Christoffer Dall <cdall@linaro.org>
virt/kvm/arm/vgic/vgic-v3.c

index 8fa737edde6f2f9458fc0a6a33faa4c8c9fa810e..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;