Re: [PATCH v3 2/2] iommu/vt-d:Add support for probing ACPI device in RMRR

2020-08-31 Thread Lu Baolu

Hi Felix,

On 8/27/20 6:02 PM, FelixCuioc wrote:

After acpi device in RMRR is detected,it is necessary
to establish a mapping for these devices.
In acpi_device_create_direct_mappings(),create a mapping
for the acpi device in RMRR.
Add a helper to achieve the acpi namespace device can
access the RMRR region.


Are those ACPI devices visible to kernel? If so, any device driver bound
for it?

Best regards,
baolu



Signed-off-by: FelixCuioc 
---
  drivers/iommu/intel/iommu.c | 29 +
  drivers/iommu/iommu.c   |  6 ++
  include/linux/iommu.h   |  3 +++
  3 files changed, 38 insertions(+)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 208a91605288..51d7a5b18f41 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4799,6 +4799,21 @@ static int __init platform_optin_force_iommu(void)
return 1;
  }
  
+static int acpi_device_create_direct_mappings(struct device *pn_dev, struct device *acpi_device)

+{
+   struct iommu_group *group;
+
+   acpi_device->bus->iommu_ops = &intel_iommu_ops;
+   group = iommu_group_get(pn_dev);
+   if (!group) {
+   pr_warn("ACPI name space devices create direct mappings 
wrong!\n");
+   return -EINVAL;
+   }
+   __acpi_device_create_direct_mappings(group, acpi_device);
+
+   return 0;
+}
+
  static int __init probe_acpi_namespace_devices(void)
  {
struct dmar_drhd_unit *drhd;
@@ -4813,6 +4828,7 @@ static int __init probe_acpi_namespace_devices(void)
struct acpi_device_physical_node *pn;
struct iommu_group *group;
struct acpi_device *adev;
+   struct device *pn_dev = NULL;
  
  			if (dev->bus != &acpi_bus_type)

continue;
@@ -4823,6 +4839,7 @@ static int __init probe_acpi_namespace_devices(void)
&adev->physical_node_list, node) {
group = iommu_group_get(pn->dev);
if (group) {
+   pn_dev = pn->dev;
iommu_group_put(group);
continue;
}
@@ -4831,7 +4848,19 @@ static int __init probe_acpi_namespace_devices(void)
ret = iommu_probe_device(pn->dev);
if (ret)
break;
+   pn_dev = pn->dev;
+   }
+   if (!pn_dev) {
+   dev->bus->iommu_ops = &intel_iommu_ops;
+   ret = iommu_probe_device(dev);
+   if (ret) {
+   pr_err("acpi_device probe fail! 
ret:%d\n", ret);
+   goto unlock;
+   }
+   goto unlock;
}
+   ret = acpi_device_create_direct_mappings(pn_dev, dev);
+unlock:
mutex_unlock(&adev->physical_node_lock);
  
  			if (ret)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 609bd25bf154..4f714a2d5ef7 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -779,6 +779,12 @@ static bool iommu_is_attach_deferred(struct iommu_domain 
*domain,
return false;
  }
  
+void  __acpi_device_create_direct_mappings(struct iommu_group *group, struct device *acpi_device)

+{
+   iommu_create_device_direct_mappings(group, acpi_device);
+}
+EXPORT_SYMBOL_GPL(__acpi_device_create_direct_mappings);
+
  /**
   * iommu_group_add_device - add a device to an iommu group
   * @group: the group into which to add the device (reference should be held)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fee209efb756..9be134775886 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -514,6 +514,9 @@ extern void iommu_domain_window_disable(struct iommu_domain 
*domain, u32 wnd_nr)
  extern int report_iommu_fault(struct iommu_domain *domain, struct device *dev,
  unsigned long iova, int flags);
  
+extern void __acpi_device_create_direct_mappings(struct iommu_group *group,

+   struct device *acpi_device);
+
  static inline void iommu_flush_tlb_all(struct iommu_domain *domain)
  {
if (domain->ops->flush_iotlb_all)


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v3 1/2] iommu/vt-d:Add support for detecting ACPI device in RMRR

2020-08-31 Thread Lu Baolu

Hi Felix,

On 8/27/20 6:02 PM, FelixCuioc wrote:

Some ACPI devices need to issue dma requests to access
the reserved memory area.BIOS uses the device scope type
ACPI_NAMESPACE_DEVICE in RMRR to report these ACPI devices.
This patch add support for detecting ACPI devices in RMRR.

Signed-off-by: FelixCuioc 
---
  drivers/iommu/intel/dmar.c  | 76 +
  drivers/iommu/intel/iommu.c | 23 ++-
  include/linux/dmar.h| 12 +-
  3 files changed, 76 insertions(+), 35 deletions(-)

diff --git a/drivers/iommu/intel/dmar.c b/drivers/iommu/intel/dmar.c
index 93e6345f3414..f6691c36bd3f 100644
--- a/drivers/iommu/intel/dmar.c
+++ b/drivers/iommu/intel/dmar.c
@@ -215,7 +215,7 @@ static bool dmar_match_pci_path(struct dmar_pci_notify_info 
*info, int bus,
  }
  
  /* Return: > 0 if match found, 0 if no match found, < 0 if error happens */

-int dmar_insert_dev_scope(struct dmar_pci_notify_info *info,
+int dmar_pci_insert_dev_scope(struct dmar_pci_notify_info *info,
  void *start, void*end, u16 segment,
  struct dmar_dev_scope *devices,
  int devices_cnt)
@@ -304,7 +304,7 @@ static int dmar_pci_bus_add_dev(struct dmar_pci_notify_info 
*info)
  
  		drhd = container_of(dmaru->hdr,

struct acpi_dmar_hardware_unit, header);
-   ret = dmar_insert_dev_scope(info, (void *)(drhd + 1),
+   ret = dmar_pci_insert_dev_scope(info, (void *)(drhd + 1),
((void *)drhd) + drhd->header.length,
dmaru->segment,
dmaru->devices, dmaru->devices_cnt);
@@ -697,47 +697,59 @@ dmar_find_matched_drhd_unit(struct pci_dev *dev)
return dmaru;
  }
  
-static void __init dmar_acpi_insert_dev_scope(u8 device_number,

- struct acpi_device *adev)
+/* Return: > 0 if match found, 0 if no match found */
+bool dmar_acpi_insert_dev_scope(u8 device_number,
+   struct acpi_device *adev,
+   void *start, void *end,
+   struct dmar_dev_scope *devices,
+   int devices_cnt)
  {
-   struct dmar_drhd_unit *dmaru;
-   struct acpi_dmar_hardware_unit *drhd;
struct acpi_dmar_device_scope *scope;
struct device *tmp;
int i;
struct acpi_dmar_pci_path *path;
  
+	for (; start < end; start += scope->length) {

+   scope = start;
+   if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
+   continue;
+   if (scope->enumeration_id != device_number)
+   continue;
+   path = (void *)(scope + 1);
+   for_each_dev_scope(devices, devices_cnt, i, tmp)
+   if (tmp == NULL) {
+   devices[i].bus = scope->bus;
+   devices[i].devfn = PCI_DEVFN(path->device, 
path->function);
+   rcu_assign_pointer(devices[i].dev,
+  get_device(&adev->dev));
+   return true;
+   }
+   WARN_ON(i >= devices_cnt);
+   }
+   return false;
+}
+
+static int dmar_acpi_bus_add_dev(u8 device_number, struct acpi_device *adev)
+{
+   struct dmar_drhd_unit *dmaru;
+   struct acpi_dmar_hardware_unit *drhd;
+   int ret;
+
for_each_drhd_unit(dmaru) {
drhd = container_of(dmaru->hdr,
struct acpi_dmar_hardware_unit,
header);
+   ret = dmar_acpi_insert_dev_scope(device_number, adev, (void 
*)(drhd+1),
+   ((void 
*)drhd)+drhd->header.length,
+   dmaru->devices, 
dmaru->devices_cnt);
+   if (ret)
+   break;
+   }
+   if (ret > 0)
+   ret = dmar_rmrr_add_acpi_dev(device_number, adev);
  
-		for (scope = (void *)(drhd + 1);

-(unsigned long)scope < ((unsigned long)drhd) + 
drhd->header.length;
-scope = ((void *)scope) + scope->length) {
-   if (scope->entry_type != ACPI_DMAR_SCOPE_TYPE_NAMESPACE)
-   continue;
-   if (scope->enumeration_id != device_number)
-   continue;
+   return ret;
  
-			path = (void *)(scope + 1);

-   pr_info("ACPI device \"%s\" under DMAR at %llx as 
%02x:%02x.%d\n",
-   dev_name(&adev->dev), dmaru->reg_base_addr,
-   scope->bus, path->device, path->function);


Please keep such information. People are used to use them as a method to
know the hardwa

Re: [PATCH 01/19] drm/msm: remove dangling submitqueue references

2020-08-31 Thread Bjorn Andersson
On Tue 01 Sep 03:42 UTC 2020, Rob Clark wrote:

> On Mon, Aug 31, 2020 at 7:35 PM Bjorn Andersson
>  wrote:
> >
> > On Fri 14 Aug 02:40 UTC 2020, Rob Clark wrote:
> >
> > > From: Rob Clark 
> > >
> > > Currently it doesn't matter, since we free the ctx immediately.  But
> > > when we start refcnt'ing the ctx, we don't want old dangling list
> > > entries to hang around.
> > >
> > > Signed-off-by: Rob Clark 
> > > ---
> > >  drivers/gpu/drm/msm/msm_submitqueue.c | 4 +++-
> > >  1 file changed, 3 insertions(+), 1 deletion(-)
> > >
> > > diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c 
> > > b/drivers/gpu/drm/msm/msm_submitqueue.c
> > > index a1d94be7883a..90c9d84e6155 100644
> > > --- a/drivers/gpu/drm/msm/msm_submitqueue.c
> > > +++ b/drivers/gpu/drm/msm/msm_submitqueue.c
> > > @@ -49,8 +49,10 @@ void msm_submitqueue_close(struct msm_file_private 
> > > *ctx)
> > >* No lock needed in close and there won't
> > >* be any more user ioctls coming our way
> > >*/
> > > - list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
> > > + list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) {
> > > + list_del(&entry->node);
> >
> > If you refcount ctx, what does that do for the entries in the submit
> > queue?
> >
> > "entry" here is kref'ed, but you're popping it off the list regardless
> > of the put ends up freeing the object or not - which afaict would mean
> > leaking the object.
> >
> 
> What ends up happening is the submit has reference to submit-queue,
> which has reference to the ctx.. the submitqueue could be alive still
> pending in-flight submits (in a later patch), but dead from the PoV of
> userspace interface.
> 
> We aren't relying (or at least aren't in the end, and I *think* I
> didn't miss anything in the middle) relying on ctx->submitqueues list
> to clean anything up in the end, just track what is still a valid
> submitqueue from userspace PoV
> 

Looks reasonable, thanks for the explanation.

> BR,
> -R
> 
> >
> > On the other hand, with the current implementation an object with higher
> > refcount with adjacent objects of single refcount would end up with
> > dangling pointers after the put. So in itself this change seems like a
> > net gain, but I'm wondering about the plan described in the commit
> > message.
> >
> > Regards,
> > Bjorn
> >
> > >   msm_submitqueue_put(entry);
> > > + }
> > >  }
> > >
> > >  int msm_submitqueue_create(struct drm_device *drm, struct 
> > > msm_file_private *ctx,
> > > --
> > > 2.26.2
> > >
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 01/19] drm/msm: remove dangling submitqueue references

2020-08-31 Thread Bjorn Andersson
On Fri 14 Aug 02:40 UTC 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> Currently it doesn't matter, since we free the ctx immediately.  But
> when we start refcnt'ing the ctx, we don't want old dangling list
> entries to hang around.
> 
> Signed-off-by: Rob Clark 

Reviewed-by: Bjorn Andersson 

> ---
>  drivers/gpu/drm/msm/msm_submitqueue.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c 
> b/drivers/gpu/drm/msm/msm_submitqueue.c
> index a1d94be7883a..90c9d84e6155 100644
> --- a/drivers/gpu/drm/msm/msm_submitqueue.c
> +++ b/drivers/gpu/drm/msm/msm_submitqueue.c
> @@ -49,8 +49,10 @@ void msm_submitqueue_close(struct msm_file_private *ctx)
>* No lock needed in close and there won't
>* be any more user ioctls coming our way
>*/
> - list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
> + list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) {
> + list_del(&entry->node);
>   msm_submitqueue_put(entry);
> + }
>  }
>  
>  int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private 
> *ctx,
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 19/19] drm/msm: show process names in gem_describe

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> In $debugfs/gem we already show any vma(s) associated with an object.
> Also show process names if the vma's address space is a per-process
> address space.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_drv.c |  2 +-
>  drivers/gpu/drm/msm/msm_gem.c | 25 +
>  drivers/gpu/drm/msm/msm_gem.h |  5 +
>  drivers/gpu/drm/msm/msm_gem_vma.c |  1 +
>  drivers/gpu/drm/msm/msm_gpu.c |  8 +---
>  drivers/gpu/drm/msm/msm_gpu.h |  2 +-
>  6 files changed, 34 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 8e70d220bba8..8d5c4f98c332 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -597,7 +597,7 @@ static int context_init(struct drm_device *dev, struct 
> drm_file *file)
>   kref_init(&ctx->ref);
>   msm_submitqueue_init(dev, ctx);
>  
> - ctx->aspace = msm_gpu_create_private_address_space(priv->gpu);
> + ctx->aspace = msm_gpu_create_private_address_space(priv->gpu, current);
>   file->driver_priv = ctx;
>  
>   return 0;
> diff --git a/drivers/gpu/drm/msm/msm_gem.c b/drivers/gpu/drm/msm/msm_gem.c
> index 3cb7aeb93fd3..76a6c5271e57 100644
> --- a/drivers/gpu/drm/msm/msm_gem.c
> +++ b/drivers/gpu/drm/msm/msm_gem.c
> @@ -842,11 +842,28 @@ void msm_gem_describe(struct drm_gem_object *obj, 
> struct seq_file *m)
>  
>   seq_puts(m, "  vmas:");
>  
> - list_for_each_entry(vma, &msm_obj->vmas, list)
> - seq_printf(m, " [%s: %08llx,%s,inuse=%d]",
> - vma->aspace != NULL ? vma->aspace->name : NULL,
> - vma->iova, vma->mapped ? "mapped" : "unmapped",
> + list_for_each_entry(vma, &msm_obj->vmas, list) {
> + const char *name, *comm;
> + if (vma->aspace) {
> + struct msm_gem_address_space *aspace = 
> vma->aspace;
> + struct task_struct *task =
> + get_pid_task(aspace->pid, PIDTYPE_PID);
> + if (task) {
> + comm = kstrdup(task->comm, GFP_KERNEL);
> + } else {
> + comm = NULL;
> + }
> + name = aspace->name;
> + } else {
> + name = comm = NULL;
> + }
> + seq_printf(m, " [%s%s%s: aspace=%p, 
> %08llx,%s,inuse=%d]",
> + name, comm ? ":" : "", comm ? comm : "",
> + vma->aspace, vma->iova,
> + vma->mapped ? "mapped" : "unmapped",
>   vma->inuse);
> + kfree(comm);
> + }
>  
>   seq_puts(m, "\n");
>   }
> diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
> index 9c573c4269cb..7b1c7a5f8eef 100644
> --- a/drivers/gpu/drm/msm/msm_gem.h
> +++ b/drivers/gpu/drm/msm/msm_gem.h
> @@ -24,6 +24,11 @@ struct msm_gem_address_space {
>   spinlock_t lock; /* Protects drm_mm node allocation/removal */
>   struct msm_mmu *mmu;
>   struct kref kref;
> +
> + /* For address spaces associated with a specific process, this
> +  * will be non-NULL:
> +  */
> + struct pid *pid;
>  };
>  
>  struct msm_gem_vma {
> diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c 
> b/drivers/gpu/drm/msm/msm_gem_vma.c
> index 29cc1305cf37..80a8a266d68f 100644
> --- a/drivers/gpu/drm/msm/msm_gem_vma.c
> +++ b/drivers/gpu/drm/msm/msm_gem_vma.c
> @@ -17,6 +17,7 @@ msm_gem_address_space_destroy(struct kref *kref)
>   drm_mm_takedown(&aspace->mm);
>   if (aspace->mmu)
>   aspace->mmu->funcs->destroy(aspace->mmu);
> + put_pid(aspace->pid);
>   kfree(aspace);
>  }
>  
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index 951850804d77..ac8961187a73 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -825,10 +825,9 @@ static int get_clocks(struct platform_device *pdev, 
> struct msm_gpu *gpu)
>  
>  /* Return a new address space for a msm_drm_private instance */
>  struct msm_gem_address_space *
> -msm_gpu_create_private_address_space(struct msm_gpu *gpu)
> +msm_gpu_create_private_address_space(struct msm_gpu *gpu, struct task_struct 
> *task)
>  {
>   struct msm_gem_address_space *aspace = NULL;
> -
>   if (!gpu)
>   return NULL;
>  
> @@ -836,8 +835,11 @@ msm_gpu_create_private_address_space(struct msm_gpu *gpu)
>* If the target doesn't support private address spaces then return
>* the global one
>*/
> - if (gpu->funcs->create_priva

Re: [PATCH 18/19] iommu/arm-smmu: add a way for implementations to influence SCTLR

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> For the Adreno GPU's SMMU, we want SCTLR.HUPCF set to ensure that
> pending translations are not terminated on iova fault.  Otherwise
> a terminated CP read could hang the GPU by returning invalid
> command-stream data.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Rob Clark 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 6 ++
>  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 3 +++
>  drivers/iommu/arm/arm-smmu/arm-smmu.h  | 3 +++
>  3 files changed, 12 insertions(+)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index 5640d9960610..2aa6249050ff 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -127,6 +127,12 @@ static int qcom_adreno_smmu_init_context(struct 
> arm_smmu_domain *smmu_domain,
>   (smmu_domain->cfg.fmt == ARM_SMMU_CTX_FMT_AARCH64))
>   pgtbl_cfg->quirks |= IO_PGTABLE_QUIRK_ARM_TTBR1;
>  
> + /*
> +  * On the GPU device we want to process subsequent transactions after a
> +  * fault to keep the GPU from hanging
> +  */
> + smmu_domain->cfg.sctlr_set |= ARM_SMMU_SCTLR_HUPCF;
> +
>   /*
>* Initialize private interface with GPU:
>*/
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index e63a480d7f71..bbec5793faf8 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -617,6 +617,9 @@ void arm_smmu_write_context_bank(struct arm_smmu_device 
> *smmu, int idx)
>   if (IS_ENABLED(CONFIG_CPU_BIG_ENDIAN))
>   reg |= ARM_SMMU_SCTLR_E;
>  
> + reg |= cfg->sctlr_set;
> + reg &= ~cfg->sctlr_clr;
> +
>   arm_smmu_cb_write(smmu, idx, ARM_SMMU_CB_SCTLR, reg);
>  }
>  
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index cd75a33967bb..2df3a70a8a41 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -144,6 +144,7 @@ enum arm_smmu_cbar_type {
>  #define ARM_SMMU_CB_SCTLR0x0
>  #define ARM_SMMU_SCTLR_S1_ASIDPNEBIT(12)
>  #define ARM_SMMU_SCTLR_CFCFG BIT(7)
> +#define ARM_SMMU_SCTLR_HUPCF BIT(8)
>  #define ARM_SMMU_SCTLR_CFIE  BIT(6)
>  #define ARM_SMMU_SCTLR_CFRE  BIT(5)
>  #define ARM_SMMU_SCTLR_E BIT(4)
> @@ -341,6 +342,8 @@ struct arm_smmu_cfg {
>   u16 asid;
>   u16 vmid;
>   };
> + u32 sctlr_set;/* extra bits to set in 
> SCTLR */
> + u32 sctlr_clr;/* bits to mask in SCTLR 
> */
>   enum arm_smmu_cbar_type cbar;
>   enum arm_smmu_context_fmt   fmt;
>  };
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 15/19] drm/msm: Add support for private address space instances

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Add support for allocating private address space instances. Targets that
> support per-context pagetables should implement their own function to
> allocate private address spaces.
> 
> The default will return a pointer to the global address space.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_drv.c | 13 +++--
>  drivers/gpu/drm/msm/msm_drv.h |  5 +
>  drivers/gpu/drm/msm/msm_gem_vma.c |  9 +
>  drivers/gpu/drm/msm/msm_gpu.c | 22 ++
>  drivers/gpu/drm/msm/msm_gpu.h |  5 +
>  5 files changed, 48 insertions(+), 6 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 01845a3b8d52..8e70d220bba8 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -597,7 +597,7 @@ static int context_init(struct drm_device *dev, struct 
> drm_file *file)
>   kref_init(&ctx->ref);
>   msm_submitqueue_init(dev, ctx);
>  
> - ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL;
> + ctx->aspace = msm_gpu_create_private_address_space(priv->gpu);
>   file->driver_priv = ctx;
>  
>   return 0;
> @@ -780,18 +780,19 @@ static int msm_ioctl_gem_cpu_fini(struct drm_device 
> *dev, void *data,
>  }
>  
>  static int msm_ioctl_gem_info_iova(struct drm_device *dev,
> - struct drm_gem_object *obj, uint64_t *iova)
> + struct drm_file *file, struct drm_gem_object *obj,
> + uint64_t *iova)
>  {
> - struct msm_drm_private *priv = dev->dev_private;
> + struct msm_file_private *ctx = file->driver_priv;
>  
> - if (!priv->gpu)
> + if (!ctx->aspace)
>   return -EINVAL;
>  
>   /*
>* Don't pin the memory here - just get an address so that userspace can
>* be productive
>*/
> - return msm_gem_get_iova(obj, priv->gpu->aspace, iova);
> + return msm_gem_get_iova(obj, ctx->aspace, iova);
>  }
>  
>  static int msm_ioctl_gem_info(struct drm_device *dev, void *data,
> @@ -830,7 +831,7 @@ static int msm_ioctl_gem_info(struct drm_device *dev, 
> void *data,
>   args->value = msm_gem_mmap_offset(obj);
>   break;
>   case MSM_INFO_GET_IOVA:
> - ret = msm_ioctl_gem_info_iova(dev, obj, &args->value);
> + ret = msm_ioctl_gem_info_iova(dev, file, obj, &args->value);
>   break;
>   case MSM_INFO_SET_NAME:
>   /* length check should leave room for terminating null: */
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index 4561bfb5e745..2ca9c3c03845 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -249,6 +249,10 @@ int msm_gem_map_vma(struct msm_gem_address_space *aspace,
>  void msm_gem_close_vma(struct msm_gem_address_space *aspace,
>   struct msm_gem_vma *vma);
>  
> +
> +struct msm_gem_address_space *
> +msm_gem_address_space_get(struct msm_gem_address_space *aspace);
> +
>  void msm_gem_address_space_put(struct msm_gem_address_space *aspace);
>  
>  struct msm_gem_address_space *
> @@ -434,6 +438,7 @@ static inline void __msm_file_private_destroy(struct kref 
> *kref)
>   struct msm_file_private *ctx = container_of(kref,
>   struct msm_file_private, ref);
>  
> + msm_gem_address_space_put(ctx->aspace);
>   kfree(ctx);
>  }
>  
> diff --git a/drivers/gpu/drm/msm/msm_gem_vma.c 
> b/drivers/gpu/drm/msm/msm_gem_vma.c
> index 5f6a11211b64..29cc1305cf37 100644
> --- a/drivers/gpu/drm/msm/msm_gem_vma.c
> +++ b/drivers/gpu/drm/msm/msm_gem_vma.c
> @@ -27,6 +27,15 @@ void msm_gem_address_space_put(struct 
> msm_gem_address_space *aspace)
>   kref_put(&aspace->kref, msm_gem_address_space_destroy);
>  }
>  
> +struct msm_gem_address_space *
> +msm_gem_address_space_get(struct msm_gem_address_space *aspace)
> +{
> + if (!IS_ERR_OR_NULL(aspace))
> + kref_get(&aspace->kref);
> +
> + return aspace;
> +}
> +
>  /* Actually unmap memory for the vma */
>  void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
>   struct msm_gem_vma *vma)
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index e1a3cbe25a0c..951850804d77 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -823,6 +823,28 @@ static int get_clocks(struct platform_device *pdev, 
> struct msm_gpu *gpu)
>   return 0;
>  }
>  
> +/* Return a new address space for a msm_drm_private instance */
> +struct msm_gem_address_space *
> +msm_gpu_create_private_address_space(struct msm_gpu *gpu)
> +{
> + struct msm_gem_address_space *aspace = NULL;
> +
> + if (!gpu)
> + return NULL;
> +
> + /*
> +  * If the target doesn't support private address spaces then return
> +  * the global one
> +   

Re: [PATCH 14/19] drm/msm: Add support to create a local pagetable

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Add support to create a io-pgtable for use by targets that support
> per-instance pagetables. In order to support per-instance pagetables the
> GPU SMMU device needs to have the qcom,adreno-smmu compatible string and
> split pagetables enabled.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_gpummu.c |   2 +-
>  drivers/gpu/drm/msm/msm_iommu.c  | 199 ++-
>  drivers/gpu/drm/msm/msm_mmu.h|  16 ++-
>  3 files changed, 214 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_gpummu.c 
> b/drivers/gpu/drm/msm/msm_gpummu.c
> index 310a31b05faa..aab121f4beb7 100644
> --- a/drivers/gpu/drm/msm/msm_gpummu.c
> +++ b/drivers/gpu/drm/msm/msm_gpummu.c
> @@ -102,7 +102,7 @@ struct msm_mmu *msm_gpummu_new(struct device *dev, struct 
> msm_gpu *gpu)
>   }
>  
>   gpummu->gpu = gpu;
> - msm_mmu_init(&gpummu->base, dev, &funcs);
> + msm_mmu_init(&gpummu->base, dev, &funcs, MSM_MMU_GPUMMU);
>  
>   return &gpummu->base;
>  }
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index 1b6635504069..697cc0a059d6 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
> @@ -4,15 +4,210 @@
>   * Author: Rob Clark 
>   */
>  
> +#include 
> +#include 
>  #include "msm_drv.h"
>  #include "msm_mmu.h"
>  
>  struct msm_iommu {
>   struct msm_mmu base;
>   struct iommu_domain *domain;
> + atomic_t pagetables;
>  };
> +
>  #define to_msm_iommu(x) container_of(x, struct msm_iommu, base)
>  
> +struct msm_iommu_pagetable {
> + struct msm_mmu base;
> + struct msm_mmu *parent;
> + struct io_pgtable_ops *pgtbl_ops;
> + phys_addr_t ttbr;
> + u32 asid;
> +};
> +static struct msm_iommu_pagetable *to_pagetable(struct msm_mmu *mmu)
> +{
> + return container_of(mmu, struct msm_iommu_pagetable, base);
> +}
> +
> +static int msm_iommu_pagetable_unmap(struct msm_mmu *mmu, u64 iova,
> + size_t size)
> +{
> + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu);
> + struct io_pgtable_ops *ops = pagetable->pgtbl_ops;
> + size_t unmapped = 0;
> +
> + /* Unmap the block one page at a time */
> + while (size) {
> + unmapped += ops->unmap(ops, iova, 4096, NULL);
> + iova += 4096;
> + size -= 4096;
> + }
> +
> + iommu_flush_tlb_all(to_msm_iommu(pagetable->parent)->domain);
> +
> + return (unmapped == size) ? 0 : -EINVAL;
> +}
> +
> +static int msm_iommu_pagetable_map(struct msm_mmu *mmu, u64 iova,
> + struct sg_table *sgt, size_t len, int prot)
> +{
> + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu);
> + struct io_pgtable_ops *ops = pagetable->pgtbl_ops;
> + struct scatterlist *sg;
> + size_t mapped = 0;
> + u64 addr = iova;
> + unsigned int i;
> +
> + for_each_sg(sgt->sgl, sg, sgt->nents, i) {
> + size_t size = sg->length;
> + phys_addr_t phys = sg_phys(sg);
> +
> + /* Map the block one page at a time */
> + while (size) {
> + if (ops->map(ops, addr, phys, 4096, prot, GFP_KERNEL)) {
> + msm_iommu_pagetable_unmap(mmu, iova, mapped);
> + return -EINVAL;
> + }
> +
> + phys += 4096;
> + addr += 4096;
> + size -= 4096;
> + mapped += 4096;
> + }
> + }
> +
> + return 0;
> +}
> +
> +static void msm_iommu_pagetable_destroy(struct msm_mmu *mmu)
> +{
> + struct msm_iommu_pagetable *pagetable = to_pagetable(mmu);
> + struct msm_iommu *iommu = to_msm_iommu(pagetable->parent);
> + struct adreno_smmu_priv *adreno_smmu =
> + dev_get_drvdata(pagetable->parent->dev);
> +
> + /*
> +  * If this is the last attached pagetable for the parent,
> +  * disable TTBR0 in the arm-smmu driver
> +  */
> + if (atomic_dec_return(&iommu->pagetables) == 0)
> + adreno_smmu->set_ttbr0_cfg(adreno_smmu->cookie, NULL);
> +
> + free_io_pgtable_ops(pagetable->pgtbl_ops);
> + kfree(pagetable);
> +}
> +
> +int msm_iommu_pagetable_params(struct msm_mmu *mmu,
> + phys_addr_t *ttbr, int *asid)
> +{
> + struct msm_iommu_pagetable *pagetable;
> +
> + if (mmu->type != MSM_MMU_IOMMU_PAGETABLE)
> + return -EINVAL;
> +
> + pagetable = to_pagetable(mmu);
> +
> + if (ttbr)
> + *ttbr = pagetable->ttbr;
> +
> + if (asid)
> + *asid = pagetable->asid;
> +
> + return 0;
> +}
> +
> +static const struct msm_mmu_funcs pagetable_funcs = {
> + .map = msm_iommu_pagetable_map,
> + .unmap = msm_iommu_pagetable_unmap,
> + .destroy = msm_iommu_pagetable_destroy,
> 

Re: [PATCH 13/19] drm/msm: Set the global virtual address range from the IOMMU domain

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Use the aperture settings from the IOMMU domain to set up the virtual
> address range for the GPU. This allows us to transparently deal with
> IOMMU side features (like split pagetables).
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c | 13 +++--
>  drivers/gpu/drm/msm/msm_iommu.c |  7 +++
>  2 files changed, 18 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index 533a34b4cce2..34e6242c1767 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -192,9 +192,18 @@ adreno_iommu_create_address_space(struct msm_gpu *gpu,
>   struct iommu_domain *iommu = iommu_domain_alloc(&platform_bus_type);
>   struct msm_mmu *mmu = msm_iommu_new(&pdev->dev, iommu);
>   struct msm_gem_address_space *aspace;
> + u64 start, size;
>  
> - aspace = msm_gem_address_space_create(mmu, "gpu", SZ_16M,
> - 0x - SZ_16M);
> + /*
> +  * Use the aperture start or SZ_16M, whichever is greater. This will
> +  * ensure that we align with the allocated pagetable range while still
> +  * allowing room in the lower 32 bits for GMEM and whatnot
> +  */
> + start = max_t(u64, SZ_16M, iommu->geometry.aperture_start);
> + size = iommu->geometry.aperture_end - start + 1;
> +
> + aspace = msm_gem_address_space_create(mmu, "gpu",
> + start & GENMASK(48, 0), size);
>  
>   if (IS_ERR(aspace) && !IS_ERR(mmu))
>   mmu->funcs->destroy(mmu);
> diff --git a/drivers/gpu/drm/msm/msm_iommu.c b/drivers/gpu/drm/msm/msm_iommu.c
> index 3a381a9674c9..1b6635504069 100644
> --- a/drivers/gpu/drm/msm/msm_iommu.c
> +++ b/drivers/gpu/drm/msm/msm_iommu.c
> @@ -36,6 +36,10 @@ static int msm_iommu_map(struct msm_mmu *mmu, uint64_t 
> iova,
>   struct msm_iommu *iommu = to_msm_iommu(mmu);
>   size_t ret;
>  
> + /* The arm-smmu driver expects the addresses to be sign extended */
> + if (iova & BIT_ULL(48))
> + iova |= GENMASK_ULL(63, 49);
> +
>   ret = iommu_map_sg(iommu->domain, iova, sgt->sgl, sgt->nents, prot);
>   WARN_ON(!ret);
>  
> @@ -46,6 +50,9 @@ static int msm_iommu_unmap(struct msm_mmu *mmu, uint64_t 
> iova, size_t len)
>  {
>   struct msm_iommu *iommu = to_msm_iommu(mmu);
>  
> + if (iova & BIT_ULL(48))
> + iova |= GENMASK_ULL(63, 49);
> +
>   iommu_unmap(iommu->domain, iova, len);
>  
>   return 0;
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 12/19] drm/msm: Drop context arg to gpu->submit()

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Now that we can get the ctx from the submitqueue, the extra arg is
> redundant.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Jordan Crouse 
> [split out of previous patch to reduce churny noise]
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/a5xx_gpu.c   | 12 +---
>  drivers/gpu/drm/msm/adreno/a6xx_gpu.c   |  5 ++---
>  drivers/gpu/drm/msm/adreno/adreno_gpu.c |  5 ++---
>  drivers/gpu/drm/msm/adreno/adreno_gpu.h |  3 +--
>  drivers/gpu/drm/msm/msm_gem_submit.c|  2 +-
>  drivers/gpu/drm/msm/msm_gpu.c   |  9 -
>  drivers/gpu/drm/msm/msm_gpu.h   |  6 ++
>  7 files changed, 17 insertions(+), 25 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> index 9e63a190642c..eff2439ea57b 100644
> --- a/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a5xx_gpu.c
> @@ -43,8 +43,7 @@ static void a5xx_flush(struct msm_gpu *gpu, struct 
> msm_ringbuffer *ring)
>   gpu_write(gpu, REG_A5XX_CP_RB_WPTR, wptr);
>  }
>  
> -static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit 
> *submit,
> - struct msm_file_private *ctx)
> +static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct msm_gem_submit 
> *submit)
>  {
>   struct msm_drm_private *priv = gpu->dev->dev_private;
>   struct msm_ringbuffer *ring = submit->ring;
> @@ -57,7 +56,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit
>   case MSM_SUBMIT_CMD_IB_TARGET_BUF:
>   break;
>   case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
> - if (priv->lastctx == ctx)
> + if (priv->lastctx == submit->queue->ctx)
>   break;
>   /* fall-thru */
>   case MSM_SUBMIT_CMD_BUF:
> @@ -103,8 +102,7 @@ static void a5xx_submit_in_rb(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit
>   msm_gpu_retire(gpu);
>  }
>  
> -static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
> - struct msm_file_private *ctx)
> +static void a5xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gpu(gpu);
>   struct a5xx_gpu *a5xx_gpu = to_a5xx_gpu(adreno_gpu);
> @@ -114,7 +112,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>  
>   if (IS_ENABLED(CONFIG_DRM_MSM_GPU_SUDO) && submit->in_rb) {
>   priv->lastctx = NULL;
> - a5xx_submit_in_rb(gpu, submit, ctx);
> + a5xx_submit_in_rb(gpu, submit);
>   return;
>   }
>  
> @@ -148,7 +146,7 @@ static void a5xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>   case MSM_SUBMIT_CMD_IB_TARGET_BUF:
>   break;
>   case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
> - if (priv->lastctx == ctx)
> + if (priv->lastctx == submit->queue->ctx)
>   break;
>   /* fall-thru */
>   case MSM_SUBMIT_CMD_BUF:
> diff --git a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c 
> b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> index c5a3e4d4c007..5eabb0109577 100644
> --- a/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/a6xx_gpu.c
> @@ -81,8 +81,7 @@ static void get_stats_counter(struct msm_ringbuffer *ring, 
> u32 counter,
>   OUT_RING(ring, upper_32_bits(iova));
>  }
>  
> -static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
> - struct msm_file_private *ctx)
> +static void a6xx_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>  {
>   unsigned int index = submit->seqno % MSM_GPU_SUBMIT_STATS_COUNT;
>   struct msm_drm_private *priv = gpu->dev->dev_private;
> @@ -115,7 +114,7 @@ static void a6xx_submit(struct msm_gpu *gpu, struct 
> msm_gem_submit *submit,
>   case MSM_SUBMIT_CMD_IB_TARGET_BUF:
>   break;
>   case MSM_SUBMIT_CMD_CTX_RESTORE_BUF:
> - if (priv->lastctx == ctx)
> + if (priv->lastctx == submit->queue->ctx)
>   break;
>   /* fall-thru */
>   case MSM_SUBMIT_CMD_BUF:
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_gpu.c 
> b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> index d2dbb6968cba..533a34b4cce2 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_gpu.c
> @@ -457,8 +457,7 @@ void adreno_recover(struct msm_gpu *gpu)
>   }
>  }
>  
> -void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit,
> - struct msm_file_private *ctx)
> +void adreno_submit(struct msm_gpu *gpu, struct msm_gem_submit *submit)
>  {
>   struct adreno_gpu *adreno_gpu = to_adreno_gp

Re: [PATCH v1] iommu/vt-d: Move intel_iommu_gfx_mapped to Intel IOMMU header

2020-08-31 Thread Lu Baolu

Hi Andy,

On 8/29/20 12:12 AM, Andy Shevchenko wrote:

Static analyzer is not happy about intel_iommu_gfx_mapped declaration:

.../drivers/iommu/intel/iommu.c:364:5: warning: symbol 'intel_iommu_gfx_mapped' 
was not declared. Should it be static?

Move its declaration to Intel IOMMU header file.

Signed-off-by: Andy Shevchenko 
---
  include/drm/intel-gtt.h | 5 +
  include/linux/intel-iommu.h | 1 +
  2 files changed, 2 insertions(+), 4 deletions(-)

diff --git a/include/drm/intel-gtt.h b/include/drm/intel-gtt.h
index 71d81923e6b0..abfefaaf897a 100644
--- a/include/drm/intel-gtt.h
+++ b/include/drm/intel-gtt.h
@@ -5,6 +5,7 @@
  #define   _DRM_INTEL_GTT_H
  
  #include 

+#include 
  #include 
  
  void intel_gtt_get(u64 *gtt_total,

@@ -33,8 +34,4 @@ void intel_gtt_clear_range(unsigned int first_entry, unsigned 
int num_entries);
  /* flag for GFDT type */
  #define AGP_USER_CACHED_MEMORY_GFDT (1 << 3)
  
-#ifdef CONFIG_INTEL_IOMMU

-extern int intel_iommu_gfx_mapped;
-#endif
-
  #endif
diff --git a/include/linux/intel-iommu.h b/include/linux/intel-iommu.h
index 64fa5c56c825..fbd3bb64649b 100644
--- a/include/linux/intel-iommu.h
+++ b/include/linux/intel-iommu.h
@@ -794,6 +794,7 @@ extern int iommu_calculate_max_sagaw(struct intel_iommu 
*iommu);
  extern int dmar_disabled;
  extern int intel_iommu_enabled;
  extern int intel_iommu_tboot_noforce;
+extern int intel_iommu_gfx_mapped;
  #else
  static inline int iommu_calculate_agaw(struct intel_iommu *iommu)
  {



Looks good to me.

Reviewed-by: Lu Baolu 

Best regards,
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 11/19] drm/msm: Add a context pointer to the submitqueue

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Each submitqueue is attached to a context. Add a pointer to the
> context to the submitqueue at create time and refcount it so
> that it stays around through the life of the queue.
> 

Reviewed-by: Bjorn Andersson 


> Co-developed-by: Rob Clark 
> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_drv.c |  3 ++-
>  drivers/gpu/drm/msm/msm_drv.h | 20 
>  drivers/gpu/drm/msm/msm_gem.h |  1 +
>  drivers/gpu/drm/msm/msm_gem_submit.c  |  6 +++---
>  drivers/gpu/drm/msm/msm_gpu.h |  1 +
>  drivers/gpu/drm/msm/msm_submitqueue.c |  3 +++
>  6 files changed, 30 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_drv.c b/drivers/gpu/drm/msm/msm_drv.c
> index 7d641c7e3514..01845a3b8d52 100644
> --- a/drivers/gpu/drm/msm/msm_drv.c
> +++ b/drivers/gpu/drm/msm/msm_drv.c
> @@ -594,6 +594,7 @@ static int context_init(struct drm_device *dev, struct 
> drm_file *file)
>   if (!ctx)
>   return -ENOMEM;
>  
> + kref_init(&ctx->ref);
>   msm_submitqueue_init(dev, ctx);
>  
>   ctx->aspace = priv->gpu ? priv->gpu->aspace : NULL;
> @@ -615,7 +616,7 @@ static int msm_open(struct drm_device *dev, struct 
> drm_file *file)
>  static void context_close(struct msm_file_private *ctx)
>  {
>   msm_submitqueue_close(ctx);
> - kfree(ctx);
> + msm_file_private_put(ctx);
>  }
>  
>  static void msm_postclose(struct drm_device *dev, struct drm_file *file)
> diff --git a/drivers/gpu/drm/msm/msm_drv.h b/drivers/gpu/drm/msm/msm_drv.h
> index af259b0573ea..4561bfb5e745 100644
> --- a/drivers/gpu/drm/msm/msm_drv.h
> +++ b/drivers/gpu/drm/msm/msm_drv.h
> @@ -57,6 +57,7 @@ struct msm_file_private {
>   struct list_head submitqueues;
>   int queueid;
>   struct msm_gem_address_space *aspace;
> + struct kref ref;
>  };
>  
>  enum msm_mdp_plane_property {
> @@ -428,6 +429,25 @@ void msm_submitqueue_close(struct msm_file_private *ctx);
>  
>  void msm_submitqueue_destroy(struct kref *kref);
>  
> +static inline void __msm_file_private_destroy(struct kref *kref)
> +{
> + struct msm_file_private *ctx = container_of(kref,
> + struct msm_file_private, ref);
> +
> + kfree(ctx);
> +}
> +
> +static inline void msm_file_private_put(struct msm_file_private *ctx)
> +{
> + kref_put(&ctx->ref, __msm_file_private_destroy);
> +}
> +
> +static inline struct msm_file_private *msm_file_private_get(
> + struct msm_file_private *ctx)
> +{
> + kref_get(&ctx->ref);
> + return ctx;
> +}
>  
>  #define DBG(fmt, ...) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
>  #define VERB(fmt, ...) if (0) DRM_DEBUG_DRIVER(fmt"\n", ##__VA_ARGS__)
> diff --git a/drivers/gpu/drm/msm/msm_gem.h b/drivers/gpu/drm/msm/msm_gem.h
> index 972490b14ba5..9c573c4269cb 100644
> --- a/drivers/gpu/drm/msm/msm_gem.h
> +++ b/drivers/gpu/drm/msm/msm_gem.h
> @@ -142,6 +142,7 @@ struct msm_gem_submit {
>   bool valid; /* true if no cmdstream patching needed */
>   bool in_rb; /* "sudo" mode, copy cmds into RB */
>   struct msm_ringbuffer *ring;
> + struct msm_file_private *ctx;
>   unsigned int nr_cmds;
>   unsigned int nr_bos;
>   u32 ident; /* A "identifier" for the submit for logging */
> diff --git a/drivers/gpu/drm/msm/msm_gem_submit.c 
> b/drivers/gpu/drm/msm/msm_gem_submit.c
> index 8cb9aa15ff90..1464b04d25d3 100644
> --- a/drivers/gpu/drm/msm/msm_gem_submit.c
> +++ b/drivers/gpu/drm/msm/msm_gem_submit.c
> @@ -27,7 +27,7 @@
>  #define BO_PINNED   0x2000
>  
>  static struct msm_gem_submit *submit_create(struct drm_device *dev,
> - struct msm_gpu *gpu, struct msm_gem_address_space *aspace,
> + struct msm_gpu *gpu,
>   struct msm_gpu_submitqueue *queue, uint32_t nr_bos,
>   uint32_t nr_cmds)
>  {
> @@ -43,7 +43,7 @@ static struct msm_gem_submit *submit_create(struct 
> drm_device *dev,
>   return NULL;
>  
>   submit->dev = dev;
> - submit->aspace = aspace;
> + submit->aspace = queue->ctx->aspace;
>   submit->gpu = gpu;
>   submit->fence = NULL;
>   submit->cmd = (void *)&submit->bos[nr_bos];
> @@ -677,7 +677,7 @@ int msm_ioctl_gem_submit(struct drm_device *dev, void 
> *data,
>   }
>   }
>  
> - submit = submit_create(dev, gpu, ctx->aspace, queue, args->nr_bos,
> + submit = submit_create(dev, gpu, queue, args->nr_bos,
>   args->nr_cmds);
>   if (!submit) {
>   ret = -ENOMEM;
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index f91b141add75..97c527e98391 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -190,6 +190,7 @@ struct msm_gpu_submitqueue {
>   u32 flags;
>   u32 prio;
>   int faults;
> + struct msm_file_private *ctx;
>   struct list_head node;
>   

Re: [PATCH 09/19] iommu/arm-smmu-qcom: Add implementation for the adreno GPU SMMU

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Add a special implementation for the SMMU attached to most Adreno GPU
> target triggered from the qcom,adreno-smmu compatible string.
> 
> The new Adreno SMMU implementation will enable split pagetables
> (TTBR1) for the domain attached to the GPU device (SID 0) and
> hard code it context bank 0 so the GPU hardware can implement
> per-instance pagetables.
> 

Reviewed-by: Bjorn Andersson 

> Co-developed-by: Rob Clark 
> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-impl.c |   3 +
>  drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c | 149 -
>  drivers/iommu/arm/arm-smmu/arm-smmu.h  |   1 +
>  3 files changed, 151 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> index 88f17cc33023..d199b4bff15d 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> @@ -223,6 +223,9 @@ struct arm_smmu_device *arm_smmu_impl_init(struct 
> arm_smmu_device *smmu)
>   of_device_is_compatible(np, "qcom,sm8250-smmu-500"))
>   return qcom_smmu_impl_init(smmu);
>  
> + if (of_device_is_compatible(smmu->dev->of_node, "qcom,adreno-smmu"))
> + return qcom_adreno_smmu_impl_init(smmu);
> +
>   if (of_device_is_compatible(np, "marvell,ap806-smmu-500"))
>   smmu->impl = &mrvl_mmu500_impl;
>  
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> index be4318044f96..5640d9960610 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-qcom.c
> @@ -3,6 +3,7 @@
>   * Copyright (c) 2019, The Linux Foundation. All rights reserved.
>   */
>  
> +#include 
>  #include 
>  #include 
>  
> @@ -12,6 +13,132 @@ struct qcom_smmu {
>   struct arm_smmu_device smmu;
>  };
>  
> +#define QCOM_ADRENO_SMMU_GPU_SID 0
> +
> +static bool qcom_adreno_smmu_is_gpu_device(struct device *dev)
> +{
> + struct iommu_fwspec *fwspec = dev_iommu_fwspec_get(dev);
> + int i;
> +
> + /*
> +  * The GPU will always use SID 0 so that is a handy way to uniquely
> +  * identify it and configure it for per-instance pagetables
> +  */
> + for (i = 0; i < fwspec->num_ids; i++) {
> + u16 sid = FIELD_GET(ARM_SMMU_SMR_ID, fwspec->ids[i]);
> +
> + if (sid == QCOM_ADRENO_SMMU_GPU_SID)
> + return true;
> + }
> +
> + return false;
> +}
> +
> +static const struct io_pgtable_cfg *qcom_adreno_smmu_get_ttbr1_cfg(
> + const void *cookie)
> +{
> + struct arm_smmu_domain *smmu_domain = (void *)cookie;
> + struct io_pgtable *pgtable =
> + io_pgtable_ops_to_pgtable(smmu_domain->pgtbl_ops);
> + return &pgtable->cfg;
> +}
> +
> +/*
> + * Local implementation to configure TTBR0 with the specified pagetable 
> config.
> + * The GPU driver will call this to enable TTBR0 when per-instance pagetables
> + * are active
> + */
> +
> +static int qcom_adreno_smmu_set_ttbr0_cfg(const void *cookie,
> + const struct io_pgtable_cfg *pgtbl_cfg)
> +{
> + struct arm_smmu_domain *smmu_domain = (void *)cookie;
> + struct io_pgtable *pgtable = 
> io_pgtable_ops_to_pgtable(smmu_domain->pgtbl_ops);
> + struct arm_smmu_cfg *cfg = &smmu_domain->cfg;
> + struct arm_smmu_cb *cb = &smmu_domain->smmu->cbs[cfg->cbndx];
> +
> + /* The domain must have split pagetables already enabled */
> + if (cb->tcr[0] & ARM_SMMU_TCR_EPD1)
> + return -EINVAL;
> +
> + /* If the pagetable config is NULL, disable TTBR0 */
> + if (!pgtbl_cfg) {
> + /* Do nothing if it is already disabled */
> + if ((cb->tcr[0] & ARM_SMMU_TCR_EPD0))
> + return -EINVAL;
> +
> + /* Set TCR to the original configuration */
> + cb->tcr[0] = arm_smmu_lpae_tcr(&pgtable->cfg);
> + cb->ttbr[0] = FIELD_PREP(ARM_SMMU_TTBRn_ASID, cb->cfg->asid);
> + } else {
> + u32 tcr = cb->tcr[0];
> +
> + /* Don't call this again if TTBR0 is already enabled */
> + if (!(cb->tcr[0] & ARM_SMMU_TCR_EPD0))
> + return -EINVAL;
> +
> + tcr |= arm_smmu_lpae_tcr(pgtbl_cfg);
> + tcr &= ~(ARM_SMMU_TCR_EPD0 | ARM_SMMU_TCR_EPD1);
> +
> + cb->tcr[0] = tcr;
> + cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> + cb->ttbr[0] |= FIELD_PREP(ARM_SMMU_TTBRn_ASID, cb->cfg->asid);
> + }
> +
> + arm_smmu_write_context_bank(smmu_domain->smmu, cb->cfg->cbndx);
> +
> + return 0;
> +}
> +
> +static int qcom_adreno_smmu_alloc_context_bank(struct arm_smmu_domain 
> *smmu_domain,
> + struct device *dev, int start, int count)
> +{
> + struct arm_smmu_device *smmu = smmu_domain->smm

Re: [PATCH 10/19] dt-bindings: arm-smmu: Add compatible string for Adreno GPU SMMU

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Every Qcom Adreno GPU has an embedded SMMU for its own use. These
> devices depend on unique features such as split pagetables,
> different stall/halt requirements and other settings. Identify them
> with a compatible string so that they can be identified in the
> arm-smmu implementation specific code.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Jordan Crouse 
> Reviewed-by: Rob Herring 
> Signed-off-by: Rob Clark 
> ---
>  Documentation/devicetree/bindings/iommu/arm,smmu.yaml | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml 
> b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> index 503160a7b9a0..5ec5d0d691f6 100644
> --- a/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> +++ b/Documentation/devicetree/bindings/iommu/arm,smmu.yaml
> @@ -40,6 +40,10 @@ properties:
>- qcom,sm8150-smmu-500
>- qcom,sm8250-smmu-500
>- const: arm,mmu-500
> +  - description: Qcom Adreno GPUs implementing "arm,smmu-v2"
> +items:
> +  - const: qcom,adreno-smmu
> +  - const: qcom,smmu-v2
>- description: Marvell SoCs implementing "arm,mmu-500"
>  items:
>- const: marvell,ap806-smmu-500
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 07/19] drm/msm: set adreno_smmu as gpu's drvdata

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> This will be populated by adreno-smmu, to provide a way for coordinating
> enabling/disabling TTBR0 translation.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/adreno_device.c | 2 --
>  drivers/gpu/drm/msm/msm_gpu.c  | 2 +-
>  drivers/gpu/drm/msm/msm_gpu.h  | 6 +-
>  3 files changed, 6 insertions(+), 4 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 26664e1b30c0..58e03b20e1c7 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -417,8 +417,6 @@ static int adreno_bind(struct device *dev, struct device 
> *master, void *data)
>   return PTR_ERR(gpu);
>   }
>  
> - dev_set_drvdata(dev, gpu);
> -
>   return 0;
>  }
>  
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index 6aa9e04e52e7..806eb0957280 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -892,7 +892,7 @@ int msm_gpu_init(struct drm_device *drm, struct 
> platform_device *pdev,
>   gpu->gpu_cx = NULL;
>  
>   gpu->pdev = pdev;
> - platform_set_drvdata(pdev, gpu);
> + platform_set_drvdata(pdev, &gpu->adreno_smmu);
>  
>   msm_devfreq_init(gpu);
>  
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index 8bda7beaed4b..f91b141add75 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -7,6 +7,7 @@
>  #ifndef __MSM_GPU_H__
>  #define __MSM_GPU_H__
>  
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -73,6 +74,8 @@ struct msm_gpu {
>   struct platform_device *pdev;
>   const struct msm_gpu_funcs *funcs;
>  
> + struct adreno_smmu_priv adreno_smmu;
> +
>   /* performance counters (hw & sw): */
>   spinlock_t perf_lock;
>   bool perfcntr_active;
> @@ -143,7 +146,8 @@ struct msm_gpu {
>  
>  static inline struct msm_gpu *dev_to_gpu(struct device *dev)
>  {
> - return dev_get_drvdata(dev);
> + struct adreno_smmu_priv *adreno_smmu = dev_get_drvdata(dev);
> + return container_of(adreno_smmu, struct msm_gpu, adreno_smmu);
>  }
>  
>  /* It turns out that all targets use the same ringbuffer size */
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 08/19] iommu/arm-smmu: constify some helpers

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> Sprinkle a few `const`s where helpers don't need write access.
> 

Reviewed-by: Bjorn Andersson 

> Signed-off-by: Rob Clark 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu.h | 6 +++---
>  1 file changed, 3 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index 59ff3fc5c6c8..27c8fc50 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -377,7 +377,7 @@ struct arm_smmu_master_cfg {
>   s16 smendx[];
>  };
>  
> -static inline u32 arm_smmu_lpae_tcr(struct io_pgtable_cfg *cfg)
> +static inline u32 arm_smmu_lpae_tcr(const struct io_pgtable_cfg *cfg)
>  {
>   u32 tcr = FIELD_PREP(ARM_SMMU_TCR_TG0, cfg->arm_lpae_s1_cfg.tcr.tg) |
>   FIELD_PREP(ARM_SMMU_TCR_SH0, cfg->arm_lpae_s1_cfg.tcr.sh) |
> @@ -398,13 +398,13 @@ static inline u32 arm_smmu_lpae_tcr(struct 
> io_pgtable_cfg *cfg)
>   return tcr;
>  }
>  
> -static inline u32 arm_smmu_lpae_tcr2(struct io_pgtable_cfg *cfg)
> +static inline u32 arm_smmu_lpae_tcr2(const struct io_pgtable_cfg *cfg)
>  {
>   return FIELD_PREP(ARM_SMMU_TCR2_PASIZE, cfg->arm_lpae_s1_cfg.tcr.ips) |
>  FIELD_PREP(ARM_SMMU_TCR2_SEP, ARM_SMMU_TCR2_SEP_UPSTREAM);
>  }
>  
> -static inline u32 arm_smmu_lpae_vtcr(struct io_pgtable_cfg *cfg)
> +static inline u32 arm_smmu_lpae_vtcr(const struct io_pgtable_cfg *cfg)
>  {
>   return ARM_SMMU_VTCR_RES1 |
>  FIELD_PREP(ARM_SMMU_VTCR_PS, cfg->arm_lpae_s2_cfg.vtcr.ps) |
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 06/19] drm/msm/gpu: add dev_to_gpu() helper

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> In a later patch, the drvdata will not directly be 'struct msm_gpu *',
> so add a helper to reduce the churn.
> 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/adreno/adreno_device.c | 10 --
>  drivers/gpu/drm/msm/msm_gpu.c  |  6 +++---
>  drivers/gpu/drm/msm/msm_gpu.h  |  5 +
>  3 files changed, 12 insertions(+), 9 deletions(-)
> 
> diff --git a/drivers/gpu/drm/msm/adreno/adreno_device.c 
> b/drivers/gpu/drm/msm/adreno/adreno_device.c
> index 9eeb46bf2a5d..26664e1b30c0 100644
> --- a/drivers/gpu/drm/msm/adreno/adreno_device.c
> +++ b/drivers/gpu/drm/msm/adreno/adreno_device.c
> @@ -282,7 +282,7 @@ struct msm_gpu *adreno_load_gpu(struct drm_device *dev)
>   int ret;
>  
>   if (pdev)
> - gpu = platform_get_drvdata(pdev);
> + gpu = dev_to_gpu(&pdev->dev);
>  
>   if (!gpu) {
>   dev_err_once(dev->dev, "no GPU device was found\n");
> @@ -425,7 +425,7 @@ static int adreno_bind(struct device *dev, struct device 
> *master, void *data)
>  static void adreno_unbind(struct device *dev, struct device *master,
>   void *data)
>  {
> - struct msm_gpu *gpu = dev_get_drvdata(dev);
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>  
>   pm_runtime_force_suspend(dev);
>   gpu->funcs->destroy(gpu);
> @@ -490,16 +490,14 @@ static const struct of_device_id dt_match[] = {
>  #ifdef CONFIG_PM
>  static int adreno_resume(struct device *dev)
>  {
> - struct platform_device *pdev = to_platform_device(dev);
> - struct msm_gpu *gpu = platform_get_drvdata(pdev);
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>  
>   return gpu->funcs->pm_resume(gpu);
>  }
>  
>  static int adreno_suspend(struct device *dev)
>  {
> - struct platform_device *pdev = to_platform_device(dev);
> - struct msm_gpu *gpu = platform_get_drvdata(pdev);
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>  
>   return gpu->funcs->pm_suspend(gpu);
>  }
> diff --git a/drivers/gpu/drm/msm/msm_gpu.c b/drivers/gpu/drm/msm/msm_gpu.c
> index d5645472b25d..6aa9e04e52e7 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.c
> +++ b/drivers/gpu/drm/msm/msm_gpu.c
> @@ -24,7 +24,7 @@
>  static int msm_devfreq_target(struct device *dev, unsigned long *freq,
>   u32 flags)
>  {
> - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>   struct dev_pm_opp *opp;
>  
>   opp = devfreq_recommended_opp(dev, freq, flags);
> @@ -45,7 +45,7 @@ static int msm_devfreq_target(struct device *dev, unsigned 
> long *freq,
>  static int msm_devfreq_get_dev_status(struct device *dev,
>   struct devfreq_dev_status *status)
>  {
> - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>   ktime_t time;
>  
>   if (gpu->funcs->gpu_get_freq)
> @@ -64,7 +64,7 @@ static int msm_devfreq_get_dev_status(struct device *dev,
>  
>  static int msm_devfreq_get_cur_freq(struct device *dev, unsigned long *freq)
>  {
> - struct msm_gpu *gpu = platform_get_drvdata(to_platform_device(dev));
> + struct msm_gpu *gpu = dev_to_gpu(dev);
>  
>   if (gpu->funcs->gpu_get_freq)
>   *freq = gpu->funcs->gpu_get_freq(gpu);
> diff --git a/drivers/gpu/drm/msm/msm_gpu.h b/drivers/gpu/drm/msm/msm_gpu.h
> index 0db117a7339b..8bda7beaed4b 100644
> --- a/drivers/gpu/drm/msm/msm_gpu.h
> +++ b/drivers/gpu/drm/msm/msm_gpu.h
> @@ -141,6 +141,11 @@ struct msm_gpu {
>   struct msm_gpu_state *crashstate;
>  };
>  
> +static inline struct msm_gpu *dev_to_gpu(struct device *dev)

That's a fairly generic name for a driver-global helper :)

Reviewed-by: Bjorn Andersson 

Regards,
Bjorn

> +{
> + return dev_get_drvdata(dev);
> +}
> +
>  /* It turns out that all targets use the same ringbuffer size */
>  #define MSM_GPU_RINGBUFFER_SZ SZ_32K
>  #define MSM_GPU_RINGBUFFER_BLKSIZE 32
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 05/19] iommu: add private interface for adreno-smmu

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:41 CDT 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> This interface will be used for drm/msm to coordinate with the
> qcom_adreno_smmu_impl to enable/disable TTBR0 translation.
> 
> Once TTBR0 translation is enabled, the GPU's CP (Command Processor)
> will directly switch TTBR0 pgtables (and do the necessary TLB inv)
> synchronized to the GPU's operation.  But help from the SMMU driver
> is needed to initially bootstrap TTBR0 translation, which cannot be
> done from the GPU.
> 
> Since this is a very special case, a private interface is used to
> avoid adding highly driver specific things to the public iommu
> interface.
> 
> Signed-off-by: Rob Clark 

Reviewed-by: Bjorn Andersson 

> ---
>  include/linux/adreno-smmu-priv.h | 36 
>  1 file changed, 36 insertions(+)
>  create mode 100644 include/linux/adreno-smmu-priv.h
> 
> diff --git a/include/linux/adreno-smmu-priv.h 
> b/include/linux/adreno-smmu-priv.h
> new file mode 100644
> index ..a889f28afb42
> --- /dev/null
> +++ b/include/linux/adreno-smmu-priv.h
> @@ -0,0 +1,36 @@
> +// SPDX-License-Identifier: GPL-2.0-only
> +/*
> + * Copyright (C) 2020 Google, Inc
> + */
> +
> +#ifndef __ADRENO_SMMU_PRIV_H
> +#define __ADRENO_SMMU_PRIV_H
> +
> +#include 
> +
> +/**
> + * struct adreno_smmu_priv - private interface between adreno-smmu and GPU
> + *
> + * @cookie:An opque token provided by adreno-smmu and passed
> + * back into the callbacks
> + * @get_ttbr1_cfg: Get the TTBR1 config for the GPUs context-bank
> + * @set_ttbr0_cfg: Set the TTBR0 config for the GPUs context bank.  A
> + * NULL config disables TTBR0 translation, otherwise
> + * TTBR0 translation is enabled with the specified cfg
> + *
> + * The GPU driver (drm/msm) and adreno-smmu work together for controlling
> + * the GPU's SMMU instance.  This is by necessity, as the GPU is directly
> + * updating the SMMU for context switches, while on the other hand we do
> + * not want to duplicate all of the initial setup logic from arm-smmu.
> + *
> + * This private interface is used for the two drivers to coordinate.  The
> + * cookie and callback functions are populated when the GPU driver attaches
> + * it's domain.
> + */
> +struct adreno_smmu_priv {
> +const void *cookie;
> +const struct io_pgtable_cfg *(*get_ttbr1_cfg)(const void *cookie);
> +int (*set_ttbr0_cfg)(const void *cookie, const struct io_pgtable_cfg 
> *cfg);
> +};
> +
> +#endif /* __ADRENO_SMMU_PRIV_H */
> \ No newline at end of file
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 01/19] drm/msm: remove dangling submitqueue references

2020-08-31 Thread Rob Clark
On Mon, Aug 31, 2020 at 7:35 PM Bjorn Andersson
 wrote:
>
> On Fri 14 Aug 02:40 UTC 2020, Rob Clark wrote:
>
> > From: Rob Clark 
> >
> > Currently it doesn't matter, since we free the ctx immediately.  But
> > when we start refcnt'ing the ctx, we don't want old dangling list
> > entries to hang around.
> >
> > Signed-off-by: Rob Clark 
> > ---
> >  drivers/gpu/drm/msm/msm_submitqueue.c | 4 +++-
> >  1 file changed, 3 insertions(+), 1 deletion(-)
> >
> > diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c 
> > b/drivers/gpu/drm/msm/msm_submitqueue.c
> > index a1d94be7883a..90c9d84e6155 100644
> > --- a/drivers/gpu/drm/msm/msm_submitqueue.c
> > +++ b/drivers/gpu/drm/msm/msm_submitqueue.c
> > @@ -49,8 +49,10 @@ void msm_submitqueue_close(struct msm_file_private *ctx)
> >* No lock needed in close and there won't
> >* be any more user ioctls coming our way
> >*/
> > - list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
> > + list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) {
> > + list_del(&entry->node);
>
> If you refcount ctx, what does that do for the entries in the submit
> queue?
>
> "entry" here is kref'ed, but you're popping it off the list regardless
> of the put ends up freeing the object or not - which afaict would mean
> leaking the object.
>

What ends up happening is the submit has reference to submit-queue,
which has reference to the ctx.. the submitqueue could be alive still
pending in-flight submits (in a later patch), but dead from the PoV of
userspace interface.

We aren't relying (or at least aren't in the end, and I *think* I
didn't miss anything in the middle) relying on ctx->submitqueues list
to clean anything up in the end, just track what is still a valid
submitqueue from userspace PoV

BR,
-R

>
> On the other hand, with the current implementation an object with higher
> refcount with adjacent objects of single refcount would end up with
> dangling pointers after the put. So in itself this change seems like a
> net gain, but I'm wondering about the plan described in the commit
> message.
>
> Regards,
> Bjorn
>
> >   msm_submitqueue_put(entry);
> > + }
> >  }
> >
> >  int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private 
> > *ctx,
> > --
> > 2.26.2
> >
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 03/19] iommu/arm-smmu: Add support for split pagetables

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:40 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Enable TTBR1 for a context bank if IO_PGTABLE_QUIRK_ARM_TTBR1 is selected
> by the io-pgtable configuration.
> 
> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 
> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu.c | 21 -
>  drivers/iommu/arm/arm-smmu/arm-smmu.h | 25 +++--
>  2 files changed, 35 insertions(+), 11 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 37d8d49299b4..976d43a7f2ff 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -552,11 +552,15 @@ static void arm_smmu_init_context_bank(struct 
> arm_smmu_domain *smmu_domain,
>   cb->ttbr[0] = pgtbl_cfg->arm_v7s_cfg.ttbr;
>   cb->ttbr[1] = 0;
>   } else {
> - cb->ttbr[0] = pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> - cb->ttbr[0] |= FIELD_PREP(ARM_SMMU_TTBRn_ASID,
> -   cfg->asid);
> + cb->ttbr[0] = FIELD_PREP(ARM_SMMU_TTBRn_ASID,
> + cfg->asid);
>   cb->ttbr[1] = FIELD_PREP(ARM_SMMU_TTBRn_ASID,
> -  cfg->asid);
> + cfg->asid);

The old indentation seems more appropriate.

Apart from that this looks sensible.

Reviewed-by: Bjorn Andersson 

Regards,
Bjorn

> +
> + if (pgtbl_cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1)
> + cb->ttbr[1] |= pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
> + else
> + cb->ttbr[0] |= pgtbl_cfg->arm_lpae_s1_cfg.ttbr;
>   }
>   } else {
>   cb->ttbr[0] = pgtbl_cfg->arm_lpae_s2_cfg.vttbr;
> @@ -822,7 +826,14 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>  
>   /* Update the domain's page sizes to reflect the page table format */
>   domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
> - domain->geometry.aperture_end = (1UL << ias) - 1;
> +
> + if (pgtbl_cfg.quirks & IO_PGTABLE_QUIRK_ARM_TTBR1) {
> + domain->geometry.aperture_start = ~0UL << ias;
> + domain->geometry.aperture_end = ~0UL;
> + } else {
> + domain->geometry.aperture_end = (1UL << ias) - 1;
> + }
> +
>   domain->geometry.force_aperture = true;
>  
>   /* Initialise the context bank with our page table cfg */
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index 83294516ac08..f3e456893f28 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -169,10 +169,12 @@ enum arm_smmu_cbar_type {
>  #define ARM_SMMU_CB_TCR  0x30
>  #define ARM_SMMU_TCR_EAE BIT(31)
>  #define ARM_SMMU_TCR_EPD1BIT(23)
> +#define ARM_SMMU_TCR_A1  BIT(22)
>  #define ARM_SMMU_TCR_TG0 GENMASK(15, 14)
>  #define ARM_SMMU_TCR_SH0 GENMASK(13, 12)
>  #define ARM_SMMU_TCR_ORGN0   GENMASK(11, 10)
>  #define ARM_SMMU_TCR_IRGN0   GENMASK(9, 8)
> +#define ARM_SMMU_TCR_EPD0BIT(7)
>  #define ARM_SMMU_TCR_T0SZGENMASK(5, 0)
>  
>  #define ARM_SMMU_VTCR_RES1   BIT(31)
> @@ -350,12 +352,23 @@ struct arm_smmu_domain {
>  
>  static inline u32 arm_smmu_lpae_tcr(struct io_pgtable_cfg *cfg)
>  {
> - return ARM_SMMU_TCR_EPD1 |
> -FIELD_PREP(ARM_SMMU_TCR_TG0, cfg->arm_lpae_s1_cfg.tcr.tg) |
> -FIELD_PREP(ARM_SMMU_TCR_SH0, cfg->arm_lpae_s1_cfg.tcr.sh) |
> -FIELD_PREP(ARM_SMMU_TCR_ORGN0, cfg->arm_lpae_s1_cfg.tcr.orgn) |
> -FIELD_PREP(ARM_SMMU_TCR_IRGN0, cfg->arm_lpae_s1_cfg.tcr.irgn) |
> -FIELD_PREP(ARM_SMMU_TCR_T0SZ, cfg->arm_lpae_s1_cfg.tcr.tsz);
> + u32 tcr = FIELD_PREP(ARM_SMMU_TCR_TG0, cfg->arm_lpae_s1_cfg.tcr.tg) |
> + FIELD_PREP(ARM_SMMU_TCR_SH0, cfg->arm_lpae_s1_cfg.tcr.sh) |
> + FIELD_PREP(ARM_SMMU_TCR_ORGN0, cfg->arm_lpae_s1_cfg.tcr.orgn) |
> + FIELD_PREP(ARM_SMMU_TCR_IRGN0, cfg->arm_lpae_s1_cfg.tcr.irgn) |
> + FIELD_PREP(ARM_SMMU_TCR_T0SZ, cfg->arm_lpae_s1_cfg.tcr.tsz);
> +
> +   /*
> + * When TTBR1 is selected shift the TCR fields by 16 bits and disable
> + * translation in TTBR0
> + */
> + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_TTBR1) {
> + tcr = (tcr << 16) & ~ARM_SMMU_TCR_A1;
> + tcr |= ARM_SMMU_TCR_EPD0;
> + } else
> + tcr |= ARM_SMMU_TCR_EPD1;
> +
> + return tcr;
>  }
>  
>  static inline u32 arm_smmu_lpae_tcr2(struct io_pgtable_cfg *cfg)
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/

[PATCH v4 4/5] vfio/type1: Use iommu_aux_at(de)tach_group() APIs

2020-08-31 Thread Lu Baolu
Replace iommu_aux_at(de)tach_device() with iommu_at(de)tach_subdev_group().

Signed-off-by: Lu Baolu 
---
 drivers/vfio/vfio_iommu_type1.c | 43 +
 1 file changed, 6 insertions(+), 37 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 5e556ac9102a..8d5eb7ce0986 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1627,45 +1627,13 @@ static struct device *vfio_mdev_get_iommu_device(struct 
device *dev)
return NULL;
 }
 
-static int vfio_mdev_attach_domain(struct device *dev, void *data)
-{
-   struct iommu_domain *domain = data;
-   struct device *iommu_device;
-
-   iommu_device = vfio_mdev_get_iommu_device(dev);
-   if (iommu_device) {
-   if (iommu_dev_feature_enabled(iommu_device, IOMMU_DEV_FEAT_AUX))
-   return iommu_aux_attach_device(domain, iommu_device);
-   else
-   return iommu_attach_device(domain, iommu_device);
-   }
-
-   return -EINVAL;
-}
-
-static int vfio_mdev_detach_domain(struct device *dev, void *data)
-{
-   struct iommu_domain *domain = data;
-   struct device *iommu_device;
-
-   iommu_device = vfio_mdev_get_iommu_device(dev);
-   if (iommu_device) {
-   if (iommu_dev_feature_enabled(iommu_device, IOMMU_DEV_FEAT_AUX))
-   iommu_aux_detach_device(domain, iommu_device);
-   else
-   iommu_detach_device(domain, iommu_device);
-   }
-
-   return 0;
-}
-
 static int vfio_iommu_attach_group(struct vfio_domain *domain,
   struct vfio_group *group)
 {
if (group->mdev_group)
-   return iommu_group_for_each_dev(group->iommu_group,
-   domain->domain,
-   vfio_mdev_attach_domain);
+   return iommu_attach_subdev_group(domain->domain,
+group->iommu_group,
+vfio_mdev_get_iommu_device);
else
return iommu_attach_group(domain->domain, group->iommu_group);
 }
@@ -1674,8 +1642,9 @@ static void vfio_iommu_detach_group(struct vfio_domain 
*domain,
struct vfio_group *group)
 {
if (group->mdev_group)
-   iommu_group_for_each_dev(group->iommu_group, domain->domain,
-vfio_mdev_detach_domain);
+   iommu_detach_subdev_group(domain->domain,
+ group->iommu_group,
+ vfio_mdev_get_iommu_device);
else
iommu_detach_group(domain->domain, group->iommu_group);
 }
-- 
2.17.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 1/5] iommu: Add optional subdev in aux_at(de)tach ops

2020-08-31 Thread Lu Baolu
In the vfio/mdev use case of aux-domain, the subdevices are created from
the physical devices with IOMMU_DEV_FEAT_AUX enabled and the aux-domains
are attached to the subdevices through the iommu_ops.aux_attach_dev()
interface.

Current iommu_ops.aux_at(de)tach_dev() design only takes the aux-domain
and the physical device as the parameters, this is insufficient if we
want the vendor iommu drivers to learn the knowledge about relationships
between the aux-domains and the subdevices. Add a @subdev parameter to
iommu_ops.aux_at(de)tach_dev() interfaces so that a subdevice could be
opt-in.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.c | 10 ++
 drivers/iommu/iommu.c   |  4 ++--
 include/linux/iommu.h   |  6 --
 3 files changed, 12 insertions(+), 8 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index bce158468abf..3c12fd06856c 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5338,8 +5338,9 @@ static int intel_iommu_attach_device(struct iommu_domain 
*domain,
return domain_add_dev_info(to_dmar_domain(domain), dev);
 }
 
-static int intel_iommu_aux_attach_device(struct iommu_domain *domain,
-struct device *dev)
+static int
+intel_iommu_aux_attach_device(struct iommu_domain *domain,
+ struct device *dev, struct device *subdev)
 {
int ret;
 
@@ -5359,8 +5360,9 @@ static void intel_iommu_detach_device(struct iommu_domain 
*domain,
dmar_remove_one_dev_info(dev);
 }
 
-static void intel_iommu_aux_detach_device(struct iommu_domain *domain,
- struct device *dev)
+static void
+intel_iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev,
+ struct device *subdev)
 {
aux_domain_remove_dev(to_dmar_domain(domain), dev);
 }
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 609bd25bf154..38cdfeb887e1 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2728,7 +2728,7 @@ int iommu_aux_attach_device(struct iommu_domain *domain, 
struct device *dev)
int ret = -ENODEV;
 
if (domain->ops->aux_attach_dev)
-   ret = domain->ops->aux_attach_dev(domain, dev);
+   ret = domain->ops->aux_attach_dev(domain, dev, NULL);
 
if (!ret)
trace_attach_device_to_domain(dev);
@@ -2740,7 +2740,7 @@ EXPORT_SYMBOL_GPL(iommu_aux_attach_device);
 void iommu_aux_detach_device(struct iommu_domain *domain, struct device *dev)
 {
if (domain->ops->aux_detach_dev) {
-   domain->ops->aux_detach_dev(domain, dev);
+   domain->ops->aux_detach_dev(domain, dev, NULL);
trace_detach_device_from_domain(dev);
}
 }
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fee209efb756..871267104915 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -279,8 +279,10 @@ struct iommu_ops {
int (*dev_disable_feat)(struct device *dev, enum iommu_dev_features f);
 
/* Aux-domain specific attach/detach entries */
-   int (*aux_attach_dev)(struct iommu_domain *domain, struct device *dev);
-   void (*aux_detach_dev)(struct iommu_domain *domain, struct device *dev);
+   int (*aux_attach_dev)(struct iommu_domain *domain, struct device *dev,
+ struct device *subdev);
+   void (*aux_detach_dev)(struct iommu_domain *domain, struct device *dev,
+  struct device *subdev);
int (*aux_get_pasid)(struct iommu_domain *domain, struct device *dev);
 
struct iommu_sva *(*sva_bind)(struct device *dev, struct mm_struct *mm,
-- 
2.17.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 0/5] iommu aux-domain APIs extensions

2020-08-31 Thread Lu Baolu
This series aims to extend the IOMMU aux-domain API set so that it
could be more friendly to vfio/mdev usage. The interactions between
vfio/mdev and iommu during mdev creation and passthr are:

1. Create a group for mdev with iommu_group_alloc();
2. Add the device to the group with

   group = iommu_group_alloc();
   if (IS_ERR(group))
   return PTR_ERR(group);

   ret = iommu_group_add_device(group, &mdev->dev);
   if (!ret)
   dev_info(&mdev->dev, "MDEV: group_id = %d\n",
iommu_group_id(group));

3. Allocate an aux-domain with iommu_domain_alloc();
4. Attach the aux-domain to the iommu_group.

   iommu_group_for_each_dev {
   if (iommu_dev_feature_enabled(iommu_device, IOMMU_DEV_FEAT_AUX))
   return iommu_aux_attach_device(domain, iommu_device);
   else
   return iommu_attach_device(domain, iommu_device);
}

   where, iommu_device is the aux-domain-capable device. The mdev's in
   the group are all derived from it.

In the whole process, an iommu group was allocated for the mdev and an
iommu domain was attached to the group, but the group->domain leaves
NULL. As the result, iommu_get_domain_for_dev() (or other similar
interfaces) doesn't work anymore.

The iommu_get_domain_for_dev() is a necessary interface for device
drivers that want to support vfio/mdev based aux-domain. For example,

unsigned long pasid;
struct iommu_domain *domain;
struct device *dev = mdev_dev(mdev);
struct device *iommu_device = vfio_mdev_get_iommu_device(dev);

domain = iommu_aux_get_domain_for_dev(dev);
if (!domain)
return -ENODEV;

pasid = iommu_aux_get_pasid(domain, iommu_device);
if (pasid <= 0)
return -EINVAL;

 /* Program the device context */
 

We tried to address this by extending iommu_aux_at(de)tach_device() so that
the users could pass in an optional device pointer (for example vfio/mdev).
(v2 of this series)

https://lore.kernel.org/linux-iommu/20200707013957.23672-1-baolu...@linux.intel.com/

But that will cause a lock issue as group->mutex has been applied in
iommu_group_for_each_dev(), but has to be reapplied again in the
iommu_aux_attach_device().

We also tried to implement an equivalent iommu_attch_group() for groups
which includes subdevices derived from a single physical device. (v3 of
this series)

https://lore.kernel.org/linux-iommu/20200714055703.5510-1-baolu...@linux.intel.com/

But that's too harsh (requires that all subdevices in an iommu_group
must be derived from a same physical device) and breaks some generic
concept of iommmu_group.

This version continues to address this by introducing some new APIs into
the aux-domain API set according to comments during v3 reviewing period.

/**
 * iommu_attach_subdev_group - attach domain to an iommu_group which
 * contains subdevices.
 *
 * @domain: domain
 * @group:  iommu_group which contains subdevices
 * @fn: callback for each subdevice in the @iommu_group to retrieve the
 *  physical device where the subdevice was created from.
 *
 * Returns 0 on success, or an error value.
 */
int iommu_attach_subdev_group(struct iommu_domain *domain,
  struct iommu_group *group,
  iommu_device_lookup_t fn)

/**
 * iommu_detach_subdev_group - detach domain from an iommu_group which
 * contains subdevices
 *
 * @domain: domain
 * @group:  iommu_group which contains subdevices
 * @fn: callback for each subdevice in the @iommu_group to retrieve the
 *  physical device where the subdevice was created from.
 *
 * The domain must have been attached to @group via iommu_attach_subdev_group().
 */
void iommu_detach_subdev_group(struct iommu_domain *domain,
   struct iommu_group *group,
   iommu_device_lookup_t fn)

struct iommu_domain *iommu_aux_get_domain_for_dev(struct device *subdev)

This version is evolved according to feedbacks from Robin, Alex and Kevin.
I'm very appreciated to their contributions.

Best regards,
baolu

---
Change log:
 - v1->v2:
   - 
https://lore.kernel.org/linux-iommu/20200627031532.28046-1-baolu...@linux.intel.com/
   - Suggested by Robin.

 - v2->v3:
   - 
https://lore.kernel.org/linux-iommu/20200707013957.23672-1-baolu...@linux.intel.com/
   - Suggested by Alex, Kevin.

 - v3->v4:
   - 
https://lore.kernel.org/linux-iommu/20200714055703.5510-1-baolu...@linux.intel.com/
   - Evolve the aux_attach_group APIs to take an iommu_device lookup
 callback.
   - Add interface to check whether a domain is aux-domain for a device.
   - Return domain only if the domain is aux-domain in
 iommu_aux_get_domain_for_dev().

Lu Baolu (5):
  iommu: Add optional subdev in aux_at(de)tach ops
  iommu: Add iommu_at(de)tach_subd

[PATCH v4 5/5] iommu/vt-d: Add is_aux_domain support

2020-08-31 Thread Lu Baolu
With subdevice information opt-in through iommu_ops.aux_at(de)tach_dev()
interfaces, the vendor iommu driver is able to learn the knowledge about
the relationships between the subdevices and the aux-domains. Implement
is_aux_domain() support based on the relationship knowledges.

Signed-off-by: Lu Baolu 
---
 drivers/iommu/intel/iommu.c | 125 ++--
 include/linux/intel-iommu.h |  17 +++--
 2 files changed, 103 insertions(+), 39 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 3c12fd06856c..50431c7b2e71 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -334,6 +334,8 @@ static int intel_iommu_attach_device(struct iommu_domain 
*domain,
 struct device *dev);
 static phys_addr_t intel_iommu_iova_to_phys(struct iommu_domain *domain,
dma_addr_t iova);
+static bool intel_iommu_dev_feat_enabled(struct device *dev,
+enum iommu_dev_features feat);
 
 #ifdef CONFIG_INTEL_IOMMU_DEFAULT_ON
 int dmar_disabled = 0;
@@ -1832,6 +1834,7 @@ static struct dmar_domain *alloc_domain(int flags)
domain->flags |= DOMAIN_FLAG_USE_FIRST_LEVEL;
domain->has_iotlb_device = false;
INIT_LIST_HEAD(&domain->devices);
+   INIT_LIST_HEAD(&domain->subdevices);
 
return domain;
 }
@@ -2580,7 +2583,7 @@ static struct dmar_domain 
*dmar_insert_one_dev_info(struct intel_iommu *iommu,
info->iommu = iommu;
info->pasid_table = NULL;
info->auxd_enabled = 0;
-   INIT_LIST_HEAD(&info->auxiliary_domains);
+   INIT_LIST_HEAD(&info->subdevices);
 
if (dev && dev_is_pci(dev)) {
struct pci_dev *pdev = to_pci_dev(info->dev);
@@ -5137,21 +5140,28 @@ static void intel_iommu_domain_free(struct iommu_domain 
*domain)
domain_exit(to_dmar_domain(domain));
 }
 
-/*
- * Check whether a @domain could be attached to the @dev through the
- * aux-domain attach/detach APIs.
- */
-static inline bool
-is_aux_domain(struct device *dev, struct iommu_domain *domain)
+/* Lookup subdev_info in the domain's subdevice siblings. */
+static struct subdev_info *
+subdev_lookup_domain(struct dmar_domain *domain, struct device *dev,
+struct device *subdev)
 {
-   struct device_domain_info *info = get_domain_info(dev);
+   struct subdev_info *sinfo = NULL, *tmp;
 
-   return info && info->auxd_enabled &&
-   domain->type == IOMMU_DOMAIN_UNMANAGED;
+   assert_spin_locked(&device_domain_lock);
+
+   list_for_each_entry(tmp, &domain->subdevices, link_domain) {
+   if ((!dev || tmp->pdev == dev) && tmp->dev == subdev) {
+   sinfo = tmp;
+   break;
+   }
+   }
+
+   return sinfo;
 }
 
-static void auxiliary_link_device(struct dmar_domain *domain,
- struct device *dev)
+static void
+subdev_link_device(struct dmar_domain *domain, struct device *dev,
+  struct subdev_info *sinfo)
 {
struct device_domain_info *info = get_domain_info(dev);
 
@@ -5159,12 +5169,13 @@ static void auxiliary_link_device(struct dmar_domain 
*domain,
if (WARN_ON(!info))
return;
 
-   domain->auxd_refcnt++;
-   list_add(&domain->auxd, &info->auxiliary_domains);
+   list_add(&info->subdevices, &sinfo->link_phys);
+   list_add(&domain->subdevices, &sinfo->link_domain);
 }
 
-static void auxiliary_unlink_device(struct dmar_domain *domain,
-   struct device *dev)
+static void
+subdev_unlink_device(struct dmar_domain *domain, struct device *dev,
+struct subdev_info *sinfo)
 {
struct device_domain_info *info = get_domain_info(dev);
 
@@ -5172,24 +5183,30 @@ static void auxiliary_unlink_device(struct dmar_domain 
*domain,
if (WARN_ON(!info))
return;
 
-   list_del(&domain->auxd);
-   domain->auxd_refcnt--;
+   list_del(&sinfo->link_phys);
+   list_del(&sinfo->link_domain);
+   kfree(sinfo);
 
-   if (!domain->auxd_refcnt && domain->default_pasid > 0)
+   if (list_empty(&domain->subdevices) && domain->default_pasid > 0)
ioasid_free(domain->default_pasid);
 }
 
-static int aux_domain_add_dev(struct dmar_domain *domain,
- struct device *dev)
+static int aux_domain_add_dev(struct dmar_domain *domain, struct device *dev,
+ struct device *subdev)
 {
int ret;
unsigned long flags;
struct intel_iommu *iommu;
+   struct subdev_info *sinfo;
 
iommu = device_to_iommu(dev, NULL, NULL);
if (!iommu)
return -ENODEV;
 
+   sinfo = kzalloc(sizeof(*sinfo), GFP_KERNEL);
+   if (!sinfo)
+   return -ENOMEM;
+
if (domain->defaul

[PATCH v4 3/5] iommu: Add iommu_aux_get_domain_for_dev()

2020-08-31 Thread Lu Baolu
The device driver needs an API to get its aux-domain. A typical usage
scenario is:

unsigned long pasid;
struct iommu_domain *domain;
struct device *dev = mdev_dev(mdev);
struct device *iommu_device = vfio_mdev_get_iommu_device(dev);

domain = iommu_aux_get_domain_for_dev(dev);
if (!domain)
return -ENODEV;

pasid = iommu_aux_get_pasid(domain, iommu_device);
if (pasid <= 0)
return -EINVAL;

 /* Program the device context */
 

This adds an API for such use case.

Suggested-by: Alex Williamson 
Link: https://lore.kernel.org/linux-iommu/20200708130749.1b1e1...@x1.home/
Signed-off-by: Lu Baolu 
---
 drivers/iommu/iommu.c | 18 ++
 include/linux/iommu.h | 20 
 2 files changed, 38 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index fb21c2ff4861..8fd93a5b8764 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2893,6 +2893,24 @@ void iommu_detach_subdev_group(struct iommu_domain 
*domain,
 }
 EXPORT_SYMBOL_GPL(iommu_detach_subdev_group);
 
+struct iommu_domain *iommu_aux_get_domain_for_dev(struct device *subdev)
+{
+   struct iommu_domain *domain = NULL;
+   struct iommu_group *group;
+
+   group = iommu_group_get(subdev);
+   if (!group || !group->domain)
+   return NULL;
+
+   if (domain_is_aux(group->domain, subdev))
+   domain = group->domain;
+
+   iommu_group_put(group);
+
+   return domain;
+}
+EXPORT_SYMBOL_GPL(iommu_aux_get_domain_for_dev);
+
 /**
  * iommu_sva_bind_device() - Bind a process address space to a device
  * @dev: the device
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index b9df8b510d4f..ea660a887dbf 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -120,6 +120,7 @@ enum iommu_attr {
DOMAIN_ATTR_NESTING,/* two stages of translation */
DOMAIN_ATTR_DMA_USE_FLUSH_QUEUE,
DOMAIN_ATTR_MAX,
+   DOMAIN_ATTR_IS_AUX,
 };
 
 /* These are the possible reserved region types */
@@ -622,6 +623,12 @@ static inline void dev_iommu_priv_set(struct device *dev, 
void *priv)
dev->iommu->priv = priv;
 }
 
+static inline bool
+domain_is_aux(struct iommu_domain *domain, struct device *subdev)
+{
+   return iommu_domain_get_attr(domain, DOMAIN_ATTR_IS_AUX, subdev);
+}
+
 int iommu_probe_device(struct device *dev);
 void iommu_release_device(struct device *dev);
 
@@ -638,6 +645,7 @@ int iommu_attach_subdev_group(struct iommu_domain *domain,
 void iommu_detach_subdev_group(struct iommu_domain *domain,
   struct iommu_group *group,
   iommu_device_lookup_t fn);
+struct iommu_domain *iommu_aux_get_domain_for_dev(struct device *subdev);
 
 struct iommu_sva *iommu_sva_bind_device(struct device *dev,
struct mm_struct *mm,
@@ -1039,6 +1047,18 @@ iommu_detach_subdev_group(struct iommu_domain *domain, 
struct iommu_group *group
 {
 }
 
+static inline bool
+domain_is_aux(struct iommu_domain *domain, struct device *subdev)
+{
+   return false;
+}
+
+static inline struct iommu_domain *
+iommu_aux_get_domain_for_dev(struct device *subdev)
+{
+   return NULL;
+}
+
 static inline struct iommu_sva *
 iommu_sva_bind_device(struct device *dev, struct mm_struct *mm, void *drvdata)
 {
-- 
2.17.1

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v4 2/5] iommu: Add iommu_at(de)tach_subdev_group()

2020-08-31 Thread Lu Baolu
This adds two new APIs for the use cases like vfio/mdev where subdevices
derived from physical devices are created and put in an iommu_group. The
new IOMMU API interfaces mimic the vfio_mdev_at(de)tach_domain() directly,
testing whether the resulting device supports IOMMU_DEV_FEAT_AUX and using
an aux vs non-aux at(de)tach.

By doing this we could

- Set the iommu_group.domain. The iommu_group.domain is private to iommu
  core (therefore vfio code cannot set it), but we need it set in order
  for iommu_get_domain_for_dev() to work with a group attached to an aux
  domain.

- Prefer to use the _attach_group() interfaces while the _attach_device()
  interfaces are relegated to special cases.

Link: https://lore.kernel.org/linux-iommu/20200730134658.44c57...@x1.home/
Link: https://lore.kernel.org/linux-iommu/20200730151703.5daf8...@x1.home/
Signed-off-by: Lu Baolu 
---
 drivers/iommu/iommu.c | 136 ++
 include/linux/iommu.h |  20 +++
 2 files changed, 156 insertions(+)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 38cdfeb887e1..fb21c2ff4861 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -2757,6 +2757,142 @@ int iommu_aux_get_pasid(struct iommu_domain *domain, 
struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_aux_get_pasid);
 
+static int __iommu_aux_attach_device(struct iommu_domain *domain,
+struct device *phys_dev,
+struct device *sub_dev)
+{
+   int ret;
+
+   if (unlikely(!domain->ops->aux_attach_dev))
+   return -ENODEV;
+
+   ret = domain->ops->aux_attach_dev(domain, phys_dev, sub_dev);
+   if (!ret)
+   trace_attach_device_to_domain(sub_dev);
+
+   return ret;
+}
+
+static void __iommu_aux_detach_device(struct iommu_domain *domain,
+ struct device *phys_dev,
+ struct device *sub_dev)
+{
+   if (unlikely(!domain->ops->aux_detach_dev))
+   return;
+
+   domain->ops->aux_detach_dev(domain, phys_dev, sub_dev);
+   trace_detach_device_from_domain(sub_dev);
+}
+
+static int __iommu_attach_subdev_group(struct iommu_domain *domain,
+  struct iommu_group *group,
+  iommu_device_lookup_t fn)
+{
+   struct group_device *device;
+   struct device *phys_dev;
+   int ret = -ENODEV;
+
+   list_for_each_entry(device, &group->devices, list) {
+   phys_dev = fn(device->dev);
+   if (!phys_dev) {
+   ret = -ENODEV;
+   break;
+   }
+
+   if (iommu_dev_feature_enabled(phys_dev, IOMMU_DEV_FEAT_AUX))
+   ret = __iommu_aux_attach_device(domain, phys_dev,
+   device->dev);
+   else
+   ret = __iommu_attach_device(domain, phys_dev);
+
+   if (ret)
+   break;
+   }
+
+   return ret;
+}
+
+static void __iommu_detach_subdev_group(struct iommu_domain *domain,
+   struct iommu_group *group,
+   iommu_device_lookup_t fn)
+{
+   struct group_device *device;
+   struct device *phys_dev;
+
+   list_for_each_entry(device, &group->devices, list) {
+   phys_dev = fn(device->dev);
+   if (!phys_dev)
+   break;
+
+   if (iommu_dev_feature_enabled(phys_dev, IOMMU_DEV_FEAT_AUX))
+   __iommu_aux_detach_device(domain, phys_dev, 
device->dev);
+   else
+   __iommu_detach_device(domain, phys_dev);
+   }
+}
+
+/**
+ * iommu_attach_subdev_group - attach domain to an iommu_group which
+ *contains subdevices.
+ *
+ * @domain: domain
+ * @group:  iommu_group which contains subdevices
+ * @fn: callback for each subdevice in the @iommu_group to retrieve the
+ *  physical device where the subdevice was created from.
+ *
+ * Returns 0 on success, or an error value.
+ */
+int iommu_attach_subdev_group(struct iommu_domain *domain,
+ struct iommu_group *group,
+ iommu_device_lookup_t fn)
+{
+   int ret = -ENODEV;
+
+   mutex_lock(&group->mutex);
+   if (group->domain) {
+   ret = -EBUSY;
+   goto unlock_out;
+   }
+
+   ret = __iommu_attach_subdev_group(domain, group, fn);
+   if (ret)
+   __iommu_detach_subdev_group(domain, group, fn);
+   else
+   group->domain = domain;
+
+unlock_out:
+   mutex_unlock(&group->mutex);
+   return ret;
+}
+EXPORT_SYMBOL_GPL(iommu_attach_subdev_group);
+
+/**
+ * iommu_detach_subdev_group - detach domain from an iommu_group which
+ *   

Re: [PATCH 02/19] iommu/arm-smmu: Pass io-pgtable config to implementation specific function

2020-08-31 Thread Bjorn Andersson
On Thu 13 Aug 21:40 CDT 2020, Rob Clark wrote:

> From: Jordan Crouse 
> 
> Construct the io-pgtable config before calling the implementation specific
> init_context function and pass it so the implementation specific function
> can get a chance to change it before the io-pgtable is created.
> 
> Signed-off-by: Jordan Crouse 
> Signed-off-by: Rob Clark 

Reviewed-by: Bjorn Andersson 

Regards,
Bjorn

> ---
>  drivers/iommu/arm/arm-smmu/arm-smmu-impl.c |  3 ++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.c  | 11 ++-
>  drivers/iommu/arm/arm-smmu/arm-smmu.h  |  3 ++-
>  3 files changed, 10 insertions(+), 7 deletions(-)
> 
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> index f4ff124a1967..a9861dcd0884 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu-impl.c
> @@ -68,7 +68,8 @@ static int cavium_cfg_probe(struct arm_smmu_device *smmu)
>   return 0;
>  }
>  
> -static int cavium_init_context(struct arm_smmu_domain *smmu_domain)
> +static int cavium_init_context(struct arm_smmu_domain *smmu_domain,
> + struct io_pgtable_cfg *pgtbl_cfg)
>  {
>   struct cavium_smmu *cs = container_of(smmu_domain->smmu,
> struct cavium_smmu, smmu);
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.c 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> index 09c42af9f31e..37d8d49299b4 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.c
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.c
> @@ -795,11 +795,6 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>   cfg->asid = cfg->cbndx;
>  
>   smmu_domain->smmu = smmu;
> - if (smmu->impl && smmu->impl->init_context) {
> - ret = smmu->impl->init_context(smmu_domain);
> - if (ret)
> - goto out_unlock;
> - }
>  
>   pgtbl_cfg = (struct io_pgtable_cfg) {
>   .pgsize_bitmap  = smmu->pgsize_bitmap,
> @@ -810,6 +805,12 @@ static int arm_smmu_init_domain_context(struct 
> iommu_domain *domain,
>   .iommu_dev  = smmu->dev,
>   };
>  
> + if (smmu->impl && smmu->impl->init_context) {
> + ret = smmu->impl->init_context(smmu_domain, &pgtbl_cfg);
> + if (ret)
> + goto out_clear_smmu;
> + }
> +
>   if (smmu_domain->non_strict)
>   pgtbl_cfg.quirks |= IO_PGTABLE_QUIRK_NON_STRICT;
>  
> diff --git a/drivers/iommu/arm/arm-smmu/arm-smmu.h 
> b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> index d890a4a968e8..83294516ac08 100644
> --- a/drivers/iommu/arm/arm-smmu/arm-smmu.h
> +++ b/drivers/iommu/arm/arm-smmu/arm-smmu.h
> @@ -386,7 +386,8 @@ struct arm_smmu_impl {
>   u64 val);
>   int (*cfg_probe)(struct arm_smmu_device *smmu);
>   int (*reset)(struct arm_smmu_device *smmu);
> - int (*init_context)(struct arm_smmu_domain *smmu_domain);
> + int (*init_context)(struct arm_smmu_domain *smmu_domain,
> + struct io_pgtable_cfg *cfg);
>   void (*tlb_sync)(struct arm_smmu_device *smmu, int page, int sync,
>int status);
>   int (*def_domain_type)(struct device *dev);
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v8 7/7] iommu/vt-d: Check UAPI data processed by IOMMU core

2020-08-31 Thread Lu Baolu

Hi Jacob,

On 9/1/20 2:25 AM, Jacob Pan wrote:

IOMMU generic layer already does sanity checks on UAPI data for version
match and argsz range based on generic information.

This patch adjusts the following data checking responsibilities:
- removes the redundant version check from VT-d driver
- removes the check for vendor specific data size
- adds check for the use of reserved/undefined flags

Signed-off-by: Jacob Pan 
---
  drivers/iommu/intel/iommu.c |  3 +--
  drivers/iommu/intel/svm.c   | 11 +--
  include/uapi/linux/iommu.h  |  1 +
  3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 43f16f0cebde..a3a0b5c8921d 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5399,8 +5399,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
int ret = 0;
u64 size = 0;
  
-	if (!inv_info || !dmar_domain ||

-   inv_info->version != IOMMU_CACHE_INVALIDATE_INFO_VERSION_1)
+   if (!inv_info || !dmar_domain)
return -EINVAL;
  
  	if (!dev || !dev_is_pci(dev))

diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 99353d6468fa..0cb9a15f1112 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -284,8 +284,15 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, 
struct device *dev,
if (WARN_ON(!iommu) || !data)
return -EINVAL;
  
-	if (data->version != IOMMU_GPASID_BIND_VERSION_1 ||

-   data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
+   if (data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
+   return -EINVAL;
+
+   /* IOMMU core ensures argsz is more than the start of the union */
+   if (data->argsz < offsetofend(struct iommu_gpasid_bind_data, 
vendor.vtd))
+   return -EINVAL;
+
+   /* Make sure no undefined flags are used in vendor data */
+   if (data->vendor.vtd.flags & ~(IOMMU_SVA_VTD_GPASID_LAST - 1))
return -EINVAL;
  
  	if (!dev_is_pci(dev))

diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
index c64bca5af419..1ebc23df4fbc 100644
--- a/include/uapi/linux/iommu.h
+++ b/include/uapi/linux/iommu.h
@@ -288,6 +288,7 @@ struct iommu_gpasid_bind_data_vtd {
  #define IOMMU_SVA_VTD_GPASID_PWT  (1 << 3) /* page-level write through */
  #define IOMMU_SVA_VTD_GPASID_EMTE (1 << 4) /* extended mem type enable */
  #define IOMMU_SVA_VTD_GPASID_CD   (1 << 5) /* PASID-level cache 
disable */
+#define IOMMU_SVA_VTD_GPASID_LAST  (1 << 6)
__u64 flags;
__u32 pat;
__u32 emt;



Reviewed-by: Lu Baolu 

Best regards,
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 01/19] drm/msm: remove dangling submitqueue references

2020-08-31 Thread Bjorn Andersson
On Fri 14 Aug 02:40 UTC 2020, Rob Clark wrote:

> From: Rob Clark 
> 
> Currently it doesn't matter, since we free the ctx immediately.  But
> when we start refcnt'ing the ctx, we don't want old dangling list
> entries to hang around.
> 
> Signed-off-by: Rob Clark 
> ---
>  drivers/gpu/drm/msm/msm_submitqueue.c | 4 +++-
>  1 file changed, 3 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/gpu/drm/msm/msm_submitqueue.c 
> b/drivers/gpu/drm/msm/msm_submitqueue.c
> index a1d94be7883a..90c9d84e6155 100644
> --- a/drivers/gpu/drm/msm/msm_submitqueue.c
> +++ b/drivers/gpu/drm/msm/msm_submitqueue.c
> @@ -49,8 +49,10 @@ void msm_submitqueue_close(struct msm_file_private *ctx)
>* No lock needed in close and there won't
>* be any more user ioctls coming our way
>*/
> - list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node)
> + list_for_each_entry_safe(entry, tmp, &ctx->submitqueues, node) {
> + list_del(&entry->node);

If you refcount ctx, what does that do for the entries in the submit
queue?

"entry" here is kref'ed, but you're popping it off the list regardless
of the put ends up freeing the object or not - which afaict would mean
leaking the object.


On the other hand, with the current implementation an object with higher
refcount with adjacent objects of single refcount would end up with
dangling pointers after the put. So in itself this change seems like a
net gain, but I'm wondering about the plan described in the commit
message.

Regards,
Bjorn

>   msm_submitqueue_put(entry);
> + }
>  }
>  
>  int msm_submitqueue_create(struct drm_device *drm, struct msm_file_private 
> *ctx,
> -- 
> 2.26.2
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [Regression] [PATCH] iommu: Avoid crash in init_no_remapping_devices if iommu is NULL

2020-08-31 Thread Lu Baolu

Hi Torsten,

Thank you for reporting this.

On 8/31/20 7:03 PM, Torsten Hilbrich wrote:

I noticed a kernel crash when trying to boot a v5.9-rc2 based kernel.

The crash reads as:

<1>[7.410192] BUG: kernel NULL pointer dereference, address: 
0038
<1>[7.410196] #PF: supervisor write access in kernel mode
<1>[7.410199] #PF: error_code(0x0002) - not-present page
<6>[7.410202] PGD 0 P4D 0
<4>[7.410207] Oops: 0002 [#1] SMP PTI
<4>[7.410212] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.9.0-devel+ #1
<4>[7.410215] Hardware name: LENOVO 20HGS0TW00/20HGS0TW00, BIOS N1WET46S 
(1.25s ) 03/30/2018
<4>[7.410224] RIP: 0010:intel_iommu_init+0xed0/0x1136
<4>[7.410229] Code: fe e9 61 02 00 00 bb f4 ff ff ff e9 57 02 00 00 48 63 d1 48 
c1 e2 04 48 03 50 20 48 8b 12 48 85 d2 74 0b 48 8b 92 d0 02 00 00 <48> 89 7a 38 ff c1 
e9 15 f5 ff ff 48 c7 c7 00 a5 ac a1 49 c7 c7 20
<4>[7.410236] RSP: :b14e40073dd0 EFLAGS: 00010282
<4>[7.410240] RAX: 8d0643731720 RBX:  RCX: 

<4>[7.410244] RDX:  RSI:  RDI: 

<4>[7.410247] RBP: b14e40073e90 R08: 0001 R09: 
8d0643803700
<4>[7.410250] R10: 8d064262 R11: 0016 R12: 
000b
<4>[7.410254] R13: 8d064361e650 R14: a2455d80 R15: 

<4>[7.410258] FS:  () GS:8d064748() 
knlGS:
<4>[7.410262] CS:  0010 DS:  ES:  CR0: 80050033
<4>[7.410266] CR2: 0038 CR3: 00056760a001 CR4: 
003706e0
<4>[7.410269] Call Trace:
<4>[7.410280]  ? call_rcu+0x10e/0x320
<4>[7.410286]  ? trace_hardirqs_on+0x2c/0xd0
<4>[7.410291]  ? rdinit_setup+0x2c/0x2c
<4>[7.410297]  ? e820__memblock_setup+0x8b/0x8b
<4>[7.410302]  pci_iommu_init+0x16/0x3f
<4>[7.410307]  do_one_initcall+0x46/0x1e4
<4>[7.410313]  kernel_init_freeable+0x169/0x1b2
<4>[7.410320]  ? rest_init+0x9f/0x9f
<4>[7.410325]  kernel_init+0xa/0x101
<4>[7.410329]  ret_from_fork+0x22/0x30
<4>[7.410333] Modules linked in:
<4>[7.410338] CR2: 0038
<4>[7.410344] ---[ end trace 16bcdb1e11668fcd ]---

Full kernel message is attached in kernel.log.

I tracked the problem down to the dev_iommu_priv_set call in 
init_no_remapping_devices. It seems that for one device the dev->iommu member 
is NULL.

An dev_err outputs the device as "pci :00:02.0: DMAR" which is the intel HD 
620 graphic adapter in a Lenovo T470s device.

The following patch (also attached as intel-iommu.patch) avoids this crash by 
checking the pointer.

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index f8177c59d229..2d285a42db3f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4053,7 +4053,8 @@ static void __init init_no_remapping_devices(void)
 drhd->ignored = 1;
 for_each_active_dev_scope(drhd->devices,
   drhd->devices_cnt, i, dev)
-   dev_iommu_priv_set(dev, 
DUMMY_DEVICE_DOMAIN_INFO);
+   if (dev->iommu)
+   dev_iommu_priv_set(dev, 
DUMMY_DEVICE_DOMAIN_INFO);


This looks more like a generic issue, used-before-allocated, and should
be fixed in iommu.c instead of VT-d driver. How about

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 8fd93a5b8764..a599da87eb60 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -190,6 +190,28 @@ static void dev_iommu_free(struct device *dev)
dev->iommu = NULL;
 }

+void *dev_iommu_priv_get(struct device *dev)
+{
+   struct dev_iommu *param = dev_iommu_get(dev);
+
+   if (WARN_ON(!param))
+   return ERR_PTR(-ENOMEM);
+
+return param->priv;
+}
+EXPORT_SYMBOL_GPL(dev_iommu_priv_get);
+
+void dev_iommu_priv_set(struct device *dev, void *priv)
+{
+   struct dev_iommu *param = dev_iommu_get(dev);
+
+   if (WARN_ON(!param))
+   return;
+
+param->priv = priv;
+}
+EXPORT_SYMBOL_GPL(dev_iommu_priv_set);
+

Best regards,
baolu


 }
 }
  }

I assume the problem might be related to the following commit introduced in 
v5.9-rc1:

commit 01b9d4e21148c89fdbab3d6b3705f9791314b631
Author: Joerg Roedel 
Date:   Thu Jun 25 15:08:25 2020 +0200

 iommu/vt-d: Use dev_iommu_priv_get/set()
 
 Remove the use of dev->archdata.iommu and use the private per-device

 pointer provided by IOMMU core code instead.

With regards,

Torsten Hilbrich


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundati

[PATCH v8 3/7] iommu/uapi: Introduce enum type for PASID data format

2020-08-31 Thread Jacob Pan
There can be multiple vendor-specific PASID data formats used in UAPI
structures. This patch adds enum type with a last entry which makes
range checking much easier.

Suggested-by: Alex Williamson 
Reviewed-by: Eric Auger 
Signed-off-by: Jacob Pan 
---
 include/uapi/linux/iommu.h | 8 ++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
index b42acc8fe007..7cc6ee6c41f7 100644
--- a/include/uapi/linux/iommu.h
+++ b/include/uapi/linux/iommu.h
@@ -298,11 +298,16 @@ struct iommu_gpasid_bind_data_vtd {
 IOMMU_SVA_VTD_GPASID_PCD |  \
 IOMMU_SVA_VTD_GPASID_PWT)
 
+enum iommu_pasid_data_format {
+   IOMMU_PASID_FORMAT_INTEL_VTD = 1,
+   IOMMU_PASID_FORMAT_LAST,
+};
+
 /**
  * struct iommu_gpasid_bind_data - Information about device and guest PASID 
binding
  * @argsz: User filled size of this data
  * @version:   Version of this data structure
- * @format:PASID table entry format
+ * @format:PASID table entry format of enum iommu_pasid_data_format type
  * @flags: Additional information on guest bind request
  * @gpgd:  Guest page directory base of the guest mm to bind
  * @hpasid:Process address space ID used for the guest mm in host IOMMU
@@ -321,7 +326,6 @@ struct iommu_gpasid_bind_data {
__u32 argsz;
 #define IOMMU_GPASID_BIND_VERSION_11
__u32 version;
-#define IOMMU_PASID_FORMAT_INTEL_VTD   1
__u32 format;
__u32 addr_width;
 #define IOMMU_SVA_GPASID_VAL   (1 << 0) /* guest PASID valid */
-- 
2.7.4

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 2/7] iommu/uapi: Add argsz for user filled data

2020-08-31 Thread Jacob Pan
As IOMMU UAPI gets extended, user data size may increase. To support
backward compatibiliy, this patch introduces a size field to each UAPI
data structures. It is *always* the responsibility for the user to fill in
the correct size. Padding fields are adjusted to ensure 8 byte alignment.

Specific scenarios for user data handling are documented in:
Documentation/userspace-api/iommu.rst

As there is no current users of the API, struct version is not
incremented.

Reviewed-by: Eric Auger 
Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
 include/uapi/linux/iommu.h | 12 +---
 1 file changed, 9 insertions(+), 3 deletions(-)

diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
index c2b2caf9ed41..b42acc8fe007 100644
--- a/include/uapi/linux/iommu.h
+++ b/include/uapi/linux/iommu.h
@@ -139,6 +139,7 @@ enum iommu_page_response_code {
 
 /**
  * struct iommu_page_response - Generic page response information
+ * @argsz: User filled size of this data
  * @version: API version of this structure
  * @flags: encodes whether the corresponding fields are valid
  * (IOMMU_FAULT_PAGE_RESPONSE_* values)
@@ -147,6 +148,7 @@ enum iommu_page_response_code {
  * @code: response code from &enum iommu_page_response_code
  */
 struct iommu_page_response {
+   __u32   argsz;
 #define IOMMU_PAGE_RESP_VERSION_1  1
__u32   version;
 #define IOMMU_PAGE_RESP_PASID_VALID(1 << 0)
@@ -222,6 +224,7 @@ struct iommu_inv_pasid_info {
 /**
  * struct iommu_cache_invalidate_info - First level/stage invalidation
  * information
+ * @argsz: User filled size of this data
  * @version: API version of this structure
  * @cache: bitfield that allows to select which caches to invalidate
  * @granularity: defines the lowest granularity used for the invalidation:
@@ -250,6 +253,7 @@ struct iommu_inv_pasid_info {
  * must support the used granularity.
  */
 struct iommu_cache_invalidate_info {
+   __u32   argsz;
 #define IOMMU_CACHE_INVALIDATE_INFO_VERSION_1 1
__u32   version;
 /* IOMMU paging structure cache */
@@ -259,7 +263,7 @@ struct iommu_cache_invalidate_info {
 #define IOMMU_CACHE_INV_TYPE_NR(3)
__u8cache;
__u8granularity;
-   __u8padding[2];
+   __u8padding[6];
union {
struct iommu_inv_pasid_info pasid_info;
struct iommu_inv_addr_info addr_info;
@@ -296,6 +300,7 @@ struct iommu_gpasid_bind_data_vtd {
 
 /**
  * struct iommu_gpasid_bind_data - Information about device and guest PASID 
binding
+ * @argsz: User filled size of this data
  * @version:   Version of this data structure
  * @format:PASID table entry format
  * @flags: Additional information on guest bind request
@@ -313,17 +318,18 @@ struct iommu_gpasid_bind_data_vtd {
  * PASID to host PASID based on this bind data.
  */
 struct iommu_gpasid_bind_data {
+   __u32 argsz;
 #define IOMMU_GPASID_BIND_VERSION_11
__u32 version;
 #define IOMMU_PASID_FORMAT_INTEL_VTD   1
__u32 format;
+   __u32 addr_width;
 #define IOMMU_SVA_GPASID_VAL   (1 << 0) /* guest PASID valid */
__u64 flags;
__u64 gpgd;
__u64 hpasid;
__u64 gpasid;
-   __u32 addr_width;
-   __u8  padding[12];
+   __u8  padding[8];
/* Vendor specific data */
union {
struct iommu_gpasid_bind_data_vtd vtd;
-- 
2.7.4

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 6/7] iommu/uapi: Handle data and argsz filled by users

2020-08-31 Thread Jacob Pan
IOMMU user APIs are responsible for processing user data. This patch
changes the interface such that user pointers can be passed into IOMMU
code directly. Separate kernel APIs without user pointers are introduced
for in-kernel users of the UAPI functionality.

IOMMU UAPI data has a user filled argsz field which indicates the data
length of the structure. User data is not trusted, argsz must be
validated based on the current kernel data size, mandatory data size,
and feature flags.

User data may also be extended, resulting in possible argsz increase.
Backward compatibility is ensured based on size and flags (or
the functional equivalent fields) checking.

This patch adds sanity checks in the IOMMU layer. In addition to argsz,
reserved/unused fields in padding, flags, and version are also checked.
Details are documented in Documentation/userspace-api/iommu.rst

Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
 drivers/iommu/iommu.c | 201 --
 include/linux/iommu.h |  28 ---
 2 files changed, 212 insertions(+), 17 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 4ae02291ccc2..3bc263ae31ed 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1961,33 +1961,218 @@ int iommu_attach_device(struct iommu_domain *domain, 
struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device);
 
+/*
+ * Check flags and other user provided data for valid combinations. We also
+ * make sure no reserved fields or unused flags are set. This is to ensure
+ * not breaking userspace in the future when these fields or flags are used.
+ */
+static int iommu_check_cache_invl_data(struct iommu_cache_invalidate_info 
*info)
+{
+   u32 mask;
+   int i;
+
+   if (info->version != IOMMU_CACHE_INVALIDATE_INFO_VERSION_1)
+   return -EINVAL;
+
+   mask = (1 << IOMMU_CACHE_INV_TYPE_NR) - 1;
+   if (info->cache & ~mask)
+   return -EINVAL;
+
+   if (info->granularity >= IOMMU_INV_GRANU_NR)
+   return -EINVAL;
+
+   switch (info->granularity) {
+   case IOMMU_INV_GRANU_ADDR:
+   if (info->cache & IOMMU_CACHE_INV_TYPE_PASID)
+   return -EINVAL;
+
+   mask = IOMMU_INV_ADDR_FLAGS_PASID |
+   IOMMU_INV_ADDR_FLAGS_ARCHID |
+   IOMMU_INV_ADDR_FLAGS_LEAF;
+
+   if (info->granu.addr_info.flags & ~mask)
+   return -EINVAL;
+   break;
+   case IOMMU_INV_GRANU_PASID:
+   mask = IOMMU_INV_PASID_FLAGS_PASID |
+   IOMMU_INV_PASID_FLAGS_ARCHID;
+   if (info->granu.pasid_info.flags & ~mask)
+   return -EINVAL;
+
+   break;
+   case IOMMU_INV_GRANU_DOMAIN:
+   if (info->cache & IOMMU_CACHE_INV_TYPE_DEV_IOTLB)
+   return -EINVAL;
+   break;
+   default:
+   return -EINVAL;
+   }
+
+   /* Check reserved padding fields */
+   for (i = 0; i < sizeof(info->padding); i++) {
+   if (info->padding[i])
+   return -EINVAL;
+   }
+
+   return 0;
+}
+
 int iommu_uapi_cache_invalidate(struct iommu_domain *domain, struct device 
*dev,
-   struct iommu_cache_invalidate_info *inv_info)
+   void __user *uinfo)
 {
+   struct iommu_cache_invalidate_info inv_info = { 0 };
+   u32 minsz;
+   int ret = 0;
+
if (unlikely(!domain->ops->cache_invalidate))
return -ENODEV;
 
-   return domain->ops->cache_invalidate(domain, dev, inv_info);
+   /*
+* No new spaces can be added before the variable sized union, the
+* minimum size is the offset to the union.
+*/
+   minsz = offsetof(struct iommu_cache_invalidate_info, granu);
+
+   /* Copy minsz from user to get flags and argsz */
+   if (copy_from_user(&inv_info, uinfo, minsz))
+   return -EFAULT;
+
+   /* Fields before variable size union is mandatory */
+   if (inv_info.argsz < minsz)
+   return -EINVAL;
+
+   /* PASID and address granu require additional info beyond minsz */
+   if (inv_info.argsz == minsz &&
+   ((inv_info.granularity == IOMMU_INV_GRANU_PASID) ||
+   (inv_info.granularity == IOMMU_INV_GRANU_ADDR)))
+   return -EINVAL;
+
+   if (inv_info.granularity == IOMMU_INV_GRANU_PASID &&
+   inv_info.argsz < offsetofend(struct iommu_cache_invalidate_info, 
granu.pasid_info))
+   return -EINVAL;
+
+   if (inv_info.granularity == IOMMU_INV_GRANU_ADDR &&
+   inv_info.argsz < offsetofend(struct iommu_cache_invalidate_info, 
granu.addr_info))
+   return -EINVAL;
+
+   /*
+* User might be using a newer UAPI header which has a larger data
+* size, we shall support the existing flag

[PATCH v8 4/7] iommu/uapi: Use named union for user data

2020-08-31 Thread Jacob Pan
IOMMU UAPI data size is filled by the user space which must be validated
by the kernel. To ensure backward compatibility, user data can only be
extended by either re-purpose padding bytes or extend the variable sized
union at the end. No size change is allowed before the union. Therefore,
the minimum size is the offset of the union.

To use offsetof() on the union, we must make it named.

Link: https://lore.kernel.org/linux-iommu/20200611145518.0c281...@x1.home/
Signed-off-by: Jacob Pan 
Reviewed-by: Lu Baolu 
Reviewed-by: Eric Auger 
---
 drivers/iommu/intel/iommu.c | 22 +++---
 drivers/iommu/intel/svm.c   |  2 +-
 include/uapi/linux/iommu.h  |  4 ++--
 3 files changed, 14 insertions(+), 14 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index e9864e52b0e9..43f16f0cebde 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5425,8 +5425,8 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
 
/* Size is only valid in address selective invalidation */
if (inv_info->granularity == IOMMU_INV_GRANU_ADDR)
-   size = to_vtd_size(inv_info->addr_info.granule_size,
-  inv_info->addr_info.nb_granules);
+   size = to_vtd_size(inv_info->granu.addr_info.granule_size,
+  inv_info->granu.addr_info.nb_granules);
 
for_each_set_bit(cache_type,
 (unsigned long *)&inv_info->cache,
@@ -5447,20 +5447,20 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
 * granularity.
 */
if (inv_info->granularity == IOMMU_INV_GRANU_PASID &&
-   (inv_info->pasid_info.flags & IOMMU_INV_PASID_FLAGS_PASID))
-   pasid = inv_info->pasid_info.pasid;
+   (inv_info->granu.pasid_info.flags & 
IOMMU_INV_PASID_FLAGS_PASID))
+   pasid = inv_info->granu.pasid_info.pasid;
else if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
-(inv_info->addr_info.flags & 
IOMMU_INV_ADDR_FLAGS_PASID))
-   pasid = inv_info->addr_info.pasid;
+(inv_info->granu.addr_info.flags & 
IOMMU_INV_ADDR_FLAGS_PASID))
+   pasid = inv_info->granu.addr_info.pasid;
 
switch (BIT(cache_type)) {
case IOMMU_CACHE_INV_TYPE_IOTLB:
/* HW will ignore LSB bits based on address mask */
if (inv_info->granularity == IOMMU_INV_GRANU_ADDR &&
size &&
-   (inv_info->addr_info.addr & ((BIT(VTD_PAGE_SHIFT + 
size)) - 1))) {
+   (inv_info->granu.addr_info.addr & 
((BIT(VTD_PAGE_SHIFT + size)) - 1))) {
pr_err_ratelimited("User address not aligned, 
0x%llx, size order %llu\n",
-  inv_info->addr_info.addr, 
size);
+  
inv_info->granu.addr_info.addr, size);
}
 
/*
@@ -5468,9 +5468,9 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
 * We use npages = -1 to indicate that.
 */
qi_flush_piotlb(iommu, did, pasid,
-   mm_to_dma_pfn(inv_info->addr_info.addr),
+   
mm_to_dma_pfn(inv_info->granu.addr_info.addr),
(granu == QI_GRAN_NONG_PASID) ? -1 : 1 
<< size,
-   inv_info->addr_info.flags & 
IOMMU_INV_ADDR_FLAGS_LEAF);
+   inv_info->granu.addr_info.flags & 
IOMMU_INV_ADDR_FLAGS_LEAF);
 
if (!info->ats_enabled)
break;
@@ -5493,7 +5493,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
size = 64 - VTD_PAGE_SHIFT;
addr = 0;
} else if (inv_info->granularity == 
IOMMU_INV_GRANU_ADDR) {
-   addr = inv_info->addr_info.addr;
+   addr = inv_info->granu.addr_info.addr;
}
 
if (info->ats_enabled)
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 95c3164a2302..99353d6468fa 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -370,7 +370,7 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, 
struct device *dev,
spin_lock(&iommu->lock);
ret = intel_pasid_setup_nested(iommu, dev,
   (pgd_t *)(uintptr_t)data->gpgd,
-  data->hpasid,

[PATCH v8 7/7] iommu/vt-d: Check UAPI data processed by IOMMU core

2020-08-31 Thread Jacob Pan
IOMMU generic layer already does sanity checks on UAPI data for version
match and argsz range based on generic information.

This patch adjusts the following data checking responsibilities:
- removes the redundant version check from VT-d driver
- removes the check for vendor specific data size
- adds check for the use of reserved/undefined flags

Signed-off-by: Jacob Pan 
---
 drivers/iommu/intel/iommu.c |  3 +--
 drivers/iommu/intel/svm.c   | 11 +--
 include/uapi/linux/iommu.h  |  1 +
 3 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index 43f16f0cebde..a3a0b5c8921d 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -5399,8 +5399,7 @@ intel_iommu_sva_invalidate(struct iommu_domain *domain, 
struct device *dev,
int ret = 0;
u64 size = 0;
 
-   if (!inv_info || !dmar_domain ||
-   inv_info->version != IOMMU_CACHE_INVALIDATE_INFO_VERSION_1)
+   if (!inv_info || !dmar_domain)
return -EINVAL;
 
if (!dev || !dev_is_pci(dev))
diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
index 99353d6468fa..0cb9a15f1112 100644
--- a/drivers/iommu/intel/svm.c
+++ b/drivers/iommu/intel/svm.c
@@ -284,8 +284,15 @@ int intel_svm_bind_gpasid(struct iommu_domain *domain, 
struct device *dev,
if (WARN_ON(!iommu) || !data)
return -EINVAL;
 
-   if (data->version != IOMMU_GPASID_BIND_VERSION_1 ||
-   data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
+   if (data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
+   return -EINVAL;
+
+   /* IOMMU core ensures argsz is more than the start of the union */
+   if (data->argsz < offsetofend(struct iommu_gpasid_bind_data, 
vendor.vtd))
+   return -EINVAL;
+
+   /* Make sure no undefined flags are used in vendor data */
+   if (data->vendor.vtd.flags & ~(IOMMU_SVA_VTD_GPASID_LAST - 1))
return -EINVAL;
 
if (!dev_is_pci(dev))
diff --git a/include/uapi/linux/iommu.h b/include/uapi/linux/iommu.h
index c64bca5af419..1ebc23df4fbc 100644
--- a/include/uapi/linux/iommu.h
+++ b/include/uapi/linux/iommu.h
@@ -288,6 +288,7 @@ struct iommu_gpasid_bind_data_vtd {
 #define IOMMU_SVA_VTD_GPASID_PWT   (1 << 3) /* page-level write through */
 #define IOMMU_SVA_VTD_GPASID_EMTE  (1 << 4) /* extended mem type enable */
 #define IOMMU_SVA_VTD_GPASID_CD(1 << 5) /* PASID-level cache 
disable */
+#define IOMMU_SVA_VTD_GPASID_LAST  (1 << 6)
__u64 flags;
__u32 pat;
__u32 emt;
-- 
2.7.4

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 5/7] iommu/uapi: Rename uapi functions

2020-08-31 Thread Jacob Pan
User APIs such as iommu_sva_unbind_gpasid() may also be used by the
kernel. Since we introduced user pointer to the UAPI functions,
in-kernel callers cannot share the same APIs. In-kernel callers are also
trusted, there is no need to validate the data.

We plan to have two flavors of the same API functions, one called
through ioctls, carrying a user pointer and one called directly with
valid IOMMU UAPI structs. To differentiate both, let's rename existing
functions with an iommu_uapi_ prefix.

Suggested-by: Alex Williamson 
Reviewed-by: Eric Auger 
Signed-off-by: Jacob Pan 
---
 drivers/iommu/iommu.c | 18 +-
 include/linux/iommu.h | 31 ---
 2 files changed, 25 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index 609bd25bf154..4ae02291ccc2 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1961,35 +1961,35 @@ int iommu_attach_device(struct iommu_domain *domain, 
struct device *dev)
 }
 EXPORT_SYMBOL_GPL(iommu_attach_device);
 
-int iommu_cache_invalidate(struct iommu_domain *domain, struct device *dev,
-  struct iommu_cache_invalidate_info *inv_info)
+int iommu_uapi_cache_invalidate(struct iommu_domain *domain, struct device 
*dev,
+   struct iommu_cache_invalidate_info *inv_info)
 {
if (unlikely(!domain->ops->cache_invalidate))
return -ENODEV;
 
return domain->ops->cache_invalidate(domain, dev, inv_info);
 }
-EXPORT_SYMBOL_GPL(iommu_cache_invalidate);
+EXPORT_SYMBOL_GPL(iommu_uapi_cache_invalidate);
 
-int iommu_sva_bind_gpasid(struct iommu_domain *domain,
-  struct device *dev, struct iommu_gpasid_bind_data 
*data)
+int iommu_uapi_sva_bind_gpasid(struct iommu_domain *domain,
+  struct device *dev, struct 
iommu_gpasid_bind_data *data)
 {
if (unlikely(!domain->ops->sva_bind_gpasid))
return -ENODEV;
 
return domain->ops->sva_bind_gpasid(domain, dev, data);
 }
-EXPORT_SYMBOL_GPL(iommu_sva_bind_gpasid);
+EXPORT_SYMBOL_GPL(iommu_uapi_sva_bind_gpasid);
 
-int iommu_sva_unbind_gpasid(struct iommu_domain *domain, struct device *dev,
-ioasid_t pasid)
+int iommu_uapi_sva_unbind_gpasid(struct iommu_domain *domain, struct device 
*dev,
+ioasid_t pasid)
 {
if (unlikely(!domain->ops->sva_unbind_gpasid))
return -ENODEV;
 
return domain->ops->sva_unbind_gpasid(dev, pasid);
 }
-EXPORT_SYMBOL_GPL(iommu_sva_unbind_gpasid);
+EXPORT_SYMBOL_GPL(iommu_uapi_sva_unbind_gpasid);
 
 static void __iommu_detach_device(struct iommu_domain *domain,
  struct device *dev)
diff --git a/include/linux/iommu.h b/include/linux/iommu.h
index fee209efb756..710d5d2691eb 100644
--- a/include/linux/iommu.h
+++ b/include/linux/iommu.h
@@ -424,13 +424,13 @@ extern int iommu_attach_device(struct iommu_domain 
*domain,
   struct device *dev);
 extern void iommu_detach_device(struct iommu_domain *domain,
struct device *dev);
-extern int iommu_cache_invalidate(struct iommu_domain *domain,
- struct device *dev,
- struct iommu_cache_invalidate_info *inv_info);
-extern int iommu_sva_bind_gpasid(struct iommu_domain *domain,
-   struct device *dev, struct iommu_gpasid_bind_data *data);
-extern int iommu_sva_unbind_gpasid(struct iommu_domain *domain,
-   struct device *dev, ioasid_t pasid);
+extern int iommu_uapi_cache_invalidate(struct iommu_domain *domain,
+  struct device *dev,
+  struct iommu_cache_invalidate_info 
*inv_info);
+extern int iommu_uapi_sva_bind_gpasid(struct iommu_domain *domain,
+ struct device *dev, struct 
iommu_gpasid_bind_data *data);
+extern int iommu_uapi_sva_unbind_gpasid(struct iommu_domain *domain,
+   struct device *dev, ioasid_t pasid);
 extern struct iommu_domain *iommu_get_domain_for_dev(struct device *dev);
 extern struct iommu_domain *iommu_get_dma_domain(struct device *dev);
 extern int iommu_map(struct iommu_domain *domain, unsigned long iova,
@@ -1032,21 +1032,22 @@ static inline int iommu_sva_get_pasid(struct iommu_sva 
*handle)
return IOMMU_PASID_INVALID;
 }
 
-static inline int
-iommu_cache_invalidate(struct iommu_domain *domain,
-  struct device *dev,
-  struct iommu_cache_invalidate_info *inv_info)
+static inline int iommu_uapi_cache_invalidate(struct iommu_domain *domain,
+ struct device *dev,
+ struct 
iommu_cache_invalidate_info *inv_info)
 {
return -ENODEV;
 }
-static inline int iom

[PATCH v8 0/7] IOMMU user API enhancement

2020-08-31 Thread Jacob Pan
IOMMU user API header was introduced to support nested DMA translation and
related fault handling. The current UAPI data structures consist of three
areas that cover the interactions between host kernel and guest:
 - fault handling
 - cache invalidation
 - bind guest page tables, i.e. guest PASID

Future extensions are likely to support more architectures and vIOMMU features.

In the previous discussion, using user-filled data size and feature flags is
made a preferred approach over a unified version number.
https://lkml.org/lkml/2020/1/29/45

In addition to introduce argsz field to data structures, this patchset is also
trying to document the UAPI design, usage, and extension rules. VT-d driver
changes to utilize the new argsz field is included, VFIO usage is to follow.

This set is available at:
https://github.com/jacobpan/linux.git vsva_v5.8_uapi_v8

Thanks,

Jacob


Changelog:
v8
- Rebased to v5.9-rc2
- Addressed review comments from Eric Auger
  1. added a check for the unused vendor flags
  2. commit message improvements
v7
- Added PASID data format enum for range checking
- Tidy up based on reviews from Alex W.
- Removed doc section for vIOMMU fault handling
v6
- Renamed all UAPI functions with iommu_uapi_ prefix
- Replaced argsz maxsz checking with flag specific size checks
- Documentation improvements based on suggestions by Eric Auger
  Replaced example code with a pointer to the actual code
- Added more checks for illegal flags combinations
- Added doc file to MAINTAINERS
v5
- Addjusted paddings in UAPI data to be 8 byte aligned
- Do not clobber argsz in IOMMU core before passing on to vendor driver
- Removed pr_warn_ for invalid UAPI data check, just return -EINVAL
- Clarified VFIO responsibility in UAPI data handling
- Use iommu_uapi prefix to differentiate APIs has in-kernel caller
- Added comment for unchecked flags of invalidation granularity
- Added example in doc to show vendor data checking

v4
- Added checks of UAPI data for reserved fields, version, and flags.
- Removed version check from vendor driver (vt-d)
- Relaxed argsz check to match the UAPI struct size instead of variable
  union size
- Updated documentation

v3:
- Rewrote backward compatibility rule to support existing code
  re-compiled with newer kernel UAPI header that runs on older
  kernel. Based on review comment from Alex W.
  https://lore.kernel.org/linux-iommu/20200611094741.6d118...@w520.home/
- Take user pointer directly in UAPI functions. Perform argsz check
  and copy_from_user() in IOMMU driver. Eliminate the need for
  VFIO or other upper layer to parse IOMMU data.
- Create wrapper function for in-kernel users of UAPI functions
v2:
- Removed unified API version and helper
- Introduced argsz for each UAPI data
- Introduced UAPI doc


Jacob Pan (7):
  docs: IOMMU user API
  iommu/uapi: Add argsz for user filled data
  iommu/uapi: Introduce enum type for PASID data format
  iommu/uapi: Use named union for user data
  iommu/uapi: Rename uapi functions
  iommu/uapi: Handle data and argsz filled by users
  iommu/vt-d: Check UAPI data processed by IOMMU core

 Documentation/userspace-api/iommu.rst | 211 ++
 MAINTAINERS   |   1 +
 drivers/iommu/intel/iommu.c   |  25 ++--
 drivers/iommu/intel/svm.c |  13 ++-
 drivers/iommu/iommu.c | 205 +++--
 include/linux/iommu.h |  35 --
 include/uapi/linux/iommu.h|  25 ++--
 7 files changed, 470 insertions(+), 45 deletions(-)
 create mode 100644 Documentation/userspace-api/iommu.rst

-- 
2.7.4

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[PATCH v8 1/7] docs: IOMMU user API

2020-08-31 Thread Jacob Pan
IOMMU UAPI is newly introduced to support communications between guest
virtual IOMMU and host IOMMU. There has been lots of discussions on how
it should work with VFIO UAPI and userspace in general.

This document is intended to clarify the UAPI design and usage. The
mechanics of how future extensions should be achieved are also covered
in this documentation.

Reviewed-by: Eric Auger 
Signed-off-by: Liu Yi L 
Signed-off-by: Jacob Pan 
---
 Documentation/userspace-api/iommu.rst | 211 ++
 MAINTAINERS   |   1 +
 2 files changed, 212 insertions(+)
 create mode 100644 Documentation/userspace-api/iommu.rst

diff --git a/Documentation/userspace-api/iommu.rst 
b/Documentation/userspace-api/iommu.rst
new file mode 100644
index ..1e68e8f05bb3
--- /dev/null
+++ b/Documentation/userspace-api/iommu.rst
@@ -0,0 +1,211 @@
+.. SPDX-License-Identifier: GPL-2.0
+.. iommu:
+
+=
+IOMMU Userspace API
+=
+
+IOMMU UAPI is used for virtualization cases where communications are
+needed between physical and virtual IOMMU drivers. For baremetal
+usage, the IOMMU is a system device which does not need to communicate
+with user space directly.
+
+The primary use cases are guest Shared Virtual Address (SVA) and
+guest IO virtual address (IOVA), wherin the vIOMMU implementation
+relies on the physical IOMMU and for this reason requires interactions
+with the host driver.
+
+.. contents:: :local:
+
+Functionalities
+===
+Communications of user and kernel involve both directions. The
+supported user-kernel APIs are as follows:
+
+1. Alloc/Free PASID
+2. Bind/Unbind guest PASID (e.g. Intel VT-d)
+3. Bind/Unbind guest PASID table (e.g. ARM SMMU)
+4. Invalidate IOMMU caches upon guest requests
+5. Report errors to the guest and serve page requests
+
+Requirements
+
+The IOMMU UAPIs are generic and extensible to meet the following
+requirements:
+
+1. Emulated and para-virtualised vIOMMUs
+2. Multiple vendors (Intel VT-d, ARM SMMU, etc.)
+3. Extensions to the UAPI shall not break existing user space
+
+Interfaces
+==
+Although the data structures defined in IOMMU UAPI are self-contained,
+there is no user API functions introduced. Instead, IOMMU UAPI is
+designed to work with existing user driver frameworks such as VFIO.
+
+Extension Rules & Precautions
+-
+When IOMMU UAPI gets extended, the data structures can *only* be
+modified in two ways:
+
+1. Adding new fields by re-purposing the padding[] field. No size change.
+2. Adding new union members at the end. May increase the structure sizes.
+
+No new fields can be added *after* the variable sized union in that it
+will break backward compatibility when offset moves. A new flag must
+be introduced whenever a change affects the structure using either
+method. The IOMMU driver processes the data based on flags which
+ensures backward compatibility.
+
+Version field is only reserved for the unlikely event of UAPI upgrade
+at its entirety.
+
+It's *always* the caller's responsibility to indicate the size of the
+structure passed by setting argsz appropriately.
+Though at the same time, argsz is user provided data which is not
+trusted. The argsz field allows the user app to indicate how much data
+it is providing, it's still the kernel's responsibility to validate
+whether it's correct and sufficient for the requested operation.
+
+Compatibility Checking
+--
+When IOMMU UAPI extension results in some structure size increase,
+IOMMU UAPI code shall handle the following cases:
+
+1. User and kernel has exact size match
+2. An older user with older kernel header (smaller UAPI size) running on a
+   newer kernel (larger UAPI size)
+3. A newer user with newer kernel header (larger UAPI size) running
+   on an older kernel.
+4. A malicious/misbehaving user pass illegal/invalid size but within
+   range. The data may contain garbage.
+
+Feature Checking
+
+While launching a guest with vIOMMU, it is strongly advised to check
+the compatibility upfront, as some subsequent errors happening during
+vIOMMU operation, such as cache invalidation failures cannot be nicely
+escaladated to the guest due to IOMMU specifications. This can lead to
+catastrophic failures for the users.
+
+User applications such as QEMU are expected to import kernel UAPI
+headers. Backward compatibility is supported per feature flags.
+For example, an older QEMU (with older kernel header) can run on newer
+kernel. Newer QEMU (with new kernel header) may refuse to initialize
+on an older kernel if new feature flags are not supported by older
+kernel. Simply recompiling existing code with newer kernel header should
+not be an issue in that only existing flags are used.
+
+IOMMU vendor driver should report the below features to IOMMU UAPI
+consumers (e.g. via VFIO).
+
+1. IOMMU_NESTING_FEAT_SYSWIDE_PASID

Re: [PATCH v7 7/7] iommu/vt-d: Check UAPI data processed by IOMMU core

2020-08-31 Thread Jacob Pan
On Thu, 13 Aug 2020 11:19:46 +0200
Auger Eric  wrote:

> Hi Jacob,
> 
> On 7/30/20 2:21 AM, Jacob Pan wrote:
> > IOMMU generic layer already does sanity checks UAPI data for version
> > match and argsz range under generic information.
> > Remove the redundant version check from VT-d driver and check for
> > vendor specific data size.
> > 
> > Signed-off-by: Jacob Pan   
> 
> > ---
> >  drivers/iommu/intel/iommu.c | 3 +--
> >  drivers/iommu/intel/svm.c   | 7 +--
> >  2 files changed, 6 insertions(+), 4 deletions(-)
> > 
> > diff --git a/drivers/iommu/intel/iommu.c
> > b/drivers/iommu/intel/iommu.c index 021f62078f52..7e03cca31a0e
> > 100644 --- a/drivers/iommu/intel/iommu.c
> > +++ b/drivers/iommu/intel/iommu.c
> > @@ -5391,8 +5391,7 @@ intel_iommu_sva_invalidate(struct
> > iommu_domain *domain, struct device *dev, int ret = 0;
> > u64 size = 0;
> >  
> > -   if (!inv_info || !dmar_domain ||
> > -   inv_info->version !=
> > IOMMU_CACHE_INVALIDATE_INFO_VERSION_1)
> > +   if (!inv_info || !dmar_domain)
> > return -EINVAL;
> >  
> > if (!dev || !dev_is_pci(dev))
> > diff --git a/drivers/iommu/intel/svm.c b/drivers/iommu/intel/svm.c
> > index 713b3a218483..55ea11e9c0f5 100644
> > --- a/drivers/iommu/intel/svm.c
> > +++ b/drivers/iommu/intel/svm.c
> > @@ -240,8 +240,11 @@ int intel_svm_bind_gpasid(struct iommu_domain
> > *domain, struct device *dev, if (WARN_ON(!iommu) || !data)
> > return -EINVAL;
> >  
> > -   if (data->version != IOMMU_GPASID_BIND_VERSION_1 ||
> > -   data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
> > +   if (data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
> > +   return -EINVAL;
> > +
> > +   /* IOMMU core ensures argsz is more than the start of the
> > union */
> > +   if (data->argsz < offsetofend(struct
> > iommu_gpasid_bind_data, vendor.vtd)) return -EINVAL;  
> Shouldn't you test the vendor flags here?
> intel_pasid_setup_bind_data() only checks valid ones but not ~mask.
> 
Yes, vendor flags should be tested to make sure there is no undefined
flags being used.

Thanks!

> Thanks
> 
> Eric
> >  
> > if (!dev_is_pci(dev))
> >   
> 

[Jacob Pan]
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [patch V2 46/46] irqchip: Add IMS (Interrupt Message Storm) driver - NOT FOR MERGING

2020-08-31 Thread Jason Gunthorpe
On Wed, Aug 26, 2020 at 01:17:14PM +0200, Thomas Gleixner wrote:
> + * ims_queue_info - Information to create an IMS queue domain
> + * @queue_lock:  Callback which informs the device driver that
> + *   an interrupt management operation starts.
> + * @queue_sync_unlock:   Callback which informs the device driver that an
> + *   interrupt management operation ends.
> +
> + * @queue_get_shadow:   Callback to retrieve te shadow storage for a MSI
> + *   entry associated to a queue. The queue is
> + *   identified by the device struct which is used for
> + *   allocating interrupts and the msi entry index.
> + *
> + * @queue_lock() and @queue_sync_unlock() are only called for management
> + * operations on a particular interrupt: request, free, enable, disable,
> + * affinity setting.  These functions are never called from atomic context,
> + * like low level interrupt handling code. The purpose of these functions
> + * is to signal the device driver the start and end of an operation which
> + * affects the IMS queue shadow state. @queue_lock() allows the driver to
> + * do preperatory work, e.g. locking. Note, that @queue_lock() has to
> + * preserve the sleepable state on return. That means the driver cannot
> + * disable preemption and (soft)interrupts in @queue_lock and then undo
> + * that operation in @queue_sync_unlock() which restricts the lock types
> + * for eventual serialization of these operations to sleepable locks. Of
> + * course the driver can disable preemption and (soft)interrupts
> + * temporarily for internal work.
> + *
> + * On @queue_sync_unlock() the driver has to check whether the shadow state
> + * changed and issue a command to update the hardware state and wait for
> + * the command to complete. If the command fails or times out then the
> + * driver has to take care of the resulting mess as this is called from
> + * functions which have no return value and none of the callers can deal
> + * with the failure. The lock which is used by the driver to protect a
> + * operation sequence must obviously not be released before the command
> + * completes or fails. Otherwise new operations on the same interrupt line
> + * could take place and change the shadow state before the driver was able
> + * to compose the command.

I haven't looked through everything in detail, but this does look like
it is good for the mlx5 devices. Looked like it was only one small
update to the set_affinity, so not very disruptive?

Thanks,
Jason
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [patch V2 24/46] PCI: vmd: Mark VMD irqdomain with DOMAIN_BUS_VMD_MSI

2020-08-31 Thread Jason Gunthorpe
On Wed, Aug 26, 2020 at 01:16:52PM +0200, Thomas Gleixner wrote:
> From: Thomas Gleixner 
> 
> Devices on the VMD bus use their own MSI irq domain, but it is not
> distinguishable from regular PCI/MSI irq domains. This is required
> to exclude VMD devices from getting the irq domain pointer set by
> interrupt remapping.
> 
> Override the default bus token.
> 
> Signed-off-by: Thomas Gleixner 
> Acked-by: Bjorn Helgaas 
>  drivers/pci/controller/vmd.c |6 ++
>  1 file changed, 6 insertions(+)
> 
> +++ b/drivers/pci/controller/vmd.c
> @@ -579,6 +579,12 @@ static int vmd_enable_domain(struct vmd_
>   return -ENODEV;
>   }
>  
> + /*
> +  * Override the irq domain bus token so the domain can be distinguished
> +  * from a regular PCI/MSI domain.
> +  */
> + irq_domain_update_bus_token(vmd->irq_domain, DOMAIN_BUS_VMD_MSI);
> +

Having the non-transparent-bridge hold a MSI table and
multiplex/de-multiplex IRQs looks like another good use case for
something close to pci_subdevice_msi_create_irq_domain()?

If each device could have its own internal MSI-X table programmed
properly things would work alot better. Disable capture/remap of the
MSI range in the NTB.

Then each device could have a proper non-multiplexed interrupt
delivered to the CPU.. Affinity would work properly, no need to share
IRQs (eg vmd_irq() goes away)/etc.

Something for the VMD maintainers to think about at least.

As I hear more about NTB these days a full MSI scheme for NTB seems
interesting to have in the PCI-E core code..

Jason
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


[Regression] [PATCH] iommu: Avoid crash in init_no_remapping_devices if iommu is NULL

2020-08-31 Thread Torsten Hilbrich
I noticed a kernel crash when trying to boot a v5.9-rc2 based kernel.

The crash reads as:

<1>[7.410192] BUG: kernel NULL pointer dereference, address: 
0038
<1>[7.410196] #PF: supervisor write access in kernel mode
<1>[7.410199] #PF: error_code(0x0002) - not-present page
<6>[7.410202] PGD 0 P4D 0 
<4>[7.410207] Oops: 0002 [#1] SMP PTI
<4>[7.410212] CPU: 1 PID: 1 Comm: swapper/0 Not tainted 5.9.0-devel+ #1
<4>[7.410215] Hardware name: LENOVO 20HGS0TW00/20HGS0TW00, BIOS N1WET46S 
(1.25s ) 03/30/2018
<4>[7.410224] RIP: 0010:intel_iommu_init+0xed0/0x1136
<4>[7.410229] Code: fe e9 61 02 00 00 bb f4 ff ff ff e9 57 02 00 00 48 63 
d1 48 c1 e2 04 48 03 50 20 48 8b 12 48 85 d2 74 0b 48 8b 92 d0 02 00 00 <48> 89 
7a 38 ff c1 e9 15 f5 ff ff 48 c7 c7 00 a5 ac a1 49 c7 c7 20
<4>[7.410236] RSP: :b14e40073dd0 EFLAGS: 00010282
<4>[7.410240] RAX: 8d0643731720 RBX:  RCX: 

<4>[7.410244] RDX:  RSI:  RDI: 

<4>[7.410247] RBP: b14e40073e90 R08: 0001 R09: 
8d0643803700
<4>[7.410250] R10: 8d064262 R11: 0016 R12: 
000b
<4>[7.410254] R13: 8d064361e650 R14: a2455d80 R15: 

<4>[7.410258] FS:  () GS:8d064748() 
knlGS:
<4>[7.410262] CS:  0010 DS:  ES:  CR0: 80050033
<4>[7.410266] CR2: 0038 CR3: 00056760a001 CR4: 
003706e0
<4>[7.410269] Call Trace:
<4>[7.410280]  ? call_rcu+0x10e/0x320
<4>[7.410286]  ? trace_hardirqs_on+0x2c/0xd0
<4>[7.410291]  ? rdinit_setup+0x2c/0x2c
<4>[7.410297]  ? e820__memblock_setup+0x8b/0x8b
<4>[7.410302]  pci_iommu_init+0x16/0x3f
<4>[7.410307]  do_one_initcall+0x46/0x1e4
<4>[7.410313]  kernel_init_freeable+0x169/0x1b2
<4>[7.410320]  ? rest_init+0x9f/0x9f
<4>[7.410325]  kernel_init+0xa/0x101
<4>[7.410329]  ret_from_fork+0x22/0x30
<4>[7.410333] Modules linked in:
<4>[7.410338] CR2: 0038
<4>[7.410344] ---[ end trace 16bcdb1e11668fcd ]---

Full kernel message is attached in kernel.log.

I tracked the problem down to the dev_iommu_priv_set call in 
init_no_remapping_devices. It seems that for one device the dev->iommu member 
is NULL.

An dev_err outputs the device as "pci :00:02.0: DMAR" which is the intel HD 
620 graphic adapter in a Lenovo T470s device.

The following patch (also attached as intel-iommu.patch) avoids this crash by 
checking the pointer.

diff --git a/drivers/iommu/intel/iommu.c b/drivers/iommu/intel/iommu.c
index f8177c59d229..2d285a42db3f 100644
--- a/drivers/iommu/intel/iommu.c
+++ b/drivers/iommu/intel/iommu.c
@@ -4053,7 +4053,8 @@ static void __init init_no_remapping_devices(void)
drhd->ignored = 1;
for_each_active_dev_scope(drhd->devices,
  drhd->devices_cnt, i, dev)
-   dev_iommu_priv_set(dev, 
DUMMY_DEVICE_DOMAIN_INFO);
+   if (dev->iommu)
+   dev_iommu_priv_set(dev, 
DUMMY_DEVICE_DOMAIN_INFO);
}
}
 }

I assume the problem might be related to the following commit introduced in 
v5.9-rc1:

commit 01b9d4e21148c89fdbab3d6b3705f9791314b631
Author: Joerg Roedel 
Date:   Thu Jun 25 15:08:25 2020 +0200

iommu/vt-d: Use dev_iommu_priv_get/set()

Remove the use of dev->archdata.iommu and use the private per-device
pointer provided by IOMMU core code instead.

With regards,

Torsten Hilbrich

-- 
Dipl.-Inform.
Torsten Hilbrich
Teamleiter Bereich Entwicklung
Abteilung Network & Client Security
Divison Public Authorities
secunet Security Networks AG 
Konrad-Zuse-Platz 2-4
81829 München

Tel: +49-201-5454-3522
Fax: +49-201-5454-1327
torsten.hilbr...@secunet.com
www.secunet.com

__

secunet Security Networks AG
Sitz: Kurfürstenstraße 58, 45138 Essen, Deutschland 
Amtsgericht Essen HRB 13615
Vorstand: Axel Deininger (Vors.), Torsten Henn, Dr. Kai Martius, Thomas
  Pleines
Aufsichtsratsvorsitzender: Ralf Wintergerst
__

Oops#1 Part1
<6>[0.00] microcode: microcode updated early to revision 0xd6, date = 2020-04-27
<5>[0.00] Linux version 5.9.0-devel+ (thilbrich@ts-6) (gcc (Debian 8.3.0-6) 8.3.0, GNU ld (GNU Binutils for Debian) 2.31.1) #2 SMP Mon Aug 31 09:20:36 CEST 2020
<6>[0.00] Command line: BOOT_IMAGE=/isolinux/bzImage console=tty1 intel_iommu=on,igfx_off loglevel=7 initcall_debug
<6>[0.00] x86/fpu: Supporting XSAVE feature 0x001: 'x87 floating point registers'
<6>[0.00] x86/fpu: Supporting XSAVE feature 0x002: 'SSE registers'
<6>[0.00] x86/fpu: Supporting XSAVE feature 0

[PATCH v5] iommu/mediatek: check 4GB mode by reading infracfg

2020-08-31 Thread Miles Chen
In previous discussion [1] and [2], we found that it is risky to
use max_pfn or totalram_pages to tell if 4GB mode is enabled.

Check 4GB mode by reading infracfg register, remove the usage
of the un-exported symbol max_pfn.

This is a step towards building mtk_iommu as a kernel module.

[1] https://lore.kernel.org/lkml/20200603161132.2441-1-miles.c...@mediatek.com/
[2] https://lore.kernel.org/lkml/20200604080120.2628-1-miles.c...@mediatek.com/
[3] https://lore.kernel.org/lkml/20200715205120.GA778876@bogus/

Cc: Mike Rapoport 
Cc: David Hildenbrand 
Cc: Yong Wu 
Cc: Yingjoe Chen 
Cc: Christoph Hellwig 
Cc: Rob Herring 
Cc: Matthias Brugger 
Signed-off-by: Miles Chen 

---

Change since v4
- remove unnecessary data->enable_4GB = false, since it is kzalloc()ed.

Change since v3
- use lore.kernel.org links
- move "change since..." after "---"

Change since v2:
- determine compatible string by m4u_plat
- rebase to next-20200720
- add "---"

Change since v1:
- remove the phandle usage, search for infracfg instead [3]
- use infracfg instead of infracfg_regmap
- move infracfg definitaions to linux/soc/mediatek/infracfg.h
- update enable_4GB only when has_4gb_mode
---
 drivers/iommu/mtk_iommu.c | 33 +++
 include/linux/soc/mediatek/infracfg.h |  3 +++
 2 files changed, 31 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index 785b228d39a6..e7b8b2bb08a9 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -3,7 +3,6 @@
  * Copyright (c) 2015-2016 MediaTek Inc.
  * Author: Yong Wu 
  */
-#include 
 #include 
 #include 
 #include 
@@ -15,13 +14,16 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
+#include 
 #include 
 #include 
 
@@ -640,8 +642,11 @@ static int mtk_iommu_probe(struct platform_device *pdev)
struct resource *res;
resource_size_t ioaddr;
struct component_match  *match = NULL;
+   struct regmap   *infracfg;
void*protect;
int i, larb_nr, ret;
+   u32 val;
+   char*p;
 
data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL);
if (!data)
@@ -655,10 +660,28 @@ static int mtk_iommu_probe(struct platform_device *pdev)
return -ENOMEM;
data->protect_base = ALIGN(virt_to_phys(protect), MTK_PROTECT_PA_ALIGN);
 
-   /* Whether the current dram is over 4GB */
-   data->enable_4GB = !!(max_pfn > (BIT_ULL(32) >> PAGE_SHIFT));
-   if (!MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE))
-   data->enable_4GB = false;
+   if (MTK_IOMMU_HAS_FLAG(data->plat_data, HAS_4GB_MODE)) {
+   switch (data->plat_data->m4u_plat) {
+   case M4U_MT2712:
+   p = "mediatek,mt2712-infracfg";
+   break;
+   case M4U_MT8173:
+   p = "mediatek,mt8173-infracfg";
+   break;
+   default:
+   p = NULL;
+   }
+
+   infracfg = syscon_regmap_lookup_by_compatible(p);
+
+   if (IS_ERR(infracfg))
+   return PTR_ERR(infracfg);
+
+   ret = regmap_read(infracfg, REG_INFRA_MISC, &val);
+   if (ret)
+   return ret;
+   data->enable_4GB = !!(val & F_DDR_4GB_SUPPORT_EN);
+   }
 
res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
data->base = devm_ioremap_resource(dev, res);
diff --git a/include/linux/soc/mediatek/infracfg.h 
b/include/linux/soc/mediatek/infracfg.h
index fd25f0148566..233463d789c6 100644
--- a/include/linux/soc/mediatek/infracfg.h
+++ b/include/linux/soc/mediatek/infracfg.h
@@ -32,6 +32,9 @@
 #define MT7622_TOP_AXI_PROT_EN_WB  (BIT(2) | BIT(6) | \
 BIT(7) | BIT(8))
 
+#define REG_INFRA_MISC 0xf00
+#define F_DDR_4GB_SUPPORT_EN   BIT(13)
+
 int mtk_infracfg_set_bus_protection(struct regmap *infracfg, u32 mask,
bool reg_update);
 int mtk_infracfg_clear_bus_protection(struct regmap *infracfg, u32 mask,
-- 
2.18.0
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v6 0/2] make dma_alloc_coherent NUMA-aware by per-NUMA CMA

2020-08-31 Thread Christoph Hellwig
This is on my todo list to be applied this week.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: [PATCH v6 0/2] make dma_alloc_coherent NUMA-aware by per-NUMA CMA

2020-08-31 Thread Song Bao Hua (Barry Song)



> -Original Message-
> From: linux-kernel-ow...@vger.kernel.org
> [mailto:linux-kernel-ow...@vger.kernel.org] On Behalf Of Christoph Hellwig
> Sent: Friday, August 21, 2020 6:19 PM
> To: Song Bao Hua (Barry Song) 
> Cc: h...@lst.de; m.szyprow...@samsung.com; robin.mur...@arm.com;
> w...@kernel.org; ganapatrao.kulka...@cavium.com;
> catalin.mari...@arm.com; iommu@lists.linux-foundation.org; Linuxarm
> ; linux-arm-ker...@lists.infradead.org;
> linux-ker...@vger.kernel.org; huangdaode 
> Subject: Re: [PATCH v6 0/2] make dma_alloc_coherent NUMA-aware by
> per-NUMA CMA
> 
> FYI, as of the last one I'm fine now, bit I really need an ACK from
> the arm64 maintainers.

Hi Christoph,

For the changes in arch/arm64, Will gave his ack here:
https://lore.kernel.org/linux-iommu/20200821090116.GB20255@willie-the-truck/

and the patchset has been refined to v8
https://lore.kernel.org/linux-iommu/20200823230309.28980-1-song.bao@hisilicon.com/
with one additional patch to remove magic number:
[PATCH v8 3/3] mm: cma: use CMA_MAX_NAME to define the length of cma name array
https://lore.kernel.org/linux-iommu/20200823230309.28980-4-song.bao@hisilicon.com/

Hopefully, you didn't miss it:-)
Does the new one need an Ack from Linux-mm maintainer?

Thanks
Barry

___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [patch V2 00/46] x86, PCI, XEN, genirq ...: Prepare for device MSI

2020-08-31 Thread Lu Baolu

Hi Thomas,

On 2020/8/31 15:10, Thomas Gleixner wrote:

On Mon, Aug 31 2020 at 08:51, Lu Baolu wrote:

On 8/26/20 7:16 PM, Thomas Gleixner wrote:

This is the second version of providing a base to support device MSI (non
PCI based) and on top of that support for IMS (Interrupt Message Storm)
based devices in a halfways architecture independent way.


After applying this patch series, the dmar_alloc_hwirq() helper doesn't
work anymore during boot. This causes the IOMMU driver to fail to
register the DMA fault handler and abort the IOMMU probe processing.
Is this a known issue?


See replies to patch 15/46 or pull the git tree. It has the issue fixed.


Ah! Yes. Sorry for the noise.

Beset regards,
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH 5/5] powerpc: use the generic dma_ops_bypass mode

2020-08-31 Thread Cédric Le Goater
On 8/31/20 8:40 AM, Christoph Hellwig wrote:
> On Sun, Aug 30, 2020 at 11:04:21AM +0200, Cédric Le Goater wrote:
>> Hello,
>>
>> On 7/8/20 5:24 PM, Christoph Hellwig wrote:
>>> Use the DMA API bypass mechanism for direct window mappings.  This uses
>>> common code and speed up the direct mapping case by avoiding indirect
>>> calls just when not using dma ops at all.  It also fixes a problem where
>>> the sync_* methods were using the bypass check for DMA allocations, but
>>> those are part of the streaming ops.
>>>
>>> Note that this patch loses the DMA_ATTR_WEAK_ORDERING override, which
>>> has never been well defined, as is only used by a few drivers, which
>>> IIRC never showed up in the typical Cell blade setups that are affected
>>> by the ordering workaround.
>>>
>>> Fixes: efd176a04bef ("powerpc/pseries/dma: Allow SWIOTLB")
>>> Signed-off-by: Christoph Hellwig 
>>> ---
>>>  arch/powerpc/Kconfig  |  1 +
>>>  arch/powerpc/include/asm/device.h |  5 --
>>>  arch/powerpc/kernel/dma-iommu.c   | 90 ---
>>>  3 files changed, 10 insertions(+), 86 deletions(-)
>>
>> I am seeing corruptions on a couple of POWER9 systems (boston) when
>> stressed with IO. stress-ng gives some results but I have first seen
>> it when compiling the kernel in a guest and this is still the best way
>> to raise the issue.
>>
>> These systems have of a SAS Adaptec controller :
>>
>>   0003:01:00.0 Serial Attached SCSI controller: Adaptec Series 8 12G 
>> SAS/PCIe 3 (rev 01)
>>
>> When the failure occurs, the POWERPC EEH interrupt fires and dumps
>> lowlevel PHB4 registers among which :
>>
>>   [ 2179.251069490,3] PHB#0003[0:3]:   phbErrorStatus = 
>> 0280
>>   [ 2179.251117476,3] PHB#0003[0:3]:  phbFirstErrorStatus = 
>> 0200
>>
>> The bits raised identify a PPC 'TCE' error, which means it is related
>> to DMAs. See below for more details.
>>
>>
>> Reverting this patch "fixes" the issue but it is probably else where,
>> in some other layers or in the aacraid driver. How should I proceed 
>> to get more information ?
> 
> The aacraid DMA masks look like a mess.  Can you try the hack
> below and see it it helps?

No effect. The system crashes the same. But Alexey spotted some issue 
with swiotlb.

C. 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [patch V2 00/46] x86, PCI, XEN, genirq ...: Prepare for device MSI

2020-08-31 Thread Thomas Gleixner
On Mon, Aug 31 2020 at 08:51, Lu Baolu wrote:
> On 8/26/20 7:16 PM, Thomas Gleixner wrote:
>> This is the second version of providing a base to support device MSI (non
>> PCI based) and on top of that support for IMS (Interrupt Message Storm)
>> based devices in a halfways architecture independent way.
>
> After applying this patch series, the dmar_alloc_hwirq() helper doesn't
> work anymore during boot. This causes the IOMMU driver to fail to
> register the DMA fault handler and abort the IOMMU probe processing.
> Is this a known issue?

See replies to patch 15/46 or pull the git tree. It has the issue fixed.

Thanks,

tglx
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v1] iommu/vt-d: Move intel_iommu_ops to header file

2020-08-31 Thread Lu Baolu

Hi Andy,

On 2020/8/31 14:30, Andy Shevchenko wrote:

On Sat, Aug 29, 2020 at 07:58:46AM +0100, Christoph Hellwig wrote:

On Fri, Aug 28, 2020 at 07:05:02PM +0300, Andy Shevchenko wrote:

Compiler is not happy about hidden declaration of intel_iommu_ops.

.../drivers/iommu/intel/iommu.c:414:24: warning: symbol 'intel_iommu_ops' was 
not declared. Should it be static?

Move declaration to header file to make compiler happy.


What about a factoring out a helper that does iommu_device_sysfs_add +
iommu_device_set_ops + iommu_device_register and then mark
intel_iommu_ops static?


I am okay with this proposal, but I think the better if IOMMU folks can answer
to this before I'm going to invest time into it.


Thanks for your patch! I am okay with Christoph's proposal as well.

Best regards,
baolu
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu