From: Nicolin Chen <nicolinc@nvidia.com>
To: <will@kernel.org>, <robin.murphy@arm.com>, <jgg@nvidia.com>
Cc: <joro@8bytes.org>, <bhelgaas@google.com>, <praan@google.com>,
<kevin.tian@intel.com>, <kees@kernel.org>, <smostafa@google.com>,
<baolu.lu@linux.intel.com>,
<linux-arm-kernel@lists.infradead.org>, <iommu@lists.linux.dev>,
<linux-kernel@vger.kernel.org>, <linux-pci@vger.kernel.org>,
<skaestle@nvidia.com>, <mmarrid@nvidia.com>,
<skolothumtho@nvidia.com>, <bbiber@nvidia.com>,
<harsha.v@oss.qualcomm.com>
Subject: [PATCH v3 09/13] iommu/arm-smmu-v3: Support PRI Page Request in arm_smmu_handle_ppr()
Date: Mon, 31 Aug 2026 17:33:34 -0700 [thread overview]
Message-ID: <0fe5f381aae307045e4cab97f8000c575f34a9ee.1788222486.git.nicolinc@nvidia.com> (raw)
In-Reply-To: <cover.1788222485.git.nicolinc@nvidia.com>
Now, arm_smmu_page_response() can issue CMDQ_OP_PRI_RESP for page requests
from the IOPF infrastructure. Forward PRI requests from the priq into the
IOPF infrastructure for PRI-enabled masters by building an iopf_fault from
the priq entry and calling iommu_report_device_fault().
For an unrecognised StreamID or a master without master->pri_enabled, fall
through to the existing "unexpected PRI request" log + LAST-page DENY path
to release the credit per the PCIe PRI spec. Merge its two info prints in
the path into one single ratelimited line, as a malfunctioning device can
spam unrecognised requests and easily flood the kernel log.
Discard any PASID Stop Marker (LRW = 0b100) prior to the fault report and
the DENY fallback both, because a Stop Marker does not expect a response.
The IOPF infrastructure requires the driver to discard it, as per the doc
at iommu_report_device_fault(). This also matches the intel-iommu code.
Note that master->pri_enabled will only be set by a later change, once all
the PRI paths are ready.
On PRIQ overflow, partial requests stored via report_partial_fault() whose
LAST-page entry was lost stay in iopf_param->partial. Drop them by calling
iopf_queue_discard_partial(), matching intel-iommu's handling. Do it after
the queue is fully drained, since the visible entries all precede the loss
point: a group whose LAST-page entry is still in the queue gets assembled
before the discard, rather than losing its stored partials to it. Nor can
a new arrival race against the discard, since an active overflow inhibits
new entries from being written to the PRI queue (IHI0070 8.1), up until a
final CONS write acknowledges it.
Co-developed-by: Barak Biber <bbiber@nvidia.com>
Signed-off-by: Barak Biber <bbiber@nvidia.com>
Co-developed-by: Stefan Kaestle <skaestle@nvidia.com>
Signed-off-by: Stefan Kaestle <skaestle@nvidia.com>
Signed-off-by: Malak Marrid <mmarrid@nvidia.com>
Signed-off-by: Nicolin Chen <nicolinc@nvidia.com>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 59 +++++++++++++++++++--
1 file changed, 55 insertions(+), 4 deletions(-)
diff --git a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
index 60f21591de9e8..502b5c7673bc9 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2368,6 +2368,7 @@ static irqreturn_t arm_smmu_evtq_thread(int irq, void *dev)
static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
{
+ struct arm_smmu_master *master;
u32 sid, ssid;
u16 grpid;
bool ssv, last;
@@ -2378,9 +2379,47 @@ static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64 *evt)
last = FIELD_GET(PRIQ_0_PRG_LAST, evt[0]);
grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
- dev_info(smmu->dev, "unexpected PRI request received:\n");
- dev_info(smmu->dev,
- "\tsid 0x%08x.0x%05x: [%u%s] %sprivileged %s%s%s access at iova 0x%016llx\n",
+ /*
+ * A PASID Stop Marker (LRW = 0b100) does not expect a response and
+ * must be discarded before fault reporting: see the documentation
+ * at iommu_report_device_fault().
+ */
+ if (last && !(evt[0] & (PRIQ_0_PERM_READ | PRIQ_0_PERM_WRITE)))
+ return;
+
+ mutex_lock(&smmu->streams_mutex);
+ master = arm_smmu_find_master(smmu, sid);
+ if (master && master->pri_enabled) {
+ struct iopf_fault iopf_fault = {};
+ struct iommu_fault *fault = &iopf_fault.fault;
+
+ fault->type = IOMMU_FAULT_PAGE_REQ;
+ if (last)
+ fault->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
+ if (ssv) {
+ fault->prm.flags |=
+ IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
+ fault->prm.pasid = ssid;
+ }
+ fault->prm.grpid = grpid;
+ if (evt[0] & PRIQ_0_PERM_READ)
+ fault->prm.perm |= IOMMU_FAULT_PERM_READ;
+ if (evt[0] & PRIQ_0_PERM_WRITE)
+ fault->prm.perm |= IOMMU_FAULT_PERM_WRITE;
+ if (evt[0] & PRIQ_0_PERM_EXEC)
+ fault->prm.perm |= IOMMU_FAULT_PERM_EXEC;
+ if (evt[0] & PRIQ_0_PERM_PRIV)
+ fault->prm.perm |= IOMMU_FAULT_PERM_PRIV;
+ fault->prm.addr = FIELD_GET(PRIQ_1_ADDR_MASK, evt[1]) << 12;
+
+ iommu_report_device_fault(master->dev, &iopf_fault);
+ mutex_unlock(&smmu->streams_mutex);
+ return;
+ }
+ mutex_unlock(&smmu->streams_mutex);
+
+ dev_info_ratelimited(smmu->dev,
+ "unexpected PRI request: sid 0x%08x.0x%05x: [%u%s] %sprivileged %s%s%s access at iova 0x%016llx\n",
sid, ssid, grpid, last ? "L" : "",
evt[0] & PRIQ_0_PERM_PRIV ? "" : "un",
evt[0] & PRIQ_0_PERM_READ ? "R" : "",
@@ -2400,15 +2439,27 @@ static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
struct arm_smmu_queue *q = &smmu->priq.q;
struct arm_smmu_ll_queue *llq = &q->llq;
u64 evt[PRIQ_ENT_DWORDS];
+ bool overflow = false;
do {
while (!queue_remove_raw(q, evt))
arm_smmu_handle_ppr(smmu, evt);
- if (queue_sync_prod_in(q) == -EOVERFLOW)
+ if (queue_sync_prod_in(q) == -EOVERFLOW) {
dev_err(smmu->dev, "PRIQ overflow detected -- requests lost\n");
+ overflow = true;
+ }
} while (!queue_empty(llq));
+ /*
+ * Discard the partial faults after the drain, so any group with its
+ * LAST-page entry visible in the queue gets assembled beforehand. An
+ * active overflow condition inhibits new entries from being written
+ * to the PRI queue, until it gets acknowledged below.
+ */
+ if (overflow)
+ iopf_queue_discard_partial(smmu->evtq.iopf);
+
/* Sync our overflow flag, as we believe we're up to speed */
queue_sync_cons_ovf(q);
return IRQ_HANDLED;
--
2.43.0
next prev parent reply other threads:[~2026-09-01 0:34 UTC|newest]
Thread overview: 38+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-01 0:33 [PATCH v3 00/13] iommu/arm-smmu-v3: Add PRI support Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 01/13] iommu/arm-smmu-v3: Add arm_smmu_attach_release() Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-04 20:16 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 02/13] iommu/arm-smmu-v3: Add Q_POS() macro Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 03/13] iommu/arm-smmu-v3: Drain in-flight fault events on domain detach Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-04 14:09 ` Jason Gunthorpe
2026-09-04 22:57 ` Nicolin Chen
2026-09-04 21:42 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 04/13] iommu/arm-smmu-v3: Flush in-flight fault work " Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-05 0:54 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 05/13] iommu/arm-smmu-v3: Allocate IOPF queue without FEAT_SVA Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-01 0:33 ` [PATCH v3 06/13] iommu/arm-smmu-v3: Submit CMDQ_OP_PRI_RESP for IOPF event Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-05 1:15 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 07/13] iommu/arm-smmu-v3: Disable the queue IRQs before disabling the SMMU Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-05 3:24 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 08/13] iommu/arm-smmu-v3: Disable PRI when no IRQ handler is registered Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-04 14:15 ` Jason Gunthorpe
2026-09-01 0:33 ` Nicolin Chen [this message]
2026-09-03 19:18 ` [PATCH v3 09/13] iommu/arm-smmu-v3: Support PRI Page Request in arm_smmu_handle_ppr() Jonathan Cameron
2026-09-05 5:08 ` Nicolin Chen
2026-09-01 0:33 ` [PATCH v3 10/13] iommu/arm-smmu-v3: Allocate IOPF queue for ARM_SMMU_FEAT_PRI Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-01 0:33 ` [PATCH v3 11/13] PCI/ATS: Add PRI stubs Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-01 0:33 ` [PATCH v3 12/13] PCI/ATS: Export pci_enable_pri() and pci_reset_pri() Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-01 0:33 ` [PATCH v3 13/13] iommu/arm-smmu-v3: Enable PRI for PCI device in arm_smmu_probe_device() Nicolin Chen
2026-09-03 19:18 ` Jonathan Cameron
2026-09-05 5:53 ` Nicolin Chen
2026-09-03 19:18 ` [PATCH v3 00/13] iommu/arm-smmu-v3: Add PRI support Jonathan Cameron
2026-09-04 14:10 ` Jason Gunthorpe
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=0fe5f381aae307045e4cab97f8000c575f34a9ee.1788222486.git.nicolinc@nvidia.com \
--to=nicolinc@nvidia.com \
--cc=baolu.lu@linux.intel.com \
--cc=bbiber@nvidia.com \
--cc=bhelgaas@google.com \
--cc=harsha.v@oss.qualcomm.com \
--cc=iommu@lists.linux.dev \
--cc=jgg@nvidia.com \
--cc=joro@8bytes.org \
--cc=kees@kernel.org \
--cc=kevin.tian@intel.com \
--cc=linux-arm-kernel@lists.infradead.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=mmarrid@nvidia.com \
--cc=praan@google.com \
--cc=robin.murphy@arm.com \
--cc=skaestle@nvidia.com \
--cc=skolothumtho@nvidia.com \
--cc=smostafa@google.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox