RE: RE: Re: CMA in AMD IOMMU driver

2019-06-26 Thread Sathyavathi M
I tried to apply the patch (AMD IOMMU driver to use dma-iommu) to linux kerenl 
5.1.15 but it gives me some errors. 
Downloaded the patch from https://patchwork.ozlabs.org/patch/1096015/

Is this the right way im doing?

Please let me know.

Thanks,
Sathya 
 
- Original Message -
Sender : Sathyavathi M  Engineer/Host Software 
/SSIR/Samsung Electronics
Date   : 2019-06-26 15:21 (GMT+5:30)
Title  : RE: Re: CMA in AMD IOMMU driver
To : null
CC : null
 
Dear Christoph,
 
Thanks for the reply.
can you please let me know which kernel has it?
 
 
Thanks,
Sathya 
 
- Original Message -
Sender : Christoph Hellwig 
Date   : 2019-06-26 12:28 (GMT+5:30)
Title  : Re: CMA in AMD IOMMU driver
To : Sathyavathi M
CC : null
 
Toms conversion of the AMD IOMMU driver to use dma-iommu adds CMA
support :)
 
 
Regards,
Sathya
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu
 
Regards,
Sathya
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v4 20/22] iommu/vt-d: Add bind guest PASID support

2019-06-26 Thread Lu Baolu

Hi Jacob and Yi,

On 6/9/19 9:44 PM, Jacob Pan wrote:

When supporting guest SVA with emulated IOMMU, the guest PASID
table is shadowed in VMM. Updates to guest vIOMMU PASID table
will result in PASID cache flush which will be passed down to
the host as bind guest PASID calls.

For the SL page tables, it will be harvested from device's
default domain (request w/o PASID), or aux domain in case of
mediated device.

 .-.  .---.
 |   vIOMMU|  | Guest process CR3, FL only|
 | |  '---'
 ./
 | PASID Entry |--- PASID cache flush -
 '-'   |
 | |   V
 | |CR3 in GPA
 '-'
Guest
--| Shadow |--|
   vv  v
Host
 .-.  .--.
 |   pIOMMU|  | Bind FL for GVA-GPA  |
 | |  '--'
 ./  |
 | PASID Entry | V (Nested xlate)
 '\.--.
 | |   |SL for GPA-HPA, default domain|
 | |   '--'
 '-'
Where:
  - FL = First level/stage one page tables
  - SL = Second level/stage two page tables

Signed-off-by: Jacob Pan 
Signed-off-by: Liu, Yi L 
---
  drivers/iommu/intel-iommu.c |   4 +
  drivers/iommu/intel-svm.c   | 187 
  include/linux/intel-iommu.h |  13 ++-
  include/linux/intel-svm.h   |  17 
  4 files changed, 219 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 7cfa0eb..3b4d712 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5782,6 +5782,10 @@ const struct iommu_ops intel_iommu_ops = {
.dev_enable_feat= intel_iommu_dev_enable_feat,
.dev_disable_feat   = intel_iommu_dev_disable_feat,
.pgsize_bitmap  = INTEL_IOMMU_PGSIZES,
+#ifdef CONFIG_INTEL_IOMMU_SVM
+   .sva_bind_gpasid= intel_svm_bind_gpasid,
+   .sva_unbind_gpasid  = intel_svm_unbind_gpasid,
+#endif
  };
  
  static void quirk_iommu_g4x_gfx(struct pci_dev *dev)

diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 66d98e1..f06a82f 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -229,6 +229,193 @@ static LIST_HEAD(global_svm_list);
list_for_each_entry(sdev, >devs, list)  \
if (dev == sdev->dev)\
  
+int intel_svm_bind_gpasid(struct iommu_domain *domain,

+   struct device *dev,
+   struct gpasid_bind_data *data)
+{
+   struct intel_iommu *iommu = intel_svm_device_to_iommu(dev);
+   struct intel_svm_dev *sdev;
+   struct intel_svm *svm = NULL;
+   struct dmar_domain *ddomain;
+   int ret = 0;
+
+   if (WARN_ON(!iommu) || !data)
+   return -EINVAL;
+
+   if (data->version != IOMMU_GPASID_BIND_VERSION_1 ||
+   data->format != IOMMU_PASID_FORMAT_INTEL_VTD)
+   return -EINVAL;
+
+   if (dev_is_pci(dev)) {
+   /* VT-d supports devices with full 20 bit PASIDs only */
+   if (pci_max_pasids(to_pci_dev(dev)) != PASID_MAX)
+   return -EINVAL;
+   }
+
+   /*
+* We only check host PASID range, we have no knowledge to check
+* guest PASID range nor do we use the guest PASID.
+*/
+   if (data->hpasid <= 0 || data->hpasid >= PASID_MAX)
+   return -EINVAL;
+
+   ddomain = to_dmar_domain(domain);
+   /* REVISIT:
+* Sanity check adddress width and paging mode support
+* width matching in two dimensions:
+* 1. paging mode CPU <= IOMMU
+* 2. address width Guest <= Host.
+*/
+   mutex_lock(_mutex);
+   svm = ioasid_find(NULL, data->hpasid, NULL);
+   if (IS_ERR(svm)) {
+   ret = PTR_ERR(svm);
+   goto out;
+   }
+   if (svm) {
+   /*
+* If we found svm for the PASID, there must be at
+* least one device bond, otherwise svm should be freed.
+*/
+   BUG_ON(list_empty(>devs));
+
+   for_each_svm_dev() {
+   /* In case of multiple sub-devices of the same pdev 
assigned, we should
+* allow multiple bind calls with the same PASID and 
pdev.
+*/
+   sdev->users++;
+   goto out;
+   }
+   } else {
+   /* We come here when PASID has never been bond to a device. */
+   svm = kzalloc(sizeof(*svm), GFP_KERNEL);
+   if (!svm) {
+   ret = -ENOMEM;
+   

Re: [PATCH v4 15/22] iommu/vt-d: Replace Intel specific PASID allocator with IOASID

2019-06-26 Thread Lu Baolu

Hi Jacob,

On 6/9/19 9:44 PM, Jacob Pan wrote:

Make use of generic IOASID code to manage PASID allocation,
free, and lookup. Replace Intel specific code.

Signed-off-by: Jacob Pan 
---
  drivers/iommu/intel-iommu.c | 11 +--
  drivers/iommu/intel-pasid.c | 36 
  drivers/iommu/intel-svm.c   | 37 +
  3 files changed, 26 insertions(+), 58 deletions(-)

diff --git a/drivers/iommu/intel-iommu.c b/drivers/iommu/intel-iommu.c
index 5b84994..39b63fe 100644
--- a/drivers/iommu/intel-iommu.c
+++ b/drivers/iommu/intel-iommu.c
@@ -5167,7 +5167,7 @@ static void auxiliary_unlink_device(struct dmar_domain 
*domain,
domain->auxd_refcnt--;
  
  	if (!domain->auxd_refcnt && domain->default_pasid > 0)

-   intel_pasid_free_id(domain->default_pasid);
+   ioasid_free(domain->default_pasid);
  }
  
  static int aux_domain_add_dev(struct dmar_domain *domain,

@@ -5185,10 +5185,9 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
if (domain->default_pasid <= 0) {
int pasid;
  
-		pasid = intel_pasid_alloc_id(domain, PASID_MIN,

-pci_max_pasids(to_pci_dev(dev)),
-GFP_KERNEL);
-   if (pasid <= 0) {
+   pasid = ioasid_alloc(NULL, PASID_MIN, 
pci_max_pasids(to_pci_dev(dev)) - 1,
+   domain);
+   if (pasid == INVALID_IOASID) {
pr_err("Can't allocate default pasid\n");
return -ENODEV;
}
@@ -5224,7 +5223,7 @@ static int aux_domain_add_dev(struct dmar_domain *domain,
spin_unlock(>lock);
spin_unlock_irqrestore(_domain_lock, flags);
if (!domain->auxd_refcnt && domain->default_pasid > 0)
-   intel_pasid_free_id(domain->default_pasid);
+   ioasid_free(domain->default_pasid);
  
  	return ret;

  }
diff --git a/drivers/iommu/intel-pasid.c b/drivers/iommu/intel-pasid.c
index 69fddd3..1e25539 100644
--- a/drivers/iommu/intel-pasid.c
+++ b/drivers/iommu/intel-pasid.c
@@ -26,42 +26,6 @@
   */
  static DEFINE_SPINLOCK(pasid_lock);
  u32 intel_pasid_max_id = PASID_MAX;
-static DEFINE_IDR(pasid_idr);
-
-int intel_pasid_alloc_id(void *ptr, int start, int end, gfp_t gfp)
-{
-   int ret, min, max;
-
-   min = max_t(int, start, PASID_MIN);
-   max = min_t(int, end, intel_pasid_max_id);
-
-   WARN_ON(in_interrupt());
-   idr_preload(gfp);
-   spin_lock(_lock);
-   ret = idr_alloc(_idr, ptr, min, max, GFP_ATOMIC);
-   spin_unlock(_lock);
-   idr_preload_end();
-
-   return ret;
-}
-
-void intel_pasid_free_id(int pasid)
-{
-   spin_lock(_lock);
-   idr_remove(_idr, pasid);
-   spin_unlock(_lock);
-}
-
-void *intel_pasid_lookup_id(int pasid)
-{
-   void *p;
-
-   spin_lock(_lock);
-   p = idr_find(_idr, pasid);
-   spin_unlock(_lock);
-
-   return p;
-}
  
  int vcmd_alloc_pasid(struct intel_iommu *iommu, unsigned int *pasid)

  {
diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index 8f87304..9cbcc1f 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -25,6 +25,7 @@
  #include 
  #include 
  #include 
+#include 
  #include 
  
  #include "intel-pasid.h"

@@ -332,16 +333,15 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int 
flags, struct svm_dev_
if (pasid_max > intel_pasid_max_id)
pasid_max = intel_pasid_max_id;
  
-		/* Do not use PASID 0 in caching mode (virtualised IOMMU) */

-   ret = intel_pasid_alloc_id(svm,
-  !!cap_caching_mode(iommu->cap),
-  pasid_max - 1, GFP_KERNEL);
-   if (ret < 0) {
+   /* Do not use PASID 0, reserved for RID to PASID */
+   svm->pasid = ioasid_alloc(NULL, PASID_MIN,
+   pasid_max - 1, svm);
+   if (svm->pasid == INVALID_IOASID) {
kfree(svm);
kfree(sdev);
+   ret = ENOSPC;
goto out;
}
-   svm->pasid = ret;
svm->notifier.ops = _mmuops;
svm->mm = mm;
svm->flags = flags;
@@ -351,7 +351,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int 
flags, struct svm_dev_
if (mm) {
ret = mmu_notifier_register(>notifier, mm);
if (ret) {
-   intel_pasid_free_id(svm->pasid);
+   ioasid_free(svm->pasid);
kfree(svm);
kfree(sdev);
goto out;
@@ -367,7 +367,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int 

Re: [PATCH AUTOSEL 5.1 09/51] iommu/vt-d: Fix lock inversion between iommu->lock and device_domain_lock

2019-06-26 Thread Sasha Levin

On Wed, Jun 26, 2019 at 08:56:06AM +0200, Joerg Roedel wrote:

Hi Sasha,

On Tue, Jun 25, 2019 at 11:40:25PM -0400, Sasha Levin wrote:

From: Dave Jiang 

[ Upstream commit 7560cc3ca7d9d11555f80c830544e463fcdb28b8 ]


This commit was reverted upstream, please drop it from your stable
queue. It caused new lockdep issues.


I've dropped it, thank you.

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


Re: [PATCH 4/8] iommu/arm-smmu-v3: Add support for Substream IDs

2019-06-26 Thread Will Deacon
On Mon, Jun 10, 2019 at 07:47:10PM +0100, Jean-Philippe Brucker wrote:
> At the moment, the SMMUv3 driver implements only one stage-1 or stage-2
> page directory per device. However SMMUv3 allows more than one address
> space for some devices, by providing multiple stage-1 page directories. In
> addition to the Stream ID (SID), that identifies a device, we can now have
> Substream IDs (SSID) identifying an address space. In PCIe, SID is called
> Requester ID (RID) and SSID is called Process Address-Space ID (PASID).
> 
> Prepare the driver for SSID support, by adding context descriptor tables
> in STEs (previously a single static context descriptor). A complete
> stage-1 walk is now performed like this by the SMMU:
> 
>   Stream tables  Ctx. tables  Page tables
> ++   ,--->+---+   ,--->+---+
> ::   |:   :   |:   :
> ++   |+---+   |+---+
>SID->|  STE   |---'  SSID->|  CD   |---'  IOVA->|  PTE  |--> IPA
> +++---++---+
> :::   ::   :
> +++---++---+
> 
> Implement a single level of context descriptor table for now, but as with
> stream and page tables, an SSID can be split to index multiple levels of
> tables.
> 
> In all stream table entries, we set S1DSS=SSID0 mode, making translations
> without an SSID use context descriptor 0. Although it would be possible by
> setting S1DSS=BYPASS, we don't currently support SSID when user selects
> iommu.passthrough.

I don't understand your comment here: iommu.passthrough works just as it did
before, right, since we set bypass in the STE config field so S1DSS is not
relevant? I also notice that SSID0 causes transactions with SSID==0 to
abort. Is a PASID of 0 reserved, so this doesn't matter?

> @@ -1062,33 +1143,90 @@ static u64 arm_smmu_cpu_tcr_to_cd(u64 tcr)
>   return val;
>  }
>  
> -static void arm_smmu_write_ctx_desc(struct arm_smmu_device *smmu,
> - struct arm_smmu_s1_cfg *cfg)
> +static int arm_smmu_write_ctx_desc(struct arm_smmu_domain *smmu_domain,
> +int ssid, struct arm_smmu_ctx_desc *cd)
>  {
>   u64 val;
> + bool cd_live;
> + struct arm_smmu_device *smmu = smmu_domain->smmu;
> + __le64 *cdptr = arm_smmu_get_cd_ptr(_domain->s1_cfg, ssid);
>  
>   /*
> -  * We don't need to issue any invalidation here, as we'll invalidate
> -  * the STE when installing the new entry anyway.
> +  * This function handles the following cases:
> +  *
> +  * (1) Install primary CD, for normal DMA traffic (SSID = 0).
> +  * (2) Install a secondary CD, for SID+SSID traffic.
> +  * (3) Update ASID of a CD. Atomically write the first 64 bits of the
> +  * CD, then invalidate the old entry and mappings.
> +  * (4) Remove a secondary CD.
>*/
> - val = arm_smmu_cpu_tcr_to_cd(cfg->cd.tcr) |
> +
> + if (!cdptr)
> + return -ENOMEM;
> +
> + val = le64_to_cpu(cdptr[0]);
> + cd_live = !!(val & CTXDESC_CD_0_V);
> +
> + if (!cd) { /* (4) */
> + cdptr[0] = 0;

Should we be using WRITE_ONCE here? (although I notice we don't seem to
bother for STEs either...)

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


Re: [PATCH 6/8] iommu/arm-smmu-v3: Support auxiliary domains

2019-06-26 Thread Will Deacon
Hi Jean-Philippe,

On Mon, Jun 10, 2019 at 07:47:12PM +0100, Jean-Philippe Brucker wrote:
> In commit a3a195929d40 ("iommu: Add APIs for multiple domains per
> device"), the IOMMU API gained the concept of auxiliary domains (AUXD),
> which allows to control the PASID-tagged address spaces of a device. With
> AUXD the PASID address space are not shared with the CPU, but are instead
> modified with iommu_map() and iommu_unmap() calls on auxiliary domains.
> 
> Add auxiliary domain support to the SMMUv3 driver. Device drivers allocate
> an unmanaged IOMMU domain with iommu_domain_alloc(), and attach it to the
> device with iommu_aux_attach_domain().

[...]

> 
> The AUXD API is fairly permissive, and allows to attach an IOMMU domain in
> both normal and auxiliary mode at the same time - one device can be
> attached to the domain normally, and another device can be attached
> through one of its PASIDs. To avoid excessive complexity in the SMMU
> implementation we pose some restrictions on supported AUXD usage:
> 
> * A domain is either in auxiliary mode or normal mode. And that state is
>   sticky. Once detached the domain has to be re-attached in the same mode.
> 
> * An auxiliary domain can have a single parent domain. Two devices can be
>   attached to the same auxiliary domain only if they are attached to the
>   same parent domain.
> 
> In practice these shouldn't be problematic, since we have the same kind of
> restriction on normal domains and users have been able to cope so far: at
> the moment a domain cannot be attached to two devices behind different
> SMMUs. When VFIO puts two such devices in the same container, it simply
> falls back to allocating two separate IOMMU domains.
> 
> Signed-off-by: Jean-Philippe Brucker 
> ---
>  drivers/iommu/Kconfig   |   1 +
>  drivers/iommu/arm-smmu-v3.c | 276 +---
>  2 files changed, 260 insertions(+), 17 deletions(-)
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index 9b45f70549a7..d326fef3d3a6 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -393,6 +393,7 @@ config ARM_SMMU_DISABLE_BYPASS_BY_DEFAULT
>  config ARM_SMMU_V3
>   bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
>   depends on ARM64
> + select IOASID
>   select IOMMU_API
>   select IOMMU_IO_PGTABLE_LPAE
>   select GENERIC_MSI_IRQ_DOMAIN
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 326b71793336..633d829f246f 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -19,6 +19,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -641,6 +642,7 @@ struct arm_smmu_master {
>   unsigned intnum_sids;
>   unsigned intssid_bits;
>   boolats_enabled :1;
> + boolauxd_enabled:1;
>  };
>  
>  /* SMMU private data for an IOMMU domain */
> @@ -666,8 +668,14 @@ struct arm_smmu_domain {
>  
>   struct iommu_domain domain;
>  
> + /* Unused in aux domains */
>   struct list_headdevices;
>   spinlock_t  devices_lock;
> +
> + /* Auxiliary domain stuff */
> + struct arm_smmu_domain  *parent;
> + ioasid_tssid;
> + unsigned long   aux_nr_devs;

Maybe use a union to avoid comments about what is used/unused?

> +static void arm_smmu_aux_detach_dev(struct iommu_domain *domain, struct 
> device *dev)
> +{
> + struct iommu_domain *parent_domain;
> + struct arm_smmu_domain *parent_smmu_domain;
> + struct arm_smmu_master *master = dev_to_master(dev);
> + struct arm_smmu_domain *smmu_domain = to_smmu_domain(domain);
> +
> + if (!arm_smmu_dev_feature_enabled(dev, IOMMU_DEV_FEAT_AUX))
> + return;
> +
> + parent_domain = iommu_get_domain_for_dev(dev);
> + if (!parent_domain)
> + return;
> + parent_smmu_domain = to_smmu_domain(parent_domain);
> +
> + mutex_lock(_domain->init_mutex);
> + if (!smmu_domain->aux_nr_devs)
> + goto out_unlock;
> +
> + if (!--smmu_domain->aux_nr_devs) {
> + arm_smmu_write_ctx_desc(parent_smmu_domain, smmu_domain->ssid,
> + NULL);
> + /*
> +  * TLB doesn't need invalidation since accesses from the device
> +  * can't use this domain's ASID once the CD is clear.
> +  *
> +  * Sadly that doesn't apply to ATCs, which are PASID tagged.
> +  * Invalidate all other devices as well, because even though
> +  * they weren't 'officially' attached to the auxiliary domain,
> +  * they could have formed ATC entries.
> +  */
> + arm_smmu_atc_inv_domain(smmu_domain, 0, 0);

I've been struggling to understand 

[PATCH v7 6/6] vfio/type1: remove duplicate retrieval of reserved regions

2019-06-26 Thread Shameer Kolothum
As we now already have the reserved regions list, just pass that into
vfio_iommu_has_sw_msi() fn.

Signed-off-by: Shameer Kolothum 
---
 drivers/vfio/vfio_iommu_type1.c | 15 ++-
 1 file changed, 6 insertions(+), 9 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 450081802dcd..43b1e68ebce9 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1308,15 +1308,13 @@ static struct vfio_group *find_iommu_group(struct 
vfio_domain *domain,
return NULL;
 }
 
-static bool vfio_iommu_has_sw_msi(struct iommu_group *group, phys_addr_t *base)
+static bool vfio_iommu_has_sw_msi(struct list_head *group_resv_regions,
+ phys_addr_t *base)
 {
-   struct list_head group_resv_regions;
-   struct iommu_resv_region *region, *next;
+   struct iommu_resv_region *region;
bool ret = false;
 
-   INIT_LIST_HEAD(_resv_regions);
-   iommu_get_group_resv_regions(group, _resv_regions);
-   list_for_each_entry(region, _resv_regions, list) {
+   list_for_each_entry(region, group_resv_regions, list) {
/*
 * The presence of any 'real' MSI regions should take
 * precedence over the software-managed one if the
@@ -1332,8 +1330,7 @@ static bool vfio_iommu_has_sw_msi(struct iommu_group 
*group, phys_addr_t *base)
ret = true;
}
}
-   list_for_each_entry_safe(region, next, _resv_regions, list)
-   kfree(region);
+
return ret;
 }
 
@@ -1774,7 +1771,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
if (ret)
goto out_detach;
 
-   resv_msi = vfio_iommu_has_sw_msi(iommu_group, _msi_base);
+   resv_msi = vfio_iommu_has_sw_msi(_resv_regions, _msi_base);
 
INIT_LIST_HEAD(>group_list);
list_add(>next, >group_list);
-- 
2.17.1




[PATCH v7 5/6] vfio/type1: Add IOVA range capability support

2019-06-26 Thread Shameer Kolothum
This allows the user-space to retrieve the supported IOVA
range(s), excluding any reserved regions. The implementation
is based on capability chains, added to VFIO_IOMMU_GET_INFO ioctl.

Signed-off-by: Shameer Kolothum 
---
v6 --> v7

Addressed mdev case with empty iovas list(Suggested by Alex)
---
 drivers/vfio/vfio_iommu_type1.c | 101 
 include/uapi/linux/vfio.h   |  23 
 2 files changed, 124 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 89ad0da7152c..450081802dcd 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -2141,6 +2141,73 @@ static int vfio_domains_have_iommu_cache(struct 
vfio_iommu *iommu)
return ret;
 }
 
+static int vfio_iommu_iova_add_cap(struct vfio_info_cap *caps,
+struct vfio_iommu_type1_info_cap_iova_range *cap_iovas,
+size_t size)
+{
+   struct vfio_info_cap_header *header;
+   struct vfio_iommu_type1_info_cap_iova_range *iova_cap;
+
+   header = vfio_info_cap_add(caps, size,
+  VFIO_IOMMU_TYPE1_INFO_CAP_IOVA_RANGE, 1);
+   if (IS_ERR(header))
+   return PTR_ERR(header);
+
+   iova_cap = container_of(header,
+   struct vfio_iommu_type1_info_cap_iova_range,
+   header);
+   iova_cap->nr_iovas = cap_iovas->nr_iovas;
+   memcpy(iova_cap->iova_ranges, cap_iovas->iova_ranges,
+  cap_iovas->nr_iovas * sizeof(*cap_iovas->iova_ranges));
+   return 0;
+}
+
+static int vfio_iommu_iova_build_caps(struct vfio_iommu *iommu,
+ struct vfio_info_cap *caps)
+{
+   struct vfio_iommu_type1_info_cap_iova_range *cap_iovas;
+   struct vfio_iova *iova;
+   size_t size;
+   int iovas = 0, i = 0, ret;
+
+   mutex_lock(>lock);
+
+   list_for_each_entry(iova, >iova_list, list)
+   iovas++;
+
+   if (!iovas) {
+   /*
+* Return 0 as a container with only an mdev device
+* will have an empty list
+*/
+   ret = 0;
+   goto out_unlock;
+   }
+
+   size = sizeof(*cap_iovas) + (iovas * sizeof(*cap_iovas->iova_ranges));
+
+   cap_iovas = kzalloc(size, GFP_KERNEL);
+   if (!cap_iovas) {
+   ret = -ENOMEM;
+   goto out_unlock;
+   }
+
+   cap_iovas->nr_iovas = iovas;
+
+   list_for_each_entry(iova, >iova_list, list) {
+   cap_iovas->iova_ranges[i].start = iova->start;
+   cap_iovas->iova_ranges[i].end = iova->end;
+   i++;
+   }
+
+   ret = vfio_iommu_iova_add_cap(caps, cap_iovas, size);
+
+   kfree(cap_iovas);
+out_unlock:
+   mutex_unlock(>lock);
+   return ret;
+}
+
 static long vfio_iommu_type1_ioctl(void *iommu_data,
   unsigned int cmd, unsigned long arg)
 {
@@ -2162,19 +2229,53 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
}
} else if (cmd == VFIO_IOMMU_GET_INFO) {
struct vfio_iommu_type1_info info;
+   struct vfio_info_cap caps = { .buf = NULL, .size = 0 };
+   unsigned long capsz;
+   int ret;
 
minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
 
+   /* For backward compatibility, cannot require this */
+   capsz = offsetofend(struct vfio_iommu_type1_info, cap_offset);
+
if (copy_from_user(, (void __user *)arg, minsz))
return -EFAULT;
 
if (info.argsz < minsz)
return -EINVAL;
 
+   if (info.argsz >= capsz) {
+   minsz = capsz;
+   info.cap_offset = 0; /* output, no-recopy necessary */
+   }
+
info.flags = VFIO_IOMMU_INFO_PGSIZES;
 
info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
 
+   ret = vfio_iommu_iova_build_caps(iommu, );
+   if (ret)
+   return ret;
+
+   if (caps.size) {
+   info.flags |= VFIO_IOMMU_INFO_CAPS;
+
+   if (info.argsz < sizeof(info) + caps.size) {
+   info.argsz = sizeof(info) + caps.size;
+   } else {
+   vfio_info_cap_shift(, sizeof(info));
+   if (copy_to_user((void __user *)arg +
+   sizeof(info), caps.buf,
+   caps.size)) {
+   kfree(caps.buf);
+   return -EFAULT;
+   }
+   info.cap_offset = sizeof(info);
+   }
+
+   

[PATCH v7 4/6] vfio/type1: check dma map request is within a valid iova range

2019-06-26 Thread Shameer Kolothum
This checks and rejects any dma map request outside valid iova
range.

Signed-off-by: Shameer Kolothum 
---
v6 --> v7

Addressed the case where a container with only an mdev device will
have an empty list(Suggested by Alex).
---
 drivers/vfio/vfio_iommu_type1.c | 26 ++
 1 file changed, 26 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index e872fb3a0f39..89ad0da7152c 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1050,6 +1050,27 @@ static int vfio_pin_map_dma(struct vfio_iommu *iommu, 
struct vfio_dma *dma,
return ret;
 }
 
+/*
+ * Check dma map request is within a valid iova range
+ */
+static bool vfio_iommu_iova_dma_valid(struct vfio_iommu *iommu,
+ dma_addr_t start, dma_addr_t end)
+{
+   struct list_head *iova = >iova_list;
+   struct vfio_iova *node;
+
+   list_for_each_entry(node, iova, list) {
+   if (start >= node->start && end <= node->end)
+   return true;
+   }
+
+   /*
+* Check for list_empty() as well since a container with
+* only an mdev device will have an empty list.
+*/
+   return list_empty(>iova_list);
+}
+
 static int vfio_dma_do_map(struct vfio_iommu *iommu,
   struct vfio_iommu_type1_dma_map *map)
 {
@@ -1093,6 +1114,11 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
goto out_unlock;
}
 
+   if (!vfio_iommu_iova_dma_valid(iommu, iova, iova + size - 1)) {
+   ret = -EINVAL;
+   goto out_unlock;
+   }
+
dma = kzalloc(sizeof(*dma), GFP_KERNEL);
if (!dma) {
ret = -ENOMEM;
-- 
2.17.1




[PATCH v7 2/6] vfio/type1: Check reserve region conflict and update iova list

2019-06-26 Thread Shameer Kolothum
This retrieves the reserved regions associated with dev group and
checks for conflicts with any existing dma mappings. Also update
the iova list excluding the reserved regions.

Reserved regions with type IOMMU_RESV_DIRECT_RELAXABLE are
excluded from above checks as they are considered as directly
mapped regions which are known to be relaxable.

Signed-off-by: Shameer Kolothum 
---
 drivers/vfio/vfio_iommu_type1.c | 96 +
 1 file changed, 96 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index 970d1ec06aed..b6bfdfa16c33 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1508,6 +1508,88 @@ static int vfio_iommu_aper_resize(struct list_head *iova,
return 0;
 }
 
+/*
+ * Check reserved region conflicts with existing dma mappings
+ */
+static bool vfio_iommu_resv_conflict(struct vfio_iommu *iommu,
+struct list_head *resv_regions)
+{
+   struct iommu_resv_region *region;
+
+   /* Check for conflict with existing dma mappings */
+   list_for_each_entry(region, resv_regions, list) {
+   if (region->type == IOMMU_RESV_DIRECT_RELAXABLE)
+   continue;
+
+   if (vfio_find_dma(iommu, region->start, region->length))
+   return true;
+   }
+
+   return false;
+}
+
+/*
+ * Check iova region overlap with  reserved regions and
+ * exclude them from the iommu iova range
+ */
+static int vfio_iommu_resv_exclude(struct list_head *iova,
+  struct list_head *resv_regions)
+{
+   struct iommu_resv_region *resv;
+   struct vfio_iova *n, *next;
+
+   list_for_each_entry(resv, resv_regions, list) {
+   phys_addr_t start, end;
+
+   if (resv->type == IOMMU_RESV_DIRECT_RELAXABLE)
+   continue;
+
+   start = resv->start;
+   end = resv->start + resv->length - 1;
+
+   list_for_each_entry_safe(n, next, iova, list) {
+   int ret = 0;
+
+   /* No overlap */
+   if (start > n->end || end < n->start)
+   continue;
+   /*
+* Insert a new node if current node overlaps with the
+* reserve region to exlude that from valid iova range.
+* Note that, new node is inserted before the current
+* node and finally the current node is deleted keeping
+* the list updated and sorted.
+*/
+   if (start > n->start)
+   ret = vfio_iommu_iova_insert(>list, n->start,
+start - 1);
+   if (!ret && end < n->end)
+   ret = vfio_iommu_iova_insert(>list, end + 1,
+n->end);
+   if (ret)
+   return ret;
+
+   list_del(>list);
+   kfree(n);
+   }
+   }
+
+   if (list_empty(iova))
+   return -EINVAL;
+
+   return 0;
+}
+
+static void vfio_iommu_resv_free(struct list_head *resv_regions)
+{
+   struct iommu_resv_region *n, *next;
+
+   list_for_each_entry_safe(n, next, resv_regions, list) {
+   list_del(>list);
+   kfree(n);
+   }
+}
+
 static void vfio_iommu_iova_free(struct list_head *iova)
 {
struct vfio_iova *n, *next;
@@ -1559,6 +1641,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
phys_addr_t resv_msi_base;
struct iommu_domain_geometry geo;
LIST_HEAD(iova_copy);
+   LIST_HEAD(group_resv_regions);
 
mutex_lock(>lock);
 
@@ -1644,6 +1727,13 @@ static int vfio_iommu_type1_attach_group(void 
*iommu_data,
goto out_detach;
}
 
+   iommu_get_group_resv_regions(iommu_group, _resv_regions);
+
+   if (vfio_iommu_resv_conflict(iommu, _resv_regions)) {
+   ret = -EINVAL;
+   goto out_detach;
+   }
+
/* Get a copy of the current iova list and work on it */
ret = vfio_iommu_iova_get_copy(iommu, _copy);
if (ret)
@@ -1654,6 +1744,10 @@ static int vfio_iommu_type1_attach_group(void 
*iommu_data,
if (ret)
goto out_detach;
 
+   ret = vfio_iommu_resv_exclude(_copy, _resv_regions);
+   if (ret)
+   goto out_detach;
+
resv_msi = vfio_iommu_has_sw_msi(iommu_group, _msi_base);
 
INIT_LIST_HEAD(>group_list);
@@ -1714,6 +1808,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
/* Delete the old one and insert new iova list */
vfio_iommu_iova_insert_copy(iommu, _copy);

[PATCH v7 3/6] vfio/type1: Update iova list on detach

2019-06-26 Thread Shameer Kolothum
Get a copy of iova list on _group_detach and try to update the list.
On success replace the current one with the copy. Leave the list as
it is if update fails.

Signed-off-by: Shameer Kolothum 
---
 drivers/vfio/vfio_iommu_type1.c | 91 +
 1 file changed, 91 insertions(+)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index b6bfdfa16c33..e872fb3a0f39 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1873,12 +1873,88 @@ static void vfio_sanity_check_pfn_list(struct 
vfio_iommu *iommu)
WARN_ON(iommu->notifier.head);
 }
 
+/*
+ * Called when a domain is removed in detach. It is possible that
+ * the removed domain decided the iova aperture window. Modify the
+ * iova aperture with the smallest window among existing domains.
+ */
+static void vfio_iommu_aper_expand(struct vfio_iommu *iommu,
+  struct list_head *iova_copy)
+{
+   struct vfio_domain *domain;
+   struct iommu_domain_geometry geo;
+   struct vfio_iova *node;
+   dma_addr_t start = 0;
+   dma_addr_t end = (dma_addr_t)~0;
+
+   list_for_each_entry(domain, >domain_list, next) {
+   iommu_domain_get_attr(domain->domain, DOMAIN_ATTR_GEOMETRY,
+ );
+   if (geo.aperture_start > start)
+   start = geo.aperture_start;
+   if (geo.aperture_end < end)
+   end = geo.aperture_end;
+   }
+
+   /* Modify aperture limits. The new aper is either same or bigger */
+   node = list_first_entry(iova_copy, struct vfio_iova, list);
+   node->start = start;
+   node = list_last_entry(iova_copy, struct vfio_iova, list);
+   node->end = end;
+}
+
+/*
+ * Called when a group is detached. The reserved regions for that
+ * group can be part of valid iova now. But since reserved regions
+ * may be duplicated among groups, populate the iova valid regions
+ * list again.
+ */
+static int vfio_iommu_resv_refresh(struct vfio_iommu *iommu,
+  struct list_head *iova_copy)
+{
+   struct vfio_domain *d;
+   struct vfio_group *g;
+   struct vfio_iova *node;
+   dma_addr_t start, end;
+   LIST_HEAD(resv_regions);
+   int ret;
+
+   list_for_each_entry(d, >domain_list, next) {
+   list_for_each_entry(g, >group_list, next)
+   iommu_get_group_resv_regions(g->iommu_group,
+_regions);
+   }
+
+   if (list_empty(_regions))
+   return 0;
+
+   node = list_first_entry(iova_copy, struct vfio_iova, list);
+   start = node->start;
+   node = list_last_entry(iova_copy, struct vfio_iova, list);
+   end = node->end;
+
+   /* purge the iova list and create new one */
+   vfio_iommu_iova_free(iova_copy);
+
+   ret = vfio_iommu_aper_resize(iova_copy, start, end);
+   if (ret)
+   goto done;
+
+   /* Exclude current reserved regions from iova ranges */
+   ret = vfio_iommu_resv_exclude(iova_copy, _regions);
+done:
+   vfio_iommu_resv_free(_regions);
+   return ret;
+}
+
 static void vfio_iommu_type1_detach_group(void *iommu_data,
  struct iommu_group *iommu_group)
 {
struct vfio_iommu *iommu = iommu_data;
struct vfio_domain *domain;
struct vfio_group *group;
+   bool iova_copy_fail;
+   LIST_HEAD(iova_copy);
 
mutex_lock(>lock);
 
@@ -1901,6 +1977,12 @@ static void vfio_iommu_type1_detach_group(void 
*iommu_data,
}
}
 
+   /*
+* Get a copy of iova list. If success, use copy to update the
+* list and to replace the current one.
+*/
+   iova_copy_fail = !!vfio_iommu_iova_get_copy(iommu, _copy);
+
list_for_each_entry(domain, >domain_list, next) {
group = find_iommu_group(domain, iommu_group);
if (!group)
@@ -1926,10 +2008,19 @@ static void vfio_iommu_type1_detach_group(void 
*iommu_data,
iommu_domain_free(domain->domain);
list_del(>next);
kfree(domain);
+   if (!iova_copy_fail && !list_empty(>domain_list))
+   vfio_iommu_aper_expand(iommu, _copy);
}
break;
}
 
+   if (!iova_copy_fail && !list_empty(>domain_list)) {
+   if (!vfio_iommu_resv_refresh(iommu, _copy))
+   vfio_iommu_iova_insert_copy(iommu, _copy);
+   else
+   vfio_iommu_iova_free(_copy);
+   }
+
 detach_group_done:
mutex_unlock(>lock);
 }
-- 
2.17.1




[PATCH v7 1/6] vfio/type1: Introduce iova list and add iommu aperture validity check

2019-06-26 Thread Shameer Kolothum
This introduces an iova list that is valid for dma mappings. Make
sure the new iommu aperture window doesn't conflict with the current
one or with any existing dma mappings during attach.

Signed-off-by: Shameer Kolothum 
---
 drivers/vfio/vfio_iommu_type1.c | 181 +++-
 1 file changed, 177 insertions(+), 4 deletions(-)

diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
index add34adfadc7..970d1ec06aed 100644
--- a/drivers/vfio/vfio_iommu_type1.c
+++ b/drivers/vfio/vfio_iommu_type1.c
@@ -1,4 +1,3 @@
-// SPDX-License-Identifier: GPL-2.0-only
 /*
  * VFIO: IOMMU DMA mapping support for Type1 IOMMU
  *
@@ -62,6 +61,7 @@ MODULE_PARM_DESC(dma_entry_limit,
 
 struct vfio_iommu {
struct list_headdomain_list;
+   struct list_headiova_list;
struct vfio_domain  *external_domain; /* domain for external user */
struct mutexlock;
struct rb_root  dma_list;
@@ -97,6 +97,12 @@ struct vfio_group {
boolmdev_group; /* An mdev group */
 };
 
+struct vfio_iova {
+   struct list_headlist;
+   dma_addr_t  start;
+   dma_addr_t  end;
+};
+
 /*
  * Guest RAM pinning working set or DMA target
  */
@@ -1401,6 +1407,146 @@ static int vfio_mdev_iommu_device(struct device *dev, 
void *data)
return 0;
 }
 
+/*
+ * This is a helper function to insert an address range to iova list.
+ * The list starts with a single entry corresponding to the IOMMU
+ * domain geometry to which the device group is attached. The list
+ * aperture gets modified when a new domain is added to the container
+ * if the new aperture doesn't conflict with the current one or with
+ * any existing dma mappings. The list is also modified to exclude
+ * any reserved regions associated with the device group.
+ */
+static int vfio_iommu_iova_insert(struct list_head *head,
+ dma_addr_t start, dma_addr_t end)
+{
+   struct vfio_iova *region;
+
+   region = kmalloc(sizeof(*region), GFP_KERNEL);
+   if (!region)
+   return -ENOMEM;
+
+   INIT_LIST_HEAD(>list);
+   region->start = start;
+   region->end = end;
+
+   list_add_tail(>list, head);
+   return 0;
+}
+
+/*
+ * Check the new iommu aperture conflicts with existing aper or with any
+ * existing dma mappings.
+ */
+static bool vfio_iommu_aper_conflict(struct vfio_iommu *iommu,
+dma_addr_t start, dma_addr_t end)
+{
+   struct vfio_iova *first, *last;
+   struct list_head *iova = >iova_list;
+
+   if (list_empty(iova))
+   return false;
+
+   /* Disjoint sets, return conflict */
+   first = list_first_entry(iova, struct vfio_iova, list);
+   last = list_last_entry(iova, struct vfio_iova, list);
+   if (start > last->end || end < first->start)
+   return true;
+
+   /* Check for any existing dma mappings outside the new start */
+   if (start > first->start) {
+   if (vfio_find_dma(iommu, first->start, start - first->start))
+   return true;
+   }
+
+   /* Check for any existing dma mappings outside the new end */
+   if (end < last->end) {
+   if (vfio_find_dma(iommu, end + 1, last->end - end))
+   return true;
+   }
+
+   return false;
+}
+
+/*
+ * Resize iommu iova aperture window. This is called only if the new
+ * aperture has no conflict with existing aperture and dma mappings.
+ */
+static int vfio_iommu_aper_resize(struct list_head *iova,
+ dma_addr_t start, dma_addr_t end)
+{
+   struct vfio_iova *node, *next;
+
+   if (list_empty(iova))
+   return vfio_iommu_iova_insert(iova, start, end);
+
+   /* Adjust iova list start */
+   list_for_each_entry_safe(node, next, iova, list) {
+   if (start < node->start)
+   break;
+   if (start >= node->start && start < node->end) {
+   node->start = start;
+   break;
+   }
+   /* Delete nodes before new start */
+   list_del(>list);
+   kfree(node);
+   }
+
+   /* Adjust iova list end */
+   list_for_each_entry_safe(node, next, iova, list) {
+   if (end > node->end)
+   continue;
+   if (end > node->start && end <= node->end) {
+   node->end = end;
+   continue;
+   }
+   /* Delete nodes after new end */
+   list_del(>list);
+   kfree(node);
+   }
+
+   return 0;
+}
+
+static void vfio_iommu_iova_free(struct list_head *iova)
+{
+   struct vfio_iova *n, *next;
+
+   list_for_each_entry_safe(n, next, iova, list) {
+   list_del(>list);
+   

Re: [PATCH v3 3/4] iommu/arm-smmu: Add support to handle Qcom's wait-for-safe logic

2019-06-26 Thread Will Deacon
On Wed, Jun 26, 2019 at 12:03:02PM +0530, Vivek Gautam wrote:
> On Tue, Jun 25, 2019 at 7:09 PM Will Deacon  wrote:
> >
> > On Tue, Jun 25, 2019 at 12:34:56PM +0530, Vivek Gautam wrote:
> > > On Mon, Jun 24, 2019 at 10:33 PM Will Deacon  wrote:
> > > > Instead, I think this needs to be part of a separate file that is 
> > > > maintained
> > > > by you, which follows on from the work that Krishna is doing for nvidia
> > > > built on top of Robin's prototype patches:
> > > >
> > > > http://linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/smmu-impl
> > >
> > > Looking at this branch quickly, it seem there can be separate 
> > > implementation
> > > level configuration file that can be added.
> > > But will this also handle separate page table ops when required in future.
> >
> > Nothing's set in stone, but having the implementation-specific code
> > constrain the page-table format (especially wrt quirks) sounds reasonable to
> > me. I'm currently waiting for Krishna to respin the nvidia changes [1] on
> > top of this so that we can see how well the abstractions are holding up.
> 
> Sure. Would you want me to try Robin's branch and take out the qualcomm
> related stuff to its own implementation? Or, would you like me to respin this
> series so that you can take it in to enable SDM845 boards such as, MTP
> and dragonboard to have a sane build - debian, etc. so people benefit
> out of it.

I can't take this series without Acks on the firmware calling changes, and I
plan to send my 5.3 patches to Joerg at the end of the week so they get some
time in -next. In which case, I think it may be worth you having a play with
the branch above so we can get a better idea of any additional smmu_impl hooks
you may need.

> Qualcomm stuff is lying in qcom-smmu and arm-smmu and may take some
> time to stub out the implementation related details.

Not sure I follow you here. Are you talking about qcom_iommu.c?

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


SATA broken with LPAE

2019-06-26 Thread Roger Quadros via iommu
Hi Christoph / Hans,

SATA has been broken on TI platforms with LPAE, on systems with RAM addresses > 
32-bits,
(e.g. DRA7 rev.H+) since v4.18.

The commit at which it breaks is
21e07dba9fb1179148089d611fc9e6e70d1887c3 ("scsi: reduce use of block bounce 
buffers").

The effect is that the SATA controller starts to see DMA addresses
above 32-bit which it does not support.

Could you please shed some light on how it is supposed to work if
we don't call blk_queue_bounce_limit() for devices that can do only 32-bit DMA
on a system that has addressable RAM above 32-bit Physical?

The below patch fixes it. Is this the right thing to do?

diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 3aab2e3d57f3..b925dc54cfa5 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -62,6 +62,9 @@ static int ahci_probe(struct platform_device *pdev)
if (of_device_is_compatible(dev->of_node, "hisilicon,hisi-ahci"))
hpriv->flags |= AHCI_HFLAG_NO_FBS | AHCI_HFLAG_NO_NCQ;
 
+   if (of_device_is_compatible(dev->of_node, "snps,dwc-ahci"))
+   hpriv->flags |= AHCI_HFLAG_32BIT_ONLY;
+
port = acpi_device_get_match_data(dev);
if (!port)
port = _port_info;
diff --git a/drivers/scsi/scsi_lib.c b/drivers/scsi/scsi_lib.c
index 65d0a10c76ad..9083c7b89dfc 100644
--- a/drivers/scsi/scsi_lib.c
+++ b/drivers/scsi/scsi_lib.c
@@ -1750,6 +1750,21 @@ static int scsi_map_queues(struct blk_mq_tag_set *set)
return blk_mq_map_queues(>map[HCTX_TYPE_DEFAULT]);
 }
 
+static u64 scsi_calculate_bounce_limit(struct Scsi_Host *shost)
+{
+   struct device *dma_dev = shost->dma_dev;
+   u64 bounce_limit = 0x;
+
+   if (shost->unchecked_isa_dma)
+   return BLK_BOUNCE_ISA;
+
+   if (dma_dev && dma_dev->dma_mask)
+   bounce_limit = (u64)dma_max_pfn(dma_dev) << PAGE_SHIFT;
+
+   return bounce_limit;
+}
+
 void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
 {
struct device *dev = shost->dma_dev;
@@ -1769,8 +1784,7 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct 
request_queue *q)
}
 
blk_queue_max_hw_sectors(q, shost->max_sectors);
-   if (shost->unchecked_isa_dma)
-   blk_queue_bounce_limit(q, BLK_BOUNCE_ISA);
+   blk_queue_bounce_limit(q, scsi_calculate_bounce_limit(shost));
blk_queue_segment_boundary(q, shost->dma_boundary);
dma_set_seg_boundary(dev, shost->dma_boundary);

cheers,
-roger
-- 
Texas Instruments Finland Oy, Porkkalankatu 22, 00180 Helsinki.
Y-tunnus/Business ID: 0615521-4. Kotipaikka/Domicile: Helsinki
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: SATA broken with LPAE

2019-06-26 Thread Christoph Hellwig
Hi Roger,

it seems the arm dma direct mapping code isn't doing the right thing
here.  On other platforms that have > 4G memory we always use swiotlb
for bounce buffering in case a device that can't DMA to all the memory.

Arm is the odd one out and uses its own dmabounce framework instead,
but it seems like it doesn't get used in this case.  We need to make
sure dmabounce (or swiotlb for that matter) is set up if > 32-bit
addressing is supported.  I'm not really an arm platform expert,
but some of those on the Cc list are and might chime in on how to
do that.
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


RE: Re: CMA in AMD IOMMU driver

2019-06-26 Thread Sathyavathi M
Dear Christoph,

Thanks for the reply.
can you please let me know which kernel has it?


Thanks,
Sathya 
 
- Original Message -
Sender : Christoph Hellwig 
Date   : 2019-06-26 12:28 (GMT+5:30)
Title  : Re: CMA in AMD IOMMU driver
To : Sathyavathi M
CC : null
 
Toms conversion of the AMD IOMMU driver to use dma-iommu adds CMA
support :)
 
 
Regards,
Sathya
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: CMA in AMD IOMMU driver

2019-06-26 Thread Christoph Hellwig
Toms conversion of the AMD IOMMU driver to use dma-iommu adds CMA
support :)
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


CMA in AMD IOMMU driver

2019-06-26 Thread Sathyavathi M
Dear All,

This mail regarding the below communication about CMA in AMD IOMMU driver.

On Mon, Feb 02, 2015 at 10:35:36AM -0700, Alex Williamson wrote:
> [cc +joerg]
> 
> On Mon, 2015-02-02 at 11:01 -0500, Mark Hounschell wrote:
> >  From what I understand of CMA, and it seems provable to me, is that 
> > dma_alloc_coherent allocates my 8MB buffer from CMA defined on the 
> > cmdline. Without CMA specified on the cmdline, dma_alloc_coherent 
> > definitely fails to allocate an 8MB contiguous buffer. From what I've 
> > read about it, it is supposed to transparently "just work" when 
> > dma_alloc_coherent is used?
> 
> Yes, if you're running with the software iotlb (aka. bounce buffers),
> then dma_ops->alloc is x86_swiotlb_alloc_coherent(), which calls
> dma_generic_alloc_coherent(), which attempts to use CMA via
> dma_alloc_from_contiguous().
> 
> If you look at the same path with AMD-Vi, dma_ops->alloc is
> amd_iommu.c:alloc_coherent(), which simply uses __get_free_pages() to
> allocate the buffer.  I don't see any CMA integration along that path.
> If you were using Intel VT-d, then the buffer is again allocated with
> dma_alloc_from_contiguous() and should use CMA.  This was added in
> kernel v3.16, but no corresponding AMD-Vi change was added.  Joerg, this
> might be an easily fixed oversight.

Right, CMA is not yet integrated in the AMD IOMMU driver, nobody asked
fot it until now :) I will add that fall-back there for big allocations.


Joerg


Has CMA been added in AMD IOMMU driver, If yes which version of kernel has it.


Thanks in Advance.
 
Regards,
Sathya
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH AUTOSEL 5.1 09/51] iommu/vt-d: Fix lock inversion between iommu->lock and device_domain_lock

2019-06-26 Thread Joerg Roedel
Hi Sasha,

On Tue, Jun 25, 2019 at 11:40:25PM -0400, Sasha Levin wrote:
> From: Dave Jiang 
> 
> [ Upstream commit 7560cc3ca7d9d11555f80c830544e463fcdb28b8 ]

This commit was reverted upstream, please drop it from your stable
queue. It caused new lockdep issues.

Regards,

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


Re: [PATCH v3 3/4] iommu/arm-smmu: Add support to handle Qcom's wait-for-safe logic

2019-06-26 Thread Vivek Gautam
On Tue, Jun 25, 2019 at 7:09 PM Will Deacon  wrote:
>
> On Tue, Jun 25, 2019 at 12:34:56PM +0530, Vivek Gautam wrote:
> > On Mon, Jun 24, 2019 at 10:33 PM Will Deacon  wrote:
> > > Instead, I think this needs to be part of a separate file that is 
> > > maintained
> > > by you, which follows on from the work that Krishna is doing for nvidia
> > > built on top of Robin's prototype patches:
> > >
> > > http://linux-arm.org/git?p=linux-rm.git;a=shortlog;h=refs/heads/iommu/smmu-impl
> >
> > Looking at this branch quickly, it seem there can be separate implementation
> > level configuration file that can be added.
> > But will this also handle separate page table ops when required in future.
>
> Nothing's set in stone, but having the implementation-specific code
> constrain the page-table format (especially wrt quirks) sounds reasonable to
> me. I'm currently waiting for Krishna to respin the nvidia changes [1] on
> top of this so that we can see how well the abstractions are holding up.

Sure. Would you want me to try Robin's branch and take out the qualcomm
related stuff to its own implementation? Or, would you like me to respin this
series so that you can take it in to enable SDM845 boards such as, MTP
and dragonboard to have a sane build - debian, etc. so people benefit
out of it.
Qualcomm stuff is lying in qcom-smmu and arm-smmu and may take some
time to stub out the implementation related details.
Let me know your take.

Thanks & regards
Vivek

>
> I certainly won't merge the stuff until we have a user.
>
> Will
>
> [1] 
> https://lkml.kernel.org/r/1543887414-18209-1-git-send-email-vdu...@nvidia.com
> ___
> iommu mailing list
> iommu@lists.linux-foundation.org
> https://lists.linuxfoundation.org/mailman/listinfo/iommu



-- 
QUALCOMM INDIA, on behalf of Qualcomm Innovation Center, Inc. is a member
of Code Aurora Forum, hosted by The Linux Foundation