]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: GICv2: Decouple GICH_HCR programming from LRs being loaded
authorMarc Zyngier <maz@kernel.org>
Thu, 20 Nov 2025 17:25:06 +0000 (17:25 +0000)
committerOliver Upton <oupton@kernel.org>
Mon, 24 Nov 2025 22:29:12 +0000 (14:29 -0800)
Not programming GICH_HCR while no LRs are populated is a bit
of an issue, as we otherwise don't see any maintenance interrupt
when the guest interacts with the LRs.

Decouple the two and always program the control register, even when
we don't have to touch the LRs.

This is very similar to what we are already doing for GICv3.

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

index 5cfbe58983428f917fe6058d070ffe3703b5fc39..a0d803c5b08ae859a5e001e8009950a5f6ef5cc6 100644 (file)
@@ -430,22 +430,25 @@ static void save_lrs(struct kvm_vcpu *vcpu, void __iomem *base)
 
 void vgic_v2_save_state(struct kvm_vcpu *vcpu)
 {
+       struct vgic_v2_cpu_if *cpu_if = &vcpu->arch.vgic_cpu.vgic_v2;
        void __iomem *base = kvm_vgic_global_state.vctrl_base;
        u64 used_lrs = vcpu->arch.vgic_cpu.vgic_v2.used_lrs;
 
        if (!base)
                return;
 
-       if (used_lrs) {
-               if (vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr & GICH_HCR_LRENPIE) {
-                       u32 val = readl_relaxed(base + GICH_HCR);
 
-                       vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr &= ~GICH_HCR_EOICOUNT;
-                       vcpu->arch.vgic_cpu.vgic_v2.vgic_hcr |= val & GICH_HCR_EOICOUNT;
-               }
+       if (used_lrs)
                save_lrs(vcpu, base);
-               writel_relaxed(0, base + GICH_HCR);
+
+       if (cpu_if->vgic_hcr & GICH_HCR_LRENPIE) {
+               u32 val = readl_relaxed(base + GICH_HCR);
+
+               cpu_if->vgic_hcr &= ~GICH_HCR_EOICOUNT;
+               cpu_if->vgic_hcr |= val & GICH_HCR_EOICOUNT;
        }
+
+       writel_relaxed(0, base + GICH_HCR);
 }
 
 void vgic_v2_restore_state(struct kvm_vcpu *vcpu)
@@ -458,13 +461,10 @@ void vgic_v2_restore_state(struct kvm_vcpu *vcpu)
        if (!base)
                return;
 
-       if (used_lrs) {
-               writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
-               for (i = 0; i < used_lrs; i++) {
-                       writel_relaxed(cpu_if->vgic_lr[i],
-                                      base + GICH_LR0 + (i * 4));
-               }
-       }
+       writel_relaxed(cpu_if->vgic_hcr, base + GICH_HCR);
+
+       for (i = 0; i < used_lrs; i++)
+               writel_relaxed(cpu_if->vgic_lr[i], base + GICH_LR0 + (i * 4));
 }
 
 void vgic_v2_load(struct kvm_vcpu *vcpu)