]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: GICv3: Extract LR computing primitive
authorMarc Zyngier <maz@kernel.org>
Thu, 20 Nov 2025 17:25:04 +0000 (17:25 +0000)
committerOliver Upton <oupton@kernel.org>
Mon, 24 Nov 2025 22:29:12 +0000 (14:29 -0800)
Split vgic_v3_populate_lr() into two, so that we have another
primitive that computes the LR from a vgic_irq, but doesn't
update anything in the shadow structure.

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-15-maz@kernel.org
Signed-off-by: Oliver Upton <oupton@kernel.org>
arch/arm64/kvm/vgic/vgic-v3.c

index 6b7d7b4048f0363651e80a81fb0043a9ac166915..bcce7f35a6d678fdbba402a122f17b6daabb56d2 100644 (file)
@@ -107,7 +107,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
 }
 
 /* Requires the irq to be locked already */
-void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+static u64 vgic_v3_compute_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq)
 {
        u32 model = vcpu->kvm->arch.vgic.vgic_model;
        u64 val = irq->intid;
@@ -154,6 +154,35 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (allow_pending && irq_is_pending(irq)) {
                val |= ICH_LR_PENDING_BIT;
 
+               if (is_v2_sgi) {
+                       u32 src = ffs(irq->source);
+
+                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
+                                          irq->intid))
+                               return 0;
+
+                       val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
+                       if (irq->source & ~BIT(src - 1))
+                               val |= ICH_LR_EOI;
+               }
+       }
+
+       if (irq->group)
+               val |= ICH_LR_GROUP;
+
+       val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
+
+       return val;
+}
+
+void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
+{
+       u32 model = vcpu->kvm->arch.vgic.vgic_model;
+       u64 val = vgic_v3_compute_lr(vcpu, irq);
+
+       vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
+
+       if (val & ICH_LR_PENDING_BIT) {
                if (irq->config == VGIC_CONFIG_EDGE)
                        irq->pending_latch = false;
 
@@ -161,16 +190,9 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
                    model == KVM_DEV_TYPE_ARM_VGIC_V2) {
                        u32 src = ffs(irq->source);
 
-                       if (WARN_RATELIMIT(!src, "No SGI source for INTID %d\n",
-                                          irq->intid))
-                               return;
-
-                       val |= (src - 1) << GICH_LR_PHYSID_CPUID_SHIFT;
-                       irq->source &= ~(1 << (src - 1));
-                       if (irq->source) {
+                       irq->source &= ~BIT(src - 1);
+                       if (irq->source)
                                irq->pending_latch = true;
-                               val |= ICH_LR_EOI;
-                       }
                }
        }
 
@@ -183,13 +205,6 @@ void vgic_v3_populate_lr(struct kvm_vcpu *vcpu, struct vgic_irq *irq, int lr)
        if (vgic_irq_is_mapped_level(irq) && (val & ICH_LR_PENDING_BIT))
                irq->line_level = false;
 
-       if (irq->group)
-               val |= ICH_LR_GROUP;
-
-       val |= (u64)irq->priority << ICH_LR_PRIORITY_SHIFT;
-
-       vcpu->arch.vgic_cpu.vgic_v3.vgic_lr[lr] = val;
-
        irq->on_lr = true;
 }