]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: vgic-v5: Hold config_lock while finalizing GICv5 PPIs
authorMarc Zyngier <maz@kernel.org>
Wed, 1 Apr 2026 10:36:01 +0000 (11:36 +0100)
committerMarc Zyngier <maz@kernel.org>
Wed, 1 Apr 2026 14:42:26 +0000 (15:42 +0100)
Finalizing the PPI state is done without holding any lock, which
means that two vcpus can race against each other and have one zeroing
the state while another one is setting it, or even maybe using it.

Fixing this is done by:

- holding the config lock while performing the initialisation

- checking if SW_PPI has already been advertised, meaning that
  we have already completed the initialisation once

Reviewed-by: Sascha Bischoff <sascha.bischoff@arm.com>
Fixes: 8f1fbe2fd2792 ("KVM: arm64: gic-v5: Finalize GICv5 PPIs and generate mask")
Link: https://sashiko.dev/#/patchset/20260319154937.3619520-1-sascha.bischoff%40arm.com
Link: https://patch.msgid.link/20260401103611.357092-7-maz@kernel.org
Signed-off-by: Marc Zyngier <maz@kernel.org>
arch/arm64/kvm/vgic/vgic-v5.c

index 2b6cd5c3f9c2fbee34edf7341d036613f64abaf7..119d7d01d0e773872d1ea0d878608043fd8d81c7 100644 (file)
@@ -172,6 +172,16 @@ int vgic_v5_finalize_ppi_state(struct kvm *kvm)
        if (!vgic_is_v5(kvm))
                return 0;
 
+       guard(mutex)(&kvm->arch.config_lock);
+
+       /*
+        * If SW_PPI has been advertised, then we know we already
+        * initialised the whole thing, and we can return early. Yes,
+        * this is pretty hackish as far as state tracking goes...
+        */
+       if (test_bit(GICV5_ARCH_PPI_SW_PPI, kvm->arch.vgic.gicv5_vm.vgic_ppi_mask))
+               return 0;
+
        /* The PPI state for all VCPUs should be the same. Pick the first. */
        vcpu0 = kvm_get_vcpu(kvm, 0);