]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
KVM: arm64: Disambiguate support for vSGIs v. vLPIs
authorOliver Upton <oliver.upton@linux.dev>
Thu, 24 Jul 2025 06:28:00 +0000 (23:28 -0700)
committerOliver Upton <oliver.upton@linux.dev>
Sat, 26 Jul 2025 15:37:45 +0000 (08:37 -0700)
vgic_supports_direct_msis() is a bit of a misnomer, as it returns true
if either vSGIs or vLPIs are supported. Pick it apart into a few
predicates and replace some open-coded checks for vSGIs, including an
opportunistic fix to always check if the CPUIF is capable of handling
vSGIs.

Reviewed-by: Marc Zyngier <maz@kernel.org>
Link: https://lore.kernel.org/r/20250724062805.2658919-2-oliver.upton@linux.dev
Signed-off-by: Oliver Upton <oliver.upton@linux.dev>
arch/arm64/kvm/vgic/vgic-init.c
arch/arm64/kvm/vgic/vgic-mmio-v3.c
arch/arm64/kvm/vgic/vgic-v4.c
arch/arm64/kvm/vgic/vgic.c
arch/arm64/kvm/vgic/vgic.h

index eb1205654ac890709cd1c990077b920f7c9de770..0d8bc2ac627a2b642414159c007a79de7cc640ba 100644 (file)
@@ -391,11 +391,10 @@ int vgic_init(struct kvm *kvm)
                goto out;
 
        /*
-        * If we have GICv4.1 enabled, unconditionally request enable the
-        * v4 support so that we get HW-accelerated vSGIs. Otherwise, only
-        * enable it if we present a virtual ITS to the guest.
+        * Ensure vPEs are allocated if direct IRQ injection (e.g. vSGIs,
+        * vLPIs) is supported.
         */
-       if (vgic_supports_direct_msis(kvm)) {
+       if (vgic_supports_direct_irqs(kvm)) {
                ret = vgic_v4_init(kvm);
                if (ret)
                        goto out;
@@ -443,7 +442,7 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
                dist->vgic_cpu_base = VGIC_ADDR_UNDEF;
        }
 
-       if (vgic_supports_direct_msis(kvm))
+       if (vgic_supports_direct_irqs(kvm))
                vgic_v4_teardown(kvm);
 
        xa_destroy(&dist->lpi_xa);
index ae4c0593d11455f395761d1fcb108cc23ce1fdd0..8f0f460b6a615e674435617b7780e4d9e706d7a4 100644 (file)
@@ -50,8 +50,12 @@ bool vgic_has_its(struct kvm *kvm)
 
 bool vgic_supports_direct_msis(struct kvm *kvm)
 {
-       return (kvm_vgic_global_state.has_gicv4_1 ||
-               (kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm)));
+       return kvm_vgic_global_state.has_gicv4 && vgic_has_its(kvm);
+}
+
+bool vgic_supports_direct_sgis(struct kvm *kvm)
+{
+       return kvm_vgic_global_state.has_gicv4_1 && gic_cpuif_has_vsgi();
 }
 
 /*
@@ -86,7 +90,7 @@ static unsigned long vgic_mmio_read_v3_misc(struct kvm_vcpu *vcpu,
                }
                break;
        case GICD_TYPER2:
-               if (kvm_vgic_global_state.has_gicv4_1 && gic_cpuif_has_vsgi())
+               if (vgic_supports_direct_sgis(vcpu->kvm))
                        value = GICD_TYPER2_nASSGIcap;
                break;
        case GICD_IIDR:
@@ -119,7 +123,7 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
                dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
 
                /* Not a GICv4.1? No HW SGIs */
-               if (!kvm_vgic_global_state.has_gicv4_1 || !gic_cpuif_has_vsgi())
+               if (!vgic_supports_direct_sgis(vcpu->kvm))
                        val &= ~GICD_CTLR_nASSGIreq;
 
                /* Dist stays enabled? nASSGIreq is RO */
@@ -133,7 +137,7 @@ static void vgic_mmio_write_v3_misc(struct kvm_vcpu *vcpu,
                if (is_hwsgi != dist->nassgireq)
                        vgic_v4_configure_vsgis(vcpu->kvm);
 
-               if (kvm_vgic_global_state.has_gicv4_1 &&
+               if (vgic_supports_direct_sgis(vcpu->kvm) &&
                    was_enabled != dist->enabled)
                        kvm_make_all_cpus_request(vcpu->kvm, KVM_REQ_RELOAD_GICv4);
                else if (!was_enabled && dist->enabled)
@@ -178,7 +182,7 @@ static int vgic_mmio_uaccess_write_v3_misc(struct kvm_vcpu *vcpu,
                }
        case GICD_CTLR:
                /* Not a GICv4.1? No HW SGIs */
-               if (!kvm_vgic_global_state.has_gicv4_1)
+               if (!vgic_supports_direct_sgis(vcpu->kvm))
                        val &= ~GICD_CTLR_nASSGIreq;
 
                dist->enabled = val & GICD_CTLR_ENABLE_SS_G1;
index 1939461081923f3e7d9735e5f043a50c24d967e0..e7e284d47a7781c24ea0aca4acbb113a86e444e9 100644 (file)
@@ -356,7 +356,7 @@ int vgic_v4_put(struct kvm_vcpu *vcpu)
 {
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
 
-       if (!vgic_supports_direct_msis(vcpu->kvm) || !vpe->resident)
+       if (!vgic_supports_direct_irqs(vcpu->kvm) || !vpe->resident)
                return 0;
 
        return its_make_vpe_non_resident(vpe, vgic_v4_want_doorbell(vcpu));
@@ -367,7 +367,7 @@ int vgic_v4_load(struct kvm_vcpu *vcpu)
        struct its_vpe *vpe = &vcpu->arch.vgic_cpu.vgic_v3.its_vpe;
        int err;
 
-       if (!vgic_supports_direct_msis(vcpu->kvm) || vpe->resident)
+       if (!vgic_supports_direct_irqs(vcpu->kvm) || vpe->resident)
                return 0;
 
        if (vcpu_get_flag(vcpu, IN_WFI))
index 8f8096d489252f7e67e985e126eb7af67a7176e9..f5148b38120ad7859dac51bb30ff2dd166d7e246 100644 (file)
@@ -951,7 +951,7 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
         * can be directly injected (GICv4).
         */
        if (list_empty(&vcpu->arch.vgic_cpu.ap_list_head) &&
-           !vgic_supports_direct_msis(vcpu->kvm))
+           !vgic_supports_direct_irqs(vcpu->kvm))
                return;
 
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
@@ -965,7 +965,7 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
        if (can_access_vgic_from_kernel())
                vgic_restore_state(vcpu);
 
-       if (vgic_supports_direct_msis(vcpu->kvm))
+       if (vgic_supports_direct_irqs(vcpu->kvm))
                vgic_v4_commit(vcpu);
 }
 
index 4349084cb9a6c891d122b624c8898391531115ba..ebf9ed6adeac1df3eee6ea1ee2a6c5cb8055f773 100644 (file)
@@ -370,6 +370,13 @@ int vgic_its_inv_lpi(struct kvm *kvm, struct vgic_irq *irq);
 int vgic_its_invall(struct kvm_vcpu *vcpu);
 
 bool vgic_supports_direct_msis(struct kvm *kvm);
+bool vgic_supports_direct_sgis(struct kvm *kvm);
+
+static inline bool vgic_supports_direct_irqs(struct kvm *kvm)
+{
+       return vgic_supports_direct_msis(kvm) || vgic_supports_direct_sgis(kvm);
+}
+
 int vgic_v4_init(struct kvm *kvm);
 void vgic_v4_teardown(struct kvm *kvm);
 void vgic_v4_configure_vsgis(struct kvm *kvm);