summaryrefslogtreecommitdiff
path: root/virt/kvm/arm
diff options
context:
space:
mode:
Diffstat (limited to 'virt/kvm/arm')
-rw-r--r--virt/kvm/arm/hyp/vgic-v2-sr.c7
-rw-r--r--virt/kvm/arm/vgic/vgic-mmio.c4
-rw-r--r--virt/kvm/arm/vgic/vgic-v2.c14
-rw-r--r--virt/kvm/arm/vgic/vgic-v3.c14
4 files changed, 22 insertions, 17 deletions
diff --git a/virt/kvm/arm/hyp/vgic-v2-sr.c b/virt/kvm/arm/hyp/vgic-v2-sr.c
index a3f12b3b277b..3a3a699b7489 100644
--- a/virt/kvm/arm/hyp/vgic-v2-sr.c
+++ b/virt/kvm/arm/hyp/vgic-v2-sr.c
@@ -100,12 +100,11 @@ static void __hyp_text save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
if (!(vcpu->arch.vgic_cpu.live_lrs & (1UL << i)))
continue;
- if (cpu_if->vgic_elrsr & (1UL << i)) {
+ if (cpu_if->vgic_elrsr & (1UL << i))
cpu_if->vgic_lr[i] &= ~GICH_LR_STATE;
- continue;
- }
+ else
+ cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
- cpu_if->vgic_lr[i] = readl_relaxed(base + GICH_LR0 + (i * 4));
writel_relaxed(0, base + GICH_LR0 + (i * 4));
}
}
diff --git a/virt/kvm/arm/vgic/vgic-mmio.c b/virt/kvm/arm/vgic/vgic-mmio.c
index 059595ec3da0..9f6fab74dce7 100644
--- a/virt/kvm/arm/vgic/vgic-mmio.c
+++ b/virt/kvm/arm/vgic/vgic-mmio.c
@@ -191,10 +191,8 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
* other thread sync back the IRQ.
*/
while (irq->vcpu && /* IRQ may have state in an LR somewhere */
- irq->vcpu->cpu != -1) { /* VCPU thread is running */
- BUG_ON(irq->intid < VGIC_NR_PRIVATE_IRQS);
+ irq->vcpu->cpu != -1) /* VCPU thread is running */
cond_resched_lock(&irq->irq_lock);
- }
irq->active = new_active_state;
if (new_active_state)
diff --git a/virt/kvm/arm/vgic/vgic-v2.c b/virt/kvm/arm/vgic/vgic-v2.c
index 8ad42c217770..e31405ee5515 100644
--- a/virt/kvm/arm/vgic/vgic-v2.c
+++ b/virt/kvm/arm/vgic/vgic-v2.c
@@ -112,11 +112,15 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
}
}
- /* Clear soft pending state when level IRQs have been acked */
- if (irq->config == VGIC_CONFIG_LEVEL &&
- !(val & GICH_LR_PENDING_BIT)) {
- irq->soft_pending = false;
- irq->pending = irq->line_level;
+ /*
+ * Clear soft pending state when level irqs have been acked.
+ * Always regenerate the pending state.
+ */
+ if (irq->config == VGIC_CONFIG_LEVEL) {
+ if (!(val & GICH_LR_PENDING_BIT))
+ irq->soft_pending = false;
+
+ irq->pending = irq->line_level || irq->soft_pending;
}
spin_unlock(&irq->irq_lock);
diff --git a/virt/kvm/arm/vgic/vgic-v3.c b/virt/kvm/arm/vgic/vgic-v3.c
index 336a46115937..346b4ad12b49 100644
--- a/virt/kvm/arm/vgic/vgic-v3.c
+++ b/virt/kvm/arm/vgic/vgic-v3.c
@@ -101,11 +101,15 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
}
}
- /* Clear soft pending state when level irqs have been acked */
- if (irq->config == VGIC_CONFIG_LEVEL &&
- !(val & ICH_LR_PENDING_BIT)) {
- irq->soft_pending = false;
- irq->pending = irq->line_level;
+ /*
+ * Clear soft pending state when level irqs have been acked.
+ * Always regenerate the pending state.
+ */
+ if (irq->config == VGIC_CONFIG_LEVEL) {
+ if (!(val & ICH_LR_PENDING_BIT))
+ irq->soft_pending = false;
+
+ irq->pending = irq->line_level || irq->soft_pending;
}
spin_unlock(&irq->irq_lock);