summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2025-11-20 17:25:25 +0000
committerOliver Upton <oupton@kernel.org>2025-11-24 14:29:14 -0800
commit6dd333c8942b2e5bb5927af843b56ec2857db7c7 (patch)
tree8fcd7d0328b2aab7734061122619c5a4cab555ea
parenteb33ffa2bd3f1842d2960aff7484869fc64aa2fb (diff)
KVM: arm64: GICv3: nv: Plug L1 LR sync into deactivation primitive
Pretty much like the rest of the LR handling, deactivation of an L2 interrupt gets reflected in the L1 LRs, and therefore must be propagated into the L1 shadow state if the interrupt is HW-bound. Instead of directly handling the active state (which looks a bit off as it ignores locking and L1->L0 HW propagation), use the new deactivation primitive to perform the deactivation and deal with the required maintenance. Tested-by: Fuad Tabba <tabba@google.com> Signed-off-by: Marc Zyngier <maz@kernel.org> Tested-by: Mark Brown <broonie@kernel.org> Link: https://msgid.link/20251120172540.2267180-36-maz@kernel.org Signed-off-by: Oliver Upton <oupton@kernel.org>
-rw-r--r--arch/arm64/kvm/vgic/vgic-v3-nested.c19
1 files changed, 9 insertions, 10 deletions
diff --git a/arch/arm64/kvm/vgic/vgic-v3-nested.c b/arch/arm64/kvm/vgic/vgic-v3-nested.c
index 40f7a37e0685..15e7033a7937 100644
--- a/arch/arm64/kvm/vgic/vgic-v3-nested.c
+++ b/arch/arm64/kvm/vgic/vgic-v3-nested.c
@@ -280,7 +280,6 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
for_each_set_bit(i, &shadow_if->lr_map, kvm_vgic_global_state.nr_lr) {
u64 val, host_lr, lr;
- struct vgic_irq *irq;
host_lr = __gic_v3_get_lr(lr_map_idx_to_shadow_idx(shadow_if, i));
@@ -290,7 +289,14 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
val |= host_lr & ICH_LR_STATE;
__vcpu_assign_sys_reg(vcpu, ICH_LRN(i), val);
- if (!(lr & ICH_LR_HW) || !(lr & ICH_LR_STATE))
+ /*
+ * Deactivation of a HW interrupt: the LR must have the HW
+ * bit set, have been in a non-invalid state before the run,
+ * and now be in an invalid state. If any of that doesn't
+ * hold, we're done with this LR.
+ */
+ if (!((lr & ICH_LR_HW) && (lr & ICH_LR_STATE) &&
+ !(host_lr & ICH_LR_STATE)))
continue;
/*
@@ -298,14 +304,7 @@ void vgic_v3_sync_nested(struct kvm_vcpu *vcpu)
* need to emulate the HW effect between the guest hypervisor
* and the nested guest.
*/
- irq = vgic_get_vcpu_irq(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
- if (WARN_ON(!irq)) /* Shouldn't happen as we check on load */
- continue;
-
- if (!(host_lr & ICH_LR_STATE))
- irq->active = false;
-
- vgic_put_irq(vcpu->kvm, irq);
+ vgic_v3_deactivate(vcpu, FIELD_GET(ICH_LR_PHYS_ID_MASK, lr));
}
/* We need these to be synchronised to generate the MI */