From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=100.103.45.18 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794064967; b=UmWqmx7uw9HrePkSzg1eOWK2Ab0J4yHYa2ewi0L3julgUBgFhztfpamaEkIYtBxqmeyZ xdLhPuPv4no55g+UtogAj4uI2W/z2PaLxKmM8g0ixrYhhDunpdBhzWD7wmMP7At1So1hH jLCC72OhLozzSaQQHEunK3JobHl2qT5Xjnx4ifpFulI1hyPSwIUQ7X8lQaBuAE7S1dQS9 Gk6YHuPWsevAjF4UUgZYIziDVP8E6vpGLSOcq/z8sH6xkhblkkf8C1/qNAoANQxkqHw5I bYmIdmwWapejKvtmc8EmmuTDZCBKt09jh8MsR/nvkXJ2Y1Ys3vdLwTtEAROEm8nrn1A== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794064967; h=Received:DKIM-Signature:From:To:Cc:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:User-Agent:X-stable:X-Patchwork-Hint: MIME-Version:Content-Transfer-Encoding; bh=xSymAFCT/hauWCkW4B3CCowvSywFGT3GKNqfCQyS/+I=; b=aNG4UbFWWooFNW1fmHAlAqM1V8I9NuKRtR4YvszlhLTSNUirl4Ppi+eN+qHFAEZLHkh8 ebhMS8M7x0VcGwlqf3vY4GB9vGyAMW+D8V9VtMao9ic31AGqNvmtD2fbkpdgIA56SoBul tOu24CeWVIDQO5exKEmWo29UzpzMJWN9Oz9mBt9i254py3JosCGS3ivk6kw+lE3fykUHv D9WgGDdhard8yg1A0hpfulYK0Vl+ZuL7IO6YsrGj/I6K5dIGjHcVQsNOGiMX7j86eQ3fx cHSDDOOOsNEFfq2Zy0FyIK+n5pbPMtio5/gfFQZd1K/r5xDNAm2TIpOIgqTqQ1VRfIQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dkim=pass header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=dWPWpVFR; arc=none smtp.remote-ip=100.103.45.18 Received: from smtp.kernel.org (quasi.space.kernel.org [100.103.45.18]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0DA76606A334; Sat, 7 Nov 2026 15:22:46 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linuxfoundation.org header.i=@linuxfoundation.org header.a=rsa-sha256 header.s=korg header.b=dWPWpVFR Received: by smtp.kernel.org (Postfix) with ESMTPSA id 68B7E1F0089F; Sat, 7 Nov 2026 15:22:46 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linuxfoundation.org; s=korg; t=1794064966; bh=xSymAFCT/hauWCkW4B3CCowvSywFGT3GKNqfCQyS/+I=; h=From:To:Cc:Subject:Date:In-Reply-To:References; b=dWPWpVFRxHgXoi1eiFLleSU98T5AMkfq5Skbr9gCrFpuKz5/z0UfgBG1mEYctfiTG IwTiisauSrqFm0beY9vrpdVuebAAQzOcAL3/9+tCrw3hIFa4pcZtu4jlo05XOSfF6s oBRLT1k4WNjZQo4576mqBTBYzMBaXS+UndrbmSG8= From: Greg Kroah-Hartman To: stable@vger.kernel.org Cc: Greg Kroah-Hartman , patches@lists.linux.dev, Marc Zyngier , Fuad Tabba , Oliver Upton , Sasha Levin Subject: [PATCH 7.3 0849/1257] KVM: arm64: vgic-its: Dont map an LPI from more than one event Date: Sat, 7 Nov 2026 08:52:25 -0500 Message-ID: <20261107135002.775202909@linuxfoundation.org> X-Mailer: git-send-email 2.56.0 In-Reply-To: <20261107134939.434104957@linuxfoundation.org> References: <20261107134939.434104957@linuxfoundation.org> User-Agent: quilt/0.69 X-stable: review X-Patchwork-Hint: ignore X-Mailing-List: patches@lists.linux.dev List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 Content-Transfer-Encoding: 8bit 7.3-stable review patch. If anyone has any objections, please let me know. ------------------ From: Fuad Tabba [ Upstream commit de81b28f0b83b22163d7d9a9b708d7aa912e0ef7 ] KVM keeps one vgic_irq per LPI. A MAPTI of an LPI whose vgic_irq already exists reuses it for the new ITE and leaves its target vCPU as it was. Mapping one LPI from two events is UNPREDICTABLE (IHI 0069H.b, 5.2.10), but nothing stops a guest from doing it. If the first MAPTI names a collection the guest never maps and the second a mapped one, the LPI translates through the second event with a NULL target vCPU. When the VMM routes an assigned device's MSI to that event on a host with GICv4 enabled, kvm_vgic_v4_set_forwarding() takes the vPE from the NULL target vCPU and the host oopses: Unable to handle kernel paging request at virtual address 0000000000001980 [...] Call trace: its_build_vmapti_cmd (drivers/irqchip/irq-gic-v3-its.c:943) (P) its_irq_set_vcpu_affinity (drivers/irqchip/irq-gic-v3-its.c:1380) irq_set_vcpu_affinity (kernel/irq/manage.c:670) its_map_vlpi (drivers/irqchip/irq-gic-v4.c:326) kvm_vgic_v4_set_forwarding (arch/arm64/kvm/vgic/vgic-v4.c:485) kvm_arch_irq_bypass_add_producer (arch/arm64/kvm/arm.c:2977) irq_bypass_register_consumer (virt/lib/irqbypass.c:44) kvm_irqfd (arch/arm64/kvm/../../../virt/kvm/eventfd.c:496) kvm_vm_ioctl (arch/arm64/kvm/../../../virt/kvm/kvm_main.c:5270) Track in each vgic_irq whether an ITE maps it. Drop a MAPTI of an LPI that is already mapped, as a failed MAPTI already is. Restoring the ITS tables keeps the first ITE it reads for each LPI and drops any later one, so a guest saved with a double mapping still restores. Key the check on the mapping, not on the vgic_irq. A vgic_irq outlives its ITE while anything holds a reference to it, such as the vCPU it was last queued on. A later MAPTI of such an LPI succeeds as before, and now retargets it to its collection. Fixes: 196b136498b35 ("KVM: arm/arm64: GICv4: Wire mapping/unmapping of VLPIs in VFIO irq bypass") Suggested-by: Marc Zyngier Cc: stable@vger.kernel.org Signed-off-by: Fuad Tabba Reviewed-by: Oliver Upton Link: https://patch.msgid.link/20261013081646.933312-2-fuad.tabba@linux.dev Signed-off-by: Marc Zyngier Signed-off-by: Sasha Levin --- arch/arm64/kvm/vgic/vgic-its.c | 26 ++++++++++++++++++++++++-- include/kvm/arm_vgic.h | 1 + 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index c10a11373e106..642dd6d0eb333 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -776,6 +776,7 @@ static void its_free_ite(struct kvm *kvm, struct its_ite *ite) its_unmap_vlpi(ite->irq->host_irq); irq->hw = false; + irq->mapped = false; } vgic_put_irq(kvm, ite->irq); @@ -784,6 +785,23 @@ static void its_free_ite(struct kvm *kvm, struct its_ite *ite) kfree(ite); } +/* Mapping one LPI from two events is UNPREDICTABLE: the first ITE keeps it. */ +static bool vgic_its_map_lpi(struct kvm *kvm, struct its_ite *ite, + struct vgic_irq *irq, struct kvm_vcpu *vcpu) +{ + scoped_guard(raw_spinlock_irqsave, &irq->irq_lock) { + if (!irq->mapped) { + irq->mapped = true; + irq->target_vcpu = vcpu; + ite->irq = irq; + return true; + } + } + + vgic_put_irq(kvm, irq); + return false; +} + static u64 its_cmd_mask_field(u64 *its_cmd, int word, int shift, int size) { return (le64_to_cpu(its_cmd[word]) >> shift) & (BIT_ULL(size) - 1); @@ -1093,13 +1111,14 @@ static int vgic_its_cmd_handle_mapi(struct kvm *kvm, struct vgic_its *its, vcpu = collection_to_vcpu(kvm, collection); irq = vgic_add_lpi(kvm, lpi_nr, vcpu); + if (!IS_ERR(irq) && !vgic_its_map_lpi(kvm, ite, irq, vcpu)) + irq = ERR_PTR(-EEXIST); if (IS_ERR(irq)) { if (new_coll) vgic_its_free_collection(its, coll_id); its_free_ite(kvm, ite); return PTR_ERR(irq); } - ite->irq = irq; return 0; } @@ -2208,7 +2227,10 @@ static int vgic_its_restore_ite(struct vgic_its *its, u32 event_id, its_free_ite(kvm, ite); return PTR_ERR(irq); } - ite->irq = irq; + + /* Drop an ITE whose LPI another ITE maps, as MAPTI does. */ + if (!vgic_its_map_lpi(kvm, ite, irq, vcpu)) + its_free_ite(kvm, ite); return offset; } diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h index 086b7578e5f33..5c3a0154becc4 100644 --- a/include/kvm/arm_vgic.h +++ b/include/kvm/arm_vgic.h @@ -256,6 +256,7 @@ struct vgic_irq { bool active:1; bool hw:1; /* Tied to HW IRQ */ bool on_lr:1; /* Present in a CPU LR */ + bool mapped:1; /* LPIs: mapped by an ITE */ refcount_t refcount; /* Used for LPIs */ u32 hwintid; /* HW INTID number */ unsigned int host_irq; /* linux irq corresponding to hwintid */ -- 2.53.0