]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: GICv3: Decouple ICH_HCR_EL2 programming from LRs
authorMarc Zyngier <maz@kernel.org>
Thu, 20 Nov 2025 17:25:02 +0000 (17:25 +0000)
committerOliver Upton <oupton@kernel.org>
Mon, 24 Nov 2025 22:29:12 +0000 (14:29 -0800)
Not programming ICH_HCR_EL2 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.

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

index 9bfcbfd91118a9068b0b28a6f537380ae2345db4..2509b52bbd6290ff9f75b986c2b0eca7240fd502 100644 (file)
@@ -219,20 +219,12 @@ void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if)
                }
        }
 
-       if (used_lrs || cpu_if->its_vpe.its_vm) {
+       if (used_lrs) {
                int i;
                u32 elrsr;
 
                elrsr = read_gicreg(ICH_ELRSR_EL2);
 
-               if (cpu_if->vgic_hcr & ICH_HCR_EL2_LRENPIE) {
-                       u64 val = read_gicreg(ICH_HCR_EL2);
-                       cpu_if->vgic_hcr &= ~ICH_HCR_EL2_EOIcount;
-                       cpu_if->vgic_hcr |= val & ICH_HCR_EL2_EOIcount;
-               }
-
-               write_gicreg(0, ICH_HCR_EL2);
-
                for (i = 0; i < used_lrs; i++) {
                        if (elrsr & (1 << i))
                                cpu_if->vgic_lr[i] &= ~ICH_LR_STATE;
@@ -242,6 +234,14 @@ void __vgic_v3_save_state(struct vgic_v3_cpu_if *cpu_if)
                        __gic_v3_set_lr(0, i);
                }
        }
+
+       if (cpu_if->vgic_hcr & ICH_HCR_EL2_LRENPIE) {
+               u64 val = read_gicreg(ICH_HCR_EL2);
+               cpu_if->vgic_hcr &= ~ICH_HCR_EL2_EOIcount;
+               cpu_if->vgic_hcr |= val & ICH_HCR_EL2_EOIcount;
+       }
+
+       write_gicreg(0, ICH_HCR_EL2);
 }
 
 void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if)
@@ -249,12 +249,10 @@ void __vgic_v3_restore_state(struct vgic_v3_cpu_if *cpu_if)
        u64 used_lrs = cpu_if->used_lrs;
        int i;
 
-       if (used_lrs || cpu_if->its_vpe.its_vm) {
-               write_gicreg(compute_ich_hcr(cpu_if), ICH_HCR_EL2);
+       write_gicreg(compute_ich_hcr(cpu_if), ICH_HCR_EL2);
 
-               for (i = 0; i < used_lrs; i++)
-                       __gic_v3_set_lr(cpu_if->vgic_lr[i], i);
-       }
+       for (i = 0; i < used_lrs; i++)
+               __gic_v3_set_lr(cpu_if->vgic_lr[i], i);
 
        /*
         * Ensure that writes to the LRs, and on non-VHE systems ensure that