diff options
author | Pavel Fedin <p.fedin@samsung.com> | 2015-09-25 10:00:29 -0400 |
---|---|---|
committer | Christoffer Dall <christoffer.dall@linaro.org> | 2015-10-20 12:04:43 -0400 |
commit | 437f9963bc4fd75889c1fe9289a92dea9124a439 (patch) | |
tree | b91113c13849796b8cee1b57094f2d0f99eb3857 /virt | |
parent | 920552b213e3dc832a874b4e7ba29ecddbab31bc (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.c | 9 |
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; |