[PATCH RFTv1 3/3] iommu/arm-smmu-v3: Support PRI Page Request

Shameer Kolothum Thodi skolothumtho at nvidia.com
Mon Mar 9 04:04:31 PDT 2026



> -----Original Message-----
> From: Nicolin Chen <nicolinc at nvidia.com>
> Sent: 03 March 2026 20:13
> To: will at kernel.org; robin.murphy at arm.com; Jason Gunthorpe
> <jgg at nvidia.com>
> Cc: joro at 8bytes.org; praan at google.com; Malak Marrid
> <mmarrid at nvidia.com>; kees at kernel.org; Alexander.Grest at microsoft.com;
> baolu.lu at linux.intel.com; smostafa at google.com; linux-arm-
> kernel at lists.infradead.org; iommu at lists.linux.dev; linux-
> kernel at vger.kernel.org
> 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 at nvidia.com>
> 
> 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 at nvidia.com>
> Signed-off-by: Barak Biber <bbiber at nvidia.com>
> Co-developed-by: Stefan Kaestle <skaestle at nvidia.com>
> Signed-off-by: Stefan Kaestle <skaestle at nvidia.com>
> Signed-off-by: Malak Marrid <mmarrid at nvidia.com>
> Signed-off-by: Nicolin Chen <nicolinc at nvidia.com>
> ---
>  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
> 




More information about the linux-arm-kernel mailing list