aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMarc Zyngier <marc.zyngier@arm.com>2013-01-31 06:25:52 -0500
committerMarc Zyngier <marc.zyngier@arm.com>2013-02-22 08:29:37 -0500
commit75da01e127f7db3b23effa6118336d303e7572a7 (patch)
treeca4f71cfc2f101609c96109eb01e9bbd651cd143 /arch
parent2ef14f465b9e096531343f5b734cffc5f759f4a6 (diff)
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')
-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 c9a17316e9fe..76ea1aa5e7d2 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)
883 lr, irq, vgic_cpu->vgic_lr[lr]); 883 lr, irq, vgic_cpu->vgic_lr[lr]);
884 BUG_ON(!test_bit(lr, vgic_cpu->lr_used)); 884 BUG_ON(!test_bit(lr, vgic_cpu->lr_used));
885 vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT; 885 vgic_cpu->vgic_lr[lr] |= GICH_LR_PENDING_BIT;
886 886 return true;
887 goto out;
888 } 887 }
889 888
890 /* Try to use another LR for this interrupt */ 889 /* 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)
898 vgic_cpu->vgic_irq_lr_map[irq] = lr; 897 vgic_cpu->vgic_irq_lr_map[irq] = lr;
899 set_bit(lr, vgic_cpu->lr_used); 898 set_bit(lr, vgic_cpu->lr_used);
900 899
901out:
902 if (!vgic_irq_is_edge(vcpu, irq)) 900 if (!vgic_irq_is_edge(vcpu, irq))
903 vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI; 901 vgic_cpu->vgic_lr[lr] |= GICH_LR_EOI;
904 902
@@ -1054,6 +1052,13 @@ static bool vgic_process_maintenance(struct kvm_vcpu *vcpu)
1054 } else { 1052 } else {
1055 vgic_cpu_irq_clear(vcpu, irq); 1053 vgic_cpu_irq_clear(vcpu, irq);
1056 } 1054 }
1055
1056 /*
1057 * Despite being EOIed, the LR may not have
1058 * been marked as empty.
1059 */
1060 set_bit(lr, (unsigned long *)vgic_cpu->vgic_elrsr);
1061 vgic_cpu->vgic_lr[lr] &= ~GICH_LR_ACTIVE_BIT;
1057 } 1062 }
1058 } 1063 }
1059 1064