[PATCH v2 06/11] iommu/arm-smmu-v3: Support PRI Page Request in arm_smmu_handle_ppr()

From: Nicolin Chen

Date: Thu May 28 2026 - 04:09:55 EST


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.

Co-developed-by: Barak Biber <bbiber@xxxxxxxxxx>
Signed-off-by: Barak Biber <bbiber@xxxxxxxxxx>
Co-developed-by: Stefan Kaestle <skaestle@xxxxxxxxxx>
Signed-off-by: Stefan Kaestle <skaestle@xxxxxxxxxx>
Signed-off-by: Malak Marrid <mmarrid@xxxxxxxxxx>
Signed-off-by: Nicolin Chen <nicolinc@xxxxxxxxxx>
---
drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c | 32 +++++++++++++++++++++
1 file changed, 32 insertions(+)

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 061f1d46fda0d..371a8bbdf6756 100644
--- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
+++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
@@ -2242,6 +2242,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;
@@ -2252,6 +2253,37 @@ 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]);

+ mutex_lock(&smmu->streams_mutex);
+ master = arm_smmu_find_master(smmu, sid);
+ if (master && master->pri_enabled) {
+ struct iopf_fault iopf_fault = {0};
+ 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(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",
--
2.43.0