summaryrefslogtreecommitdiff
path: root/arch/arm/kvm/vgic.c
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2013-01-31 11:25:52 (GMT)
committerMarc Zyngier <marc.zyngier@arm.com>2013-02-22 13:29:37 (GMT)
commit75da01e127f7db3b23effa6118336d303e7572a7 (patch)
treeca4f71cfc2f101609c96109eb01e9bbd651cd143 /arch/arm/kvm/vgic.c
parent2ef14f465b9e096531343f5b734cffc5f759f4a6 (diff)
downloadlinux-75da01e127f7db3b23effa6118336d303e7572a7.tar.xz
ARM: KVM: vgic: force EOIed LRs to the empty state
The VGIC doesn't guarantee that an EOIed LR that has been configured to generate a maintenance interrupt will appear as empty. While the code recovers from this situation, it is better to clean the LR and flag it as empty so it can be quickly recycled. Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Diffstat (limited to 'arch/arm/kvm/vgic.c')
-rw-r--r--arch/arm/kvm/vgic.c11
1 files changed, 8 insertions, 3 deletions
diff --git a/arch/arm/kvm/vgic.c b/arch/arm/kvm/vgic.c
index c9a1731..76ea1aa 100644
--- a/arch/arm/kvm/vgic.c
+++ b/arch/arm/kvm/vgic.c
@@ -883,8 +883,7 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
lr, irq, vgic_cpu->vgic_lr[lr]);
BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
-
- goto out;
+ return true;
}
/* Try to use another LR for this interrupt */
@@ -898,7 +897,6 @@ static bool vgic_queue_irq(struct kvm_vcpu *vcpu, u8 sgi_source_id, int irq)
vgic_cpu->vgic_irq_lr_map[irq] = lr;
set_bit(lr, vgic_cpu->lr_used);
-out:
if (!vgic_irq_is_edge(vcpu, irq))
vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
@@ -1054,6 +1052,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
} else {
vgic_cpu_irq_clear(vcpu, irq);
}
+
+ /*
+ * Despite being EOIed, the LR may not have
+ * been marked as empty.
+ */
+ set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
+ vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
}
}