RE: [PATCH RFTv1 3/3] iommu/arm-smmu-v3: Support PRI Page Request
From: Shameer Kolothum Thodi
Date: Mon Mar 09 2026 - 07:04:39 EST
> -----Original Message-----
> From: Nicolin Chen <nicolinc@xxxxxxxxxx>
> Sent: 03 March 2026 20:13
> To: will@xxxxxxxxxx; robin.murphy@xxxxxxx; Jason Gunthorpe
> <jgg@xxxxxxxxxx>
> Cc: joro@xxxxxxxxxx; praan@xxxxxxxxxx; Malak Marrid
> <mmarrid@xxxxxxxxxx>; kees@xxxxxxxxxx; Alexander.Grest@xxxxxxxxxxxxx;
> baolu.lu@xxxxxxxxxxxxxxx; smostafa@xxxxxxxxxx; linux-arm-
> kernel@xxxxxxxxxxxxxxxxxxx; iommu@xxxxxxxxxxxxxxx; linux-
> kernel@xxxxxxxxxxxxxxx
> Subject: [PATCH RFTv1 3/3] iommu/arm-smmu-v3: Support PRI Page Request
>
> External email: Use caution opening links or attachments
>
>
> From: Malak Marrid <mmarrid@xxxxxxxxxx>
>
> Now, arm_smmu_page_response() can issue CMDQ_OP_PRI_RESP for page
> requests
> from the IOPF infrastructure. Decode the page requests from the PRI queue,
> and report it to the IOPF infrastructure.
>
> This fills the final piece for PRI support.
Do we also need pci_reset_pri()/pci_enable_pri() to enable PRI on the
device side?
Also, is there a check that the device advertises PCI PRI capability
before calling iopf_queue_add_device()?
Thanks,
Shameer
> 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 | 65 +++++++++++------
> ----
> 1 file changed, 33 insertions(+), 32 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 055dde5367131..277d753c7675c 100644
> --- a/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> +++ b/drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c
> @@ -2061,40 +2061,41 @@ static irqreturn_t arm_smmu_evtq_thread(int
> irq, void *dev)
>
> static void arm_smmu_handle_ppr(struct arm_smmu_device *smmu, u64
> *evt)
> {
> - u32 sid, ssid;
> - u16 grpid;
> - bool ssv, last;
> -
> - sid = FIELD_GET(PRIQ_0_SID, evt[0]);
> - ssv = FIELD_GET(PRIQ_0_SSID_V, evt[0]);
> - ssid = ssv ? FIELD_GET(PRIQ_0_SSID, evt[0]) : IOMMU_NO_PASID;
> - 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",
> - sid, ssid, grpid, last ? "L" : "",
> - evt[0] & PRIQ_0_PERM_PRIV ? "" : "un",
> - evt[0] & PRIQ_0_PERM_READ ? "R" : "",
> - evt[0] & PRIQ_0_PERM_WRITE ? "W" : "",
> - evt[0] & PRIQ_0_PERM_EXEC ? "X" : "",
> - evt[1] & PRIQ_1_ADDR_MASK);
> -
> - if (last) {
> - struct arm_smmu_cmdq_ent cmd = {
> - .opcode = CMDQ_OP_PRI_RESP,
> - .substream_valid = ssv,
> - .pri = {
> - .sid = sid,
> - .ssid = ssid,
> - .grpid = grpid,
> - .resp = PRI_RESP_DENY,
> - },
> - };
> + u32 sid = FIELD_GET(PRIQ_0_SID, evt[0]);
> + struct iopf_fault iopf_fault = {0};
> + struct iommu_fault *fault = &iopf_fault.fault;
> + struct arm_smmu_master *master;
> +
> + INIT_LIST_HEAD(&iopf_fault.list);
>
> - arm_smmu_cmdq_issue_cmd(smmu, &cmd);
> + fault->type = IOMMU_FAULT_PAGE_REQ;
> +
> + if (FIELD_GET(PRIQ_0_PRG_LAST, evt[0]))
> + fault->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_LAST_PAGE;
> + if (FIELD_GET(PRIQ_0_SSID_V, evt[0])) {
> + fault->prm.flags |= IOMMU_FAULT_PAGE_REQUEST_PASID_VALID;
> + fault->prm.pasid = FIELD_GET(PRIQ_0_SSID, evt[0]);
> }
> +
> + fault->prm.grpid = FIELD_GET(PRIQ_1_PRG_IDX, evt[1]);
> +
> + 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;
> +
> + guard(mutex)(&smmu->streams_mutex);
> + master = arm_smmu_find_master(smmu, sid);
> + if (master)
> + iommu_report_device_fault(master->dev, &iopf_fault);
> + else
> + dev_warn(smmu->dev, "PPR: unrecognized StreamID 0x%x\n", sid);
> }
>
> static irqreturn_t arm_smmu_priq_thread(int irq, void *dev)
> --
> 2.43.0
>