All of lore.kernel.org
 help / color / mirror / Atom feed
From: Nicolin Chen <nicolinc@nvidia.com>
To: Will Deacon <will@kernel.org>
Cc: Robin Murphy <robin.murphy@arm.com>,
	"Joerg Roedel (AMD)" <joro@8bytes.org>,
	Jason Gunthorpe <jgg@nvidia.com>, <linux-tegra@vger.kernel.org>,
	<linux-arm-kernel@lists.infradead.org>, <iommu@lists.linux.dev>,
	<linux-kernel@vger.kernel.org>
Subject: [PATCH v3] iommu/tegra241-cmdqv: Reject a VCMDQ base above the 48-bit hardware limit
Date: Wed, 29 Jul 2026 15:03:29 -0700	[thread overview]
Message-ID: <20260729220329.805417-1-nicolinc@nvidia.com> (raw)

tegra241_vcmdq_alloc_smmu_cmdq() allocates the VCMDQ buffer via the common
arm_smmu_init_one_queue(), which uses smmu->dev and its coherent DMA mask
of DMA_BIT_MASK(smmu->oas). An SMMUv3 queue base holds a 52-bit address in
Q_BASE_ADDR_MASK, but the VCMDQ_BASE register holds only 48 (VCMDQ_ADDR),
so the masked write "q_base = base_dma & VCMDQ_ADDR" silently drops bits 48
and up. The HW would then fetch its commands from a wrong memory location,
which likely raises VCMDQ errors.

Real hardware always pairs an SMMU OAS with a matching VCMDQ address field,
so this cannot happen; it takes a VMM that gives a guest a mismatched OAS.
Nor can the guest rely on the VMM to catch it: an SMMU CMDQ base keeps bits
48 and up in Q_BASE_ADDR_MASK, so a trapped CMDQ_BASE write still carries
them, while a VCMDQ base goes straight to the hardware and loses them.

Reject a base_dma with bits set outside VCMDQ_ADDR, the way the user-VCMDQ
path already does for its base_addr_pa, failing the queue init rather than
silently truncating the base. Use dev_warn_once() rather than WARN_ON(), as
the OAS is VMM-controlled and a WARN_ON() would let it panic a guest booted
with panic_on_warn.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---

Changelog
v3
 * Rebase on arm/smmu/updates branch
 * Update subject, commit message, and inline notes
v2
 https://lore.kernel.org/all/4e638ec1bbff46a358b4129e264fef66b4f37703.1784059577.git.nicolinc@nvidia.com/
 * No change
v1
 https://lore.kernel.org/all/0dc3a146a3d274d7c47e525385830343cea0f675.1783054570.git.nicolinc@nvidia.com/

 drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c | 14 ++++++++++++++
 1 file changed, 14 insertions(+)

diff --git a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
index 6644075c1431e..664aff9593de8 100644
--- a/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
+++ b/drivers/iommu/arm/arm-smmu-v3/tegra241-cmdqv.c
@@ -672,6 +672,20 @@ static int tegra241_vcmdq_alloc_smmu_cmdq(struct tegra241_vcmdq *vcmdq)
 	if (ret)
 		return ret;
 
+	/*
+	 * The q->base_dma is bounded by DMA_BIT_MASK of SMMU's IDR5.OAS. On a
+	 * real hardware, VCMDQ_ADDR mask and IDR5.OAS are always aligned. But
+	 * a buggy VMM might give a guest a mismatched IDR5.OAS. Spit a warning
+	 * instead of a silent truncation that would make the HW fetch commands
+	 * from a wrong memory location.
+	 */
+	if (q->base_dma & ~VCMDQ_ADDR) {
+		dev_warn_once(
+			vcmdq->cmdqv->dev,
+			"VCMDQ base %pad exceeds the 48-bit VCMDQ_ADDR limit\n",
+			&q->base_dma);
+		return -EINVAL;
+	}
 	/* ...override q_base to write VCMDQ_BASE registers */
 	q->q_base = q->base_dma & VCMDQ_ADDR;
 	q->q_base |= FIELD_PREP(VCMDQ_LOG2SIZE, q->llq.max_n_shift);

base-commit: a86c36163c9722545d27e92bdad8418fdcaa8b1d
-- 
2.43.0



             reply	other threads:[~2026-07-29 22:04 UTC|newest]

Thread overview: 5+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-29 22:03 Nicolin Chen [this message]
2026-08-06 12:47 ` [PATCH v3] iommu/tegra241-cmdqv: Reject a VCMDQ base above the 48-bit hardware limit Will Deacon
2026-08-06 13:17   ` Robin Murphy
2026-08-06 14:09     ` Jason Gunthorpe
2026-08-06 17:22       ` Nicolin Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260729220329.805417-1-nicolinc@nvidia.com \
    --to=nicolinc@nvidia.com \
    --cc=iommu@lists.linux.dev \
    --cc=jgg@nvidia.com \
    --cc=joro@8bytes.org \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-tegra@vger.kernel.org \
    --cc=robin.murphy@arm.com \
    --cc=will@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.