aboutsummaryrefslogtreecommitdiffstats
path: root/virt
diff options
context:
space:
mode:
authorPavel Fedin <p.fedin@samsung.com>2015-09-25 10:00:29 -0400
committerChristoffer Dall <christoffer.dall@linaro.org>2015-10-20 12:04:43 -0400
commit437f9963bc4fd75889c1fe9289a92dea9124a439 (patch)
treeb91113c13849796b8cee1b57094f2d0f99eb3857 /virt
parent920552b213e3dc832a874b4e7ba29ecddbab31bc (diff)
KVM: arm/arm64: Do not inject spurious interrupts
When lowering a level-triggered line from userspace, we forgot to lower the pending bit on the emulated CPU interface and we also did not re-compute the pending_on_cpu bitmap for the CPU affected by the change. Update vgic_update_irq_pending() to fix the two issues above and also raise a warning in vgic_quue_irq_to_lr if we encounter an interrupt pending on a CPU which is neither marked active nor pending. [ Commit text reworked completely - Christoffer ] Signed-off-by: Pavel Fedin <p.fedin@samsung.com> Signed-off-by: Christoffer Dall <christoffer.dall@linaro.org>
Diffstat (limited to 'virt')
-rw-r--r--virt/kvm/arm/vgic.c9
1 files changed, 7 insertions, 2 deletions
diff --git a/virt/kvm/arm/vgic.c b/virt/kvm/arm/vgic.c
index 6bd1c9bf7ae7..596455a394af 100644
--- a/virt/kvm/arm/vgic.c
+++ b/virt/kvm/arm/vgic.c
@@ -1132,7 +1132,8 @@ static void vgic_queue_irq_to_lr(struct kvm_vcpu *vcpu, int irq,
1132 kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state); 1132 kvm_debug("Set active, clear distributor: 0x%x\n", vlr.state);
1133 vgic_irq_clear_active(vcpu, irq); 1133 vgic_irq_clear_active(vcpu, irq);
1134 vgic_update_state(vcpu->kvm); 1134 vgic_update_state(vcpu->kvm);
1135 } else if (vgic_dist_irq_is_pending(vcpu, irq)) { 1135 } else {
1136 WARN_ON(!vgic_dist_irq_is_pending(vcpu, irq));
1136 vlr.state |= LR_STATE_PENDING; 1137 vlr.state |= LR_STATE_PENDING;
1137 kvm_debug("Set pending: 0x%x\n", vlr.state); 1138 kvm_debug("Set pending: 0x%x\n", vlr.state);
1138 } 1139 }
@@ -1607,8 +1608,12 @@ static int vgic_update_irq_pending(struct kvm *kvm, int cpuid,
1607 } else { 1608 } else {
1608 if (level_triggered) { 1609 if (level_triggered) {
1609 vgic_dist_irq_clear_level(vcpu, irq_num); 1610 vgic_dist_irq_clear_level(vcpu, irq_num);
1610 if (!vgic_dist_irq_soft_pend(vcpu, irq_num)) 1611 if (!vgic_dist_irq_soft_pend(vcpu, irq_num)) {
1611 vgic_dist_irq_clear_pending(vcpu, irq_num); 1612 vgic_dist_irq_clear_pending(vcpu, irq_num);
1613 vgic_cpu_irq_clear(vcpu, irq_num);
1614 if (!compute_pending_for_cpu(vcpu))
1615 clear_bit(cpuid, dist->irq_pending_on_cpu);
1616 }
1612 } 1617 }
1613 1618
1614 ret = false; 1619 ret = false;