From nobody Fri Dec 19 20:13:25 2025 Received: from out-173.mta1.migadu.com (out-173.mta1.migadu.com [95.215.58.173]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5067251025 for ; Tue, 13 Feb 2024 09:38:35 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=95.215.58.173 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707817116; cv=none; b=QG80NMsCFGw0XzODEef7qLo9WnQJh6bx29/d9xu0Yq10C1WHTCkcFwA5ugyCMc/uHEulOs9Wioa7CgBrupavwJg+VGaND6QDOPriWnzytWiulOefmBRkuEuZ5GDgQbMX5ckkllmI0b/TGamnD6dG1gNE507pMS/3AAP8eRaxodw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1707817116; c=relaxed/simple; bh=iYPy+Djc7SztwYSE8UN83cn8sXnT9Xu1HwT7l4kGpr8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Tq0RTUvzPPIMH8N1kP02GICcGU0U0LDx7eQWwk2+3nR8qr+T6CPLsXpIUBRpkOIDHJYYCi7vERnykLa7nd3KkwYzT92TlObJ5ZBYML2fcIqcRFGfAZYSMWUFAf8M8YlPHHRX1tSm4FKveMlgXZCxITclHKeFWQqjnXnrPM8iFjs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev; spf=pass smtp.mailfrom=linux.dev; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b=dZHpG1G4; arc=none smtp.client-ip=95.215.58.173 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linux.dev Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linux.dev Authentication-Results: smtp.subspace.kernel.org; dkim=pass (1024-bit key) header.d=linux.dev header.i=@linux.dev header.b="dZHpG1G4" X-Report-Abuse: Please report any abuse attempt to abuse@migadu.com and include these headers. DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linux.dev; s=key1; t=1707817113; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=tzXQU++wkXrnCgv+wzrV4DGhnpKBtk4FI4+/K2Mli/0=; b=dZHpG1G41vsXh+Cd0nri7mL23uzEzEJ70EEubkmZ69krO3yyr+812ExcHaaBN0tAiYO/1j mWbk+z49WB6RF7XK+zWtdsHBak3IzYRe5ZZ6A+c6lVvY4iSgqVimAHVnBcZnoQY/JcJ+jy rWrWEvDJuv4QY3UsXTWBGjkZRgjx9ik= From: Oliver Upton To: kvmarm@lists.linux.dev Cc: kvm@vger.kernel.org, Marc Zyngier , James Morse , Suzuki K Poulose , Zenghui Yu , linux-kernel@vger.kernel.org, Oliver Upton Subject: [PATCH v2 14/23] KVM: arm64: vgic-its: Protect cached vgic_irq pointers with RCU Date: Tue, 13 Feb 2024 09:37:38 +0000 Message-ID: <20240213093747.3960866-1-oliver.upton@linux.dev> In-Reply-To: <20240213093250.3960069-1-oliver.upton@linux.dev> References: <20240213093250.3960069-1-oliver.upton@linux.dev> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Migadu-Flow: FLOW_OUT Content-Type: text/plain; charset="utf-8" RCU readers of the LPI translation cache will be able to run in parallel with a cache invalidation, which clears the RCU pointer. Start using RCU protection on the cached irq pointer in light of this. Signed-off-by: Oliver Upton --- arch/arm64/kvm/vgic/vgic-its.c | 28 ++++++++++++++++++---------- 1 file changed, 18 insertions(+), 10 deletions(-) diff --git a/arch/arm64/kvm/vgic/vgic-its.c b/arch/arm64/kvm/vgic/vgic-its.c index 35926d5ae561..99042ecc9c85 100644 --- a/arch/arm64/kvm/vgic/vgic-its.c +++ b/arch/arm64/kvm/vgic/vgic-its.c @@ -156,7 +156,7 @@ struct vgic_translation_cache_entry { phys_addr_t db; u32 devid; u32 eventid; - struct vgic_irq *irq; + struct vgic_irq __rcu *irq; atomic64_t usage_count; }; =20 @@ -574,7 +574,7 @@ static struct vgic_irq *__vgic_its_check_cache(struct v= gic_dist *dist, * If we hit a NULL entry, there is nothing after this * point. */ - if (!cte->irq) + if (!rcu_access_pointer(cte->irq)) break; =20 if (cte->db !=3D db || cte->devid !=3D devid || @@ -582,7 +582,7 @@ static struct vgic_irq *__vgic_its_check_cache(struct v= gic_dist *dist, continue; =20 atomic64_inc(&cte->usage_count); - return cte->irq; + return rcu_dereference(cte->irq); } =20 return NULL; @@ -629,7 +629,7 @@ static struct vgic_translation_cache_entry *vgic_its_ca= che_victim(struct vgic_di tmp =3D atomic64_read(&cte->usage_count); max =3D max(max, tmp); =20 - if (!cte->irq) { + if (!rcu_access_pointer(cte->irq)) { victim =3D cte; break; } @@ -663,6 +663,7 @@ static void vgic_its_cache_translation(struct kvm *kvm,= struct vgic_its *its, return; =20 raw_spin_lock_irqsave(&dist->lpi_list_lock, flags); + rcu_read_lock(); =20 /* * We could have raced with another CPU caching the same @@ -693,27 +694,32 @@ static void vgic_its_cache_translation(struct kvm *kv= m, struct vgic_its *its, new->db =3D db; new->devid =3D devid; new->eventid =3D eventid; - new->irq =3D irq; + rcu_assign_pointer(new->irq, irq); =20 /* Move the new translation to the head of the list */ list_add(&new->entry, &dist->lpi_translation_cache); dist->lpi_cache_count++; =20 out: + rcu_read_unlock(); raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); =20 if (!victim) return; =20 + synchronize_rcu(); + /* * Caching the translation implies having an extra reference * to the interrupt, so drop the potential reference on what - * was in the cache, and increment it on the new interrupt. + * was in the cache. */ if (victim->irq) { + struct vgic_irq *irq =3D rcu_dereference_raw(victim->irq); + KVM_VM_TRACE_EVENT(kvm, vgic_its_trans_cache_victim, victim->db, - victim->devid, victim->eventid, victim->irq->intid); - vgic_put_irq(kvm, victim->irq); + victim->devid, victim->eventid, irq->intid); + vgic_put_irq(kvm, irq); } =20 kfree(victim); @@ -726,19 +732,21 @@ void vgic_its_invalidate_cache(struct kvm *kvm) unsigned long flags; =20 raw_spin_lock_irqsave(&dist->lpi_list_lock, flags); + rcu_read_lock(); =20 list_for_each_entry(cte, &dist->lpi_translation_cache, entry) { /* * If we hit a NULL entry, there is nothing after this * point. */ - if (!cte->irq) + if (!rcu_access_pointer(cte->irq)) break; =20 vgic_put_irq(kvm, cte->irq); - cte->irq =3D NULL; + rcu_assign_pointer(cte->irq, NULL); } =20 + rcu_read_unlock(); raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags); } =20 --=20 2.43.0.687.g38aa6559b0-goog