mbox series

[v10,00/10] iommu: I/O page faults for SMMUv3

Message ID 20210121123623.2060416-1-jean-philippe@linaro.org
Headers show
Series iommu: I/O page faults for SMMUv3 | expand

Message

Jean-Philippe Brucker Jan. 21, 2021, 12:36 p.m. UTC
Add stall support to the SMMUv3, along with a common I/O Page Fault
handler.

Changes since v9 [1]:
* Style changes suggested by Jonathan
* Fixes to patch 10 pointed out by Robin
* In patch 10, don't register the mm fault handler when enabling
  IOMMU_DEV_FEAT_IOPF, because that feature only indicates that a device
  driver wants to use PRI or stall. After enabling it, drivers may
  register their own IOPF handler (see discussion on v9 patch 03).
  Instead register the mm handler when enabling IOMMU_DEV_FEAT_SVA.

[1] https://lore.kernel.org/linux-iommu/20210108145217.2254447-1-jean-philippe@linaro.org/

Jean-Philippe Brucker (10):
  iommu: Fix comment for struct iommu_fwspec
  iommu/arm-smmu-v3: Use device properties for pasid-num-bits
  iommu: Separate IOMMU_DEV_FEAT_IOPF from IOMMU_DEV_FEAT_SVA
  iommu/vt-d: Support IOMMU_DEV_FEAT_IOPF
  uacce: Enable IOMMU_DEV_FEAT_IOPF
  iommu: Add a page fault handler
  iommu/arm-smmu-v3: Maintain a SID->device structure
  dt-bindings: document stall property for IOMMU masters
  ACPI/IORT: Enable stall support for platform devices
  iommu/arm-smmu-v3: Add stall support for platform devices

 drivers/iommu/Makefile                        |   1 +
 .../devicetree/bindings/iommu/iommu.txt       |  18 +
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.h   |  56 ++-
 drivers/iommu/iommu-sva-lib.h                 |  53 ++
 include/linux/iommu.h                         |  26 +-
 drivers/acpi/arm64/iort.c                     |  15 +-
 .../iommu/arm/arm-smmu-v3/arm-smmu-v3-sva.c   |  59 ++-
 drivers/iommu/arm/arm-smmu-v3/arm-smmu-v3.c   | 347 +++++++++++--
 drivers/iommu/intel/iommu.c                   |  11 +-
 drivers/iommu/io-pgfault.c                    | 461 ++++++++++++++++++
 drivers/iommu/of_iommu.c                      |   5 -
 drivers/misc/uacce/uacce.c                    |  39 +-
 12 files changed, 1018 insertions(+), 73 deletions(-)
 create mode 100644 drivers/iommu/io-pgfault.c

Comments

Jean-Philippe Brucker Jan. 22, 2021, 8:51 a.m. UTC | #1
On Thu, Jan 21, 2021 at 07:12:36PM +0000, Jonathan Cameron wrote:
> > @@ -2502,6 +2647,7 @@ static void arm_smmu_release_device(struct device *dev)

> >  

> >  	master = dev_iommu_priv_get(dev);

> >  	WARN_ON(arm_smmu_master_sva_enabled(master));

> > +	iopf_queue_remove_device(master->smmu->evtq.iopf, dev);

> >  	arm_smmu_detach_dev(master);

> >  	arm_smmu_disable_pasid(master);

> >  	arm_smmu_remove_master(master);

> 

> The lack of symmetry here bothers me a bit, but it's already true, so I guess

> this case is fine as well.


Normally the device driver calls iommu_dev_feat_disable(SVA) which does
iopf_queue_remove_device(). This is just a safety net in case the device
gets removed without the driver properly cleaning up (which will WARN as
well) 

> 

> ...

> >  

> > @@ -2785,6 +2946,7 @@ static int arm_smmu_cmdq_init(struct arm_smmu_device *smmu)

> >  static int arm_smmu_init_queues(struct arm_smmu_device *smmu)

> >  {

> >  	int ret;

> > +	bool sva = smmu->features & ARM_SMMU_FEAT_STALLS;

> 

> FEAT_SVA?


Ugh yes, thanks. I left this as a bool instead of moving into the test
below because the PRI patch reuses it, but I think I'll just move it down
when resending.

Thanks,
Jean

> 

> >  

> >  	/* cmdq */

> >  	ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD,

> > @@ -2804,6 +2966,12 @@ static int arm_smmu_init_queues(struct arm_smmu_device *smmu)

> >  	if (ret)

> >  		return ret;

> >  

> > +	if (sva && smmu->features & ARM_SMMU_FEAT_STALLS) {

> 

> Isn't this checking same thing twice?

> 

> > +		smmu->evtq.iopf = iopf_queue_alloc(dev_name(smmu->dev));

> > +		if (!smmu->evtq.iopf)

> > +			return -ENOMEM;

> > +	}

> > +

> >  	/* priq */

> >  	if (!(smmu->features & ARM_SMMU_FEAT_PRI))

> >  		return 0;

> > @@ -3718,6 +3886,7 @@ static int arm_smmu_device_remove(struct platform_device *pdev)

> >  	iommu_device_unregister(&smmu->iommu);

> >  	iommu_device_sysfs_remove(&smmu->iommu);

> >  	arm_smmu_device_disable(smmu);

> > +	iopf_queue_free(smmu->evtq.iopf);

> >  

> >  	return 0;

> >  }

>