[PATCH v2] iommu/amd: Set AMD iommu callbacks for platform bus driver

2016-05-09 Thread Wan Zongshun
From: Wan Zongshun 

AMD has more drivers will use ACPI to platform bus driver later,
all those devices need iommu support, for example: eMMC driver.

For latest AMD eMMC controller, it will utilize sdhci-acpi.c driver,
which will rely on platform bus to match device and driver, where we
will set 'dev' of struct platform_device as map_sg parameter passing
to iommu driver for DMA request, so the iommu-ops are needed on the
platform bus.

Signed-off-by: Wan Zongshun 

---
changes from v1: Add comment why the iommu-ops are needed on platform bus.
---
 drivers/iommu/amd_iommu.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index c430c10..547cdd4 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -21,6 +21,7 @@
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -2980,6 +2981,9 @@ int __init amd_iommu_init_api(void)
if (err)
return err;
 #endif
+   err = bus_set_iommu(_bus_type, _iommu_ops);
+   if (err)
+   return err;
return 0;
 }
 
-- 
1.9.1

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


Re: [PATCH 1/5] dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi

2016-05-09 Thread 张洪辉
On 5/10/2016 4:22 AM, Rob Herring wrote:
> On Mon, May 09, 2016 at 04:00:12PM +0800, honghui.zh...@mediatek.com wrote:
>> From: Honghui Zhang 
>>
>> This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
>> add descriptions of binding for mediatek generation one iommu and smi.
>>
>> Signed-off-by: Honghui Zhang 
>> ---
>>  .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
>>  .../memory-controllers/mediatek,smi-common.txt | 21 +-
>>  .../memory-controllers/mediatek,smi-larb.txt   |  4 +-
>>  include/dt-bindings/memory/mt2701-larb-port.h  | 85 
>> ++
>>  4 files changed, 115 insertions(+), 8 deletions(-)
>>  create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h
>>
>> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt 
>> b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
>> index cd1b1cd..9a4a5b5 100644
>> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
>> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
>> @@ -1,7 +1,9 @@
>>  * Mediatek IOMMU Architecture Implementation
>>  
>> -  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
>> -uses the ARM Short-Descriptor translation table format for address 
>> translation.
>> +  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
>> +this M4U have two generations of HW architecture. Generation one use flat
> 
> s/use/uses/

Hi, Rob,
Thank you very much, I will fix all of those in the next version.

> 
>> +pagetable, and only support 4K size page mapping. Generation two uses the
> 
> s/support/supports/
> 
>> +ARM Short-Descriptor translation table format for address translation.
>>  
>>About the M4U Hardware Block Diagram, please check below:
>>  
>> @@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like 
>> MC, PP, VLD in the
>>  video decode local arbiter, all these ports are according to the video HW.
>>  
>>  Required properties:
>> -- compatible : must be "mediatek,mt8173-m4u".
>> +- compatible : must be one of the following string:
>> +"mediatek,mt2701-m4u" for mt2701 which use generation one m4u HW.
>> +"mediatek,mt8173-m4u" for mt8173 which use generation two m4u HW.
>>  - reg : m4u register base and size.
>>  - interrupts : the interrupt of m4u.
>>  - clocks : must contain one entry for each clock-names.
>> @@ -46,7 +50,8 @@ Required properties:
>>  according to the local arbiter index, like larb0, larb1, larb2...
>>  - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
>>  Specifies the mtk_m4u_id as defined in
>> -dt-binding/memory/mt8173-larb-port.h.
>> +dt-binding/memory/mt2701-larb-port.h for mt2701 and
>> +dt-binding/memory/mt8173-larb-port.h for mt8173
>>  
>>  Example:
>>  iommu: iommu@10205000 {
>> diff --git 
>> a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
>>  
>> b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
>> index 06a83ce..80c0e22 100644
>> --- 
>> a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
>> +++ 
>> b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
>> @@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
>>  
>>  The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
>>  
>> +Mediatek SMI have two generation HW architecture, mt8173 use the secondary
> 
> s/generation/generations of/
> s/use/uses/
> s/secondary/second/
> 
>> +generation of SMI HW while mt2701 use the first generation HW of SMI.
> 
> s/use/uses/
> 
>> +
>> +There's slight differences between the two SMI, for generation 2, the
>> +register which control the iommu port is at each larb's register base. But
>> +for generation 1, the register is at smi ao base(smi always on register
>> +base). Besides that, the smi async clock should be prepare and enabled for
> 
> s/prepare/prepared/
> 
>> +SMI generation 1 to transform the smi clock into emi clock domain, but no
> 
> s/no/that is not/
> 
>> +needed for SMI generation 2.
>> +
>>  Required properties:
>> -- compatible : must be "mediatek,mt8173-smi-common"
>> +- compatible : must be one of :
>> +"mediatek,mt2701-smi-common"
>> +"mediatek,mt8173-smi-common"
>>  - reg : the register and size of the SMI block.
>>  - power-domains : a phandle to the power domain of this local arbiter.
>>  - clocks : Must contain an entry for each entry in clock-names.
>> -- clock-names : must contain 2 entries, as follows:
>> +- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
>> +  for generation 2 smi HW as follows:
>>- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
>>  the register.
>>- "smi" : It's the clock for transfer data and command.
>> -  They may be the same if both source clocks are the same.
>> +

Re: [PATCH v9 7/7] vfio/type1: return MSI geometry through VFIO_IOMMU_GET_INFO capability chains

2016-05-09 Thread Alex Williamson
On Wed, 4 May 2016 14:06:19 +0200
Eric Auger  wrote:

> Hi Alex,
> On 05/04/2016 01:54 PM, Eric Auger wrote:
> > This patch allows the user-space to retrieve the MSI geometry. The
> > implementation is based on capability chains, now also added to
> > VFIO_IOMMU_GET_INFO.  
> 
> If you prefer we could consider this patch outside of the main series
> since it brings extra functionalities (MSI geometry reporting). In a
> first QEMU integration we would live without knowing the MSI geometry I
> think, all the more so I currently report an arbitrary number of
> requested IOVA pages. The computation of the exact number of doorbells
> to map brings extra complexity and I did not address this issue yet.
> 
> It sketches a possible user API to report the MSI geometry based on the
> capability chains, as you suggested some time ago. I am currently busy
> drafting a QEMU integration.

How would the user know that reserved MSI mappings are requires or
available without this?  Wouldn't the only option be for userspace to
try to map something with the reserved MSI flag set and see if the
kernel accepts it?  That's not a very desirable programming model.  The
arbitrary size is pretty ugly, but it at least makes for a consistent
user interface.  Is it a functional issue if we overestimate the size
or is it just a matter of wasting IOVA space?  Is there significant
harm in making it obscenely large, like 1MB?  The reference counting and
re-use of IOVA pages seems like we may often only be using a single
IOVA page for multiple doorbells.  I guess I'm leaning towards defining
the API even if the value is somewhat arbitrary because we'd rather have
control of this rather than having the user guess and try to rope them
back in later to use a kernel recommended value.  Thanks,

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


Re: [PATCH v9 7/7] vfio/type1: return MSI geometry through VFIO_IOMMU_GET_INFO capability chains

2016-05-09 Thread Alex Williamson
On Wed,  4 May 2016 11:54:18 +
Eric Auger  wrote:

> This patch allows the user-space to retrieve the MSI geometry. The
> implementation is based on capability chains, now also added to
> VFIO_IOMMU_GET_INFO.
> 
> The returned info comprise:
> - whether the MSI IOVA are constrained to a reserved range (x86 case) and
>   in the positive, the start/end of the aperture,
> - or whether the IOVA aperture need to be set by the userspace. In that
>   case, the size and alignment of the IOVA region to be provided are
>   returned.
> 
> In case the userspace must provide the IOVA range, we currently return
> an arbitrary number of IOVA pages (16), supposed to fulfill the needs of
> current ARM platforms. This may be deprecated by a more sophisticated
> computation later on.
> 
> Signed-off-by: Eric Auger 
> 
> ---
> v8 -> v9:
> - use iommu_msi_supported flag instead of programmable
> - replace IOMMU_INFO_REQUIRE_MSI_MAP flag by a more sophisticated
>   capability chain, reporting the MSI geometry
> 
> v7 -> v8:
> - use iommu_domain_msi_geometry
> 
> v6 -> v7:
> - remove the computation of the number of IOVA pages to be provisionned.
>   This number depends on the domain/group/device topology which can
>   dynamically change. Let's rely instead rely on an arbitrary max depending
>   on the system
> 
> v4 -> v5:
> - move msi_info and ret declaration within the conditional code
> 
> v3 -> v4:
> - replace former vfio_domains_require_msi_mapping by
>   more complex computation of MSI mapping requirements, especially the
>   number of pages to be provided by the user-space.
> - reword patch title
> 
> RFC v1 -> v1:
> - derived from
>   [RFC PATCH 3/6] vfio: Extend iommu-info to return MSIs automap state
> - renamed allow_msi_reconfig into require_msi_mapping
> - fixed VFIO_IOMMU_GET_INFO
> ---
>  drivers/vfio/vfio_iommu_type1.c | 69 
> +
>  include/uapi/linux/vfio.h   | 30 +-
>  2 files changed, 98 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2fc8197..841360b 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -1134,6 +1134,50 @@ static int vfio_domains_have_iommu_cache(struct 
> vfio_iommu *iommu)
>   return ret;
>  }
>  
> +static int compute_msi_geometry_caps(struct vfio_iommu *iommu,
> +  struct vfio_info_cap *caps)
> +{
> + struct vfio_iommu_type1_info_cap_msi_geometry *vfio_msi_geometry;
> + struct iommu_domain_msi_geometry msi_geometry;
> + struct vfio_info_cap_header *header;
> + struct vfio_domain *d;
> + bool mapping_required;
> + size_t size;
> +
> + mutex_lock(>lock);
> + /* All domains have same require_msi_map property, pick first */
> + d = list_first_entry(>domain_list, struct vfio_domain, next);
> + iommu_domain_get_attr(d->domain, DOMAIN_ATTR_MSI_GEOMETRY,
> +   _geometry);
> + mapping_required = msi_geometry.iommu_msi_supported;
> +
> + mutex_unlock(>lock);
> +
> + size = sizeof(*vfio_msi_geometry);
> + header = vfio_info_cap_add(caps, size,
> +VFIO_IOMMU_TYPE1_INFO_CAP_MSI_GEOMETRY, 1);
> +
> + if (IS_ERR(header))
> + return PTR_ERR(header);
> +
> + vfio_msi_geometry = container_of(header,
> + struct vfio_iommu_type1_info_cap_msi_geometry,
> + header);
> +
> + vfio_msi_geometry->reserved = !mapping_required;
> + if (vfio_msi_geometry->reserved) {
> + vfio_msi_geometry->aperture_start = msi_geometry.aperture_start;
> + vfio_msi_geometry->aperture_end = msi_geometry.aperture_end;
> + return 0;
> + }
> +
> + vfio_msi_geometry->alignment = 1 << __ffs(vfio_pgsize_bitmap(iommu));
> + /* we currently report the need for an arbitray number of 16 pages */
> + vfio_msi_geometry->size = 16 * vfio_msi_geometry->alignment;

Hmm, that really is arbitrary.  How could we know a real value here?

> +
> + return 0;
> +}
> +
>  static long vfio_iommu_type1_ioctl(void *iommu_data,
>  unsigned int cmd, unsigned long arg)
>  {
> @@ -1155,6 +1199,8 @@ 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 };
> + int ret;
>  
>   minsz = offsetofend(struct vfio_iommu_type1_info, iova_pgsizes);
>  
> @@ -1168,6 +1214,29 @@ static long vfio_iommu_type1_ioctl(void *iommu_data,
>  
>   info.iova_pgsizes = vfio_pgsize_bitmap(iommu);
>  
> + ret = compute_msi_geometry_caps(iommu, );
> + if (ret)
> + return ret;
> +
> + if 

Re: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at msi domain

2016-05-09 Thread Alex Williamson
On Wed,  4 May 2016 11:54:16 +
Eric Auger  wrote:

> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
> by the msi controller. vfio_safe_irq_domain allows to check whether
> interrupts are "safe" for a given device. They are if the device does
> not use MSI

Are we sure we're not opening a security hole here?  An MSI is simply a
DMA write, so really whether or not a device uses MSI is irrelevant.
If it can generate a DMA to the MSI doorbell then we need to be
protected and I think we pretty much need to assume that devices are
DMA capable.  Do the MSI domain checks cover this?

> or if the device uses MSI and the msi-parent controller
> supports IRQ remapping.
> 
> Then we check at group level if all devices have safe interrupts: if not,
> we only allow the group to be attached if allow_unsafe_interrupts is set.
> 
> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
> changed in next patch.
> 
> Signed-off-by: Eric Auger 
> 
> ---
> v3 -> v4:
> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>   and irq_remapping into safe_irq_domains
> 
> v2 -> v3:
> - protect vfio_msi_parent_irq_remapping_capable with
>   CONFIG_GENERIC_MSI_IRQ_DOMAIN
> ---
>  drivers/vfio/vfio_iommu_type1.c | 44 
> +++--
>  1 file changed, 42 insertions(+), 2 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 4d3a6f1..2fc8197 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -37,6 +37,8 @@
>  #include 
>  #include 
>  #include 
> +#include 
> +#include 
>  
>  #define DRIVER_VERSION  "0.2"
>  #define DRIVER_AUTHOR   "Alex Williamson "
> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>   return 0;
>  }
>  
> +/**
> + * vfio_safe_irq_domain: returns whether the irq domain
> + * the device is attached to is safe with respect to MSI isolation.
> + * If the irq domain is not an MSI domain, we return it is safe.
> + *
> + * @dev: device handle
> + * @data: unused
> + * returns 0 if the irq domain is safe, -1 if not.
> + */
> +static int vfio_safe_irq_domain(struct device *dev, void *data)
> +{
> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
> + struct irq_domain *domain;
> + struct msi_domain_info *info;
> +
> + domain = dev_get_msi_domain(dev);
> + if (!domain)
> + return 0;
> +
> + info = msi_get_domain_info(domain);
> +
> + if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
> + return -1;
> +#endif
> + return 0;
> +}
> +
>  static int vfio_iommu_replay(struct vfio_iommu *iommu,
>struct vfio_domain *domain)
>  {
> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void *iommu_data,
>   struct vfio_group *group, *g;
>   struct vfio_domain *domain, *d;
>   struct bus_type *bus = NULL;
> - int ret;
> + int ret, safe_irq_domains;
>  
>   mutex_lock(>lock);
>  
> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void 
> *iommu_data,
>  
>   group->iommu_group = iommu_group;
>  
> + /*
> +  * Determine if all the devices of the group have a safe irq domain
> +  * with respect to MSI isolation
> +  */
> + safe_irq_domains = !iommu_group_for_each_dev(iommu_group, ,
> +vfio_safe_irq_domain);
> +
>   /* Determine bus_type in order to allocate a domain */
>   ret = iommu_group_for_each_dev(iommu_group, , vfio_bus_type);
>   if (ret)
> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void 
> *iommu_data,
>   INIT_LIST_HEAD(>group_list);
>   list_add(>next, >group_list);
>  
> + /*
> +  * to advertise safe interrupts either the IOMMU or the MSI controllers
> +  * must support IRQ remapping/interrupt translation
> +  */
>   if (!allow_unsafe_interrupts &&
> - !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
> + (!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>   pr_warn("%s: No interrupt remapping support.  Use the module 
> param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this 
> platform\n",
>  __func__);
>   ret = -EPERM;

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


Re: [PATCH v9 2/7] vfio/type1: vfio_find_dma accepting a type argument

2016-05-09 Thread Alex Williamson
On Wed,  4 May 2016 11:54:13 +
Eric Auger  wrote:

> In our RB-tree we now have slots of different types (USER and RESERVED).
> It becomes useful to be able to search for dma slots of a specific type or
> any type. This patch proposes an implementation for that modality and also
> changes the existing callers using the USER type.
> 
> Signed-off-by: Eric Auger 
> ---
>  drivers/vfio/vfio_iommu_type1.c | 63 
> ++---
>  1 file changed, 53 insertions(+), 10 deletions(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index aaf5a6c..2d769d4 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -98,23 +98,64 @@ struct vfio_group {
>   * into DMA'ble space using the IOMMU
>   */
>  
> -static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> -   dma_addr_t start, size_t size)
> +/**
> + * vfio_find_dma_from_node: looks for a dma slot intersecting a window
> + * from a given rb tree node
> + * @top: top rb tree node where the search starts (including this node)
> + * @start: window start
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma_from_node(struct rb_node *top,
> + dma_addr_t start, size_t size,
> + enum vfio_iova_type type)
>  {
> - struct rb_node *node = iommu->dma_list.rb_node;
> + struct rb_node *node = top;
> + struct vfio_dma *dma;
>  
>   while (node) {
> - struct vfio_dma *dma = rb_entry(node, struct vfio_dma, node);
> -
> + dma = rb_entry(node, struct vfio_dma, node);
>   if (start + size <= dma->iova)
>   node = node->rb_left;
>   else if (start >= dma->iova + dma->size)
>   node = node->rb_right;
>   else
> + break;
> + }
> + if (!node)
> + return NULL;
> +
> + /* a dma slot intersects our window, check the type also matches */
> + if (type == VFIO_IOVA_ANY || dma->type == type)
> + return dma;
> +
> + /* restart 2 searches skipping the current node */
> + if (start < dma->iova) {
> + dma = vfio_find_dma_from_node(node->rb_left, start,
> +   size, type);
> + if (dma)
>   return dma;
>   }
> + if (start + size > dma->iova + dma->size)
> + dma = vfio_find_dma_from_node(node->rb_right, start,
> +   size, type);

It might be nice to split this little bit of trickery out to a separate
patch so that you can better explain what it does.  It's really not
needed until we start creating user-type entries, so it shouldn't hurt
bisection.

> + return dma;
> +}
> +
> +/**
> + * vfio_find_dma: find a dma slot intersecting a given window
> + * @iommu: vfio iommu handle
> + * @start: window base iova
> + * @size: window size
> + * @type: window type
> + */
> +static struct vfio_dma *vfio_find_dma(struct vfio_iommu *iommu,
> +   dma_addr_t start, size_t size,
> +   enum vfio_iova_type type)
> +{
> + struct rb_node *top_node = iommu->dma_list.rb_node;
>  
> - return NULL;
> + return vfio_find_dma_from_node(top_node, start, size, type);
>  }
>  
>  static void vfio_link_dma(struct vfio_iommu *iommu, struct vfio_dma *new)
> @@ -488,19 +529,21 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
>* mappings within the range.
>*/
>   if (iommu->v2) {
> - dma = vfio_find_dma(iommu, unmap->iova, 0);
> + dma = vfio_find_dma(iommu, unmap->iova, 0, VFIO_IOVA_USER);
>   if (dma && dma->iova != unmap->iova) {
>   ret = -EINVAL;
>   goto unlock;
>   }
> - dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0);
> + dma = vfio_find_dma(iommu, unmap->iova + unmap->size - 1, 0,
> + VFIO_IOVA_USER);
>   if (dma && dma->iova + dma->size != unmap->iova + unmap->size) {
>   ret = -EINVAL;
>   goto unlock;
>   }
>   }
>  
> - while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size))) {
> + while ((dma = vfio_find_dma(iommu, unmap->iova, unmap->size,
> + VFIO_IOVA_USER))) {
>   if (!iommu->v2 && unmap->iova > dma->iova)
>   break;
>   unmapped += dma->size;
> @@ -604,7 +647,7 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>  
>   mutex_lock(>lock);
>  
> - if (vfio_find_dma(iommu, iova, size)) {
> + if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>   

Re: [PATCH v9 3/7] vfio/type1: bypass unmap/unpin and replay for VFIO_IOVA_RESERVED slots

2016-05-09 Thread Alex Williamson
On Wed,  4 May 2016 11:54:14 +
Eric Auger  wrote:

> Before allowing the end-user to create VFIO_IOVA_RESERVED dma slots,
> let's implement the expected behavior for removal and replay. As opposed
> to user dma slots, IOVAs are not systematically bound to PAs and PAs are
> not pinned. VFIO just initializes the IOVA "aperture". IOVAs are allocated
> outside of the VFIO framework, typically the MSI layer which is
> responsible to free and unmap them. The MSI mapping resources are freeed
> by the IOMMU driver on domain destruction.
> 
> Signed-off-by: Eric Auger 
> 
> ---
> 
> v7 -> v8:
> - do no destroy anything anymore, just bypass unmap/unpin and iommu_map
>   on replay
> ---
>  drivers/vfio/vfio_iommu_type1.c | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c
> index 2d769d4..94a9916 100644
> --- a/drivers/vfio/vfio_iommu_type1.c
> +++ b/drivers/vfio/vfio_iommu_type1.c
> @@ -391,7 +391,7 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, 
> struct vfio_dma *dma)
>   struct vfio_domain *domain, *d;
>   long unlocked = 0;
>  
> - if (!dma->size)
> + if (!dma->size || dma->type != VFIO_IOVA_USER)
>   return;
>   /*
>* We use the IOMMU to track the physical addresses, otherwise we'd
> @@ -727,6 +727,9 @@ static int vfio_iommu_replay(struct vfio_iommu *iommu,
>   dma = rb_entry(n, struct vfio_dma, node);
>   iova = dma->iova;
>  
> + if (dma->type == VFIO_IOVA_RESERVED)
> + continue;
> +

But you do still need some sort of replay mechanism, right?  Not to
replay the IOVA to PA mapping, but to call iommu_msi_set_aperture() for
the new domain.  How will you know that this entry is an MSI reserved
range or something else?  Perhaps we can't have a generic "reserved"
type here.

>   while (iova < dma->iova + dma->size) {
>   phys_addr_t phys = iommu_iova_to_phys(d->domain, iova);
>   size_t size;

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


Re: [PATCH V4 0/4] Code refine for Intel IOMMU

2016-05-09 Thread Wei Yang
On Mon, May 09, 2016 at 01:24:02PM +0200, Joerg Roedel wrote:
>On Sun, May 08, 2016 at 01:22:53PM +, Wei Yang wrote:
>> >Wei Yang (4):
>> >  iommu/vt-d: replace *hdr with {drhd/atsr}[0] in struct
>> >dmar_{drhd/atsr}_unit
>> >  iommu/vt-d: use zero-sized array in DMAR related ACPI structures
>> >  iommu/vt-d: check Register Base Address at the beginning of
>> >dmar_parse_one_drhd()
>> >  iommu/vt-d: refine dmar_acpi_dev_scope_init() with
>> >dmar_walk_dmar_table()
>
>Okay, I've ignored this so far as I don't see where you are going with
>this refactoring. The patches as-is don't make much sense to me other
>than creating conflicts with other vt-d driver changes.
>

Hi, Joerg

Thanks for your comments. 

Generally, the purpose of these patches is to make the code more audience
friendly. Below is my thoughts for each patch.

For Patch 1, the zero-sized drhd/atsr would save some space in
dmar_{drhd/atsr}_unit. As in the change log explained, before commit
<6b1972493a84> ("iommu/vt-d: Implement DMAR unit hotplug framework"), it is
necessary to have a pointer. While after this commit, we just need a place
holder.

For Patch 2, I add a zero-sized array at the end of related structures to
represent variable length elements. By doing so, our code could use this field
to be a parameter for a function instead of casting and add 1. I think this
would let audience understand the variable elements is used here instead of go
through SPEC to check which part it means, which is not that reader friendly.

For Patch 3, when you go through the code, Register Base Address will be
checked to see whether this is a valid dmar. Since this is what we have to do,
I move this step a little bit ahead, so that we can avoid related setups at
the first place.

For Patch 4, dmar_acpi_dev_scope_init() initialize dev_scope by iterate on the
remapping structure. We can see this is just what dmar_walk_dmar_table() does.
So I reuse the code in this place.

In my mind, those changes are dmar internal changes, which will not be seen
outside. Would you mind pointing me the conflicts you saw? Maybe I missed some
thing :-)

Thanks, have a good day.

>
>
>   Joerg

-- 
Wei Yang
Help you, Help me
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [RFC PATCH v1 00/18] x86: Secure Memory Encryption (AMD)

2016-05-09 Thread Tom Lendacky
On 05/09/2016 10:13 AM, Paolo Bonzini wrote:
> 
> 
> On 02/05/2016 20:31, Andy Lutomirski wrote:
>> And did the SEV implementation remember to encrypt the guest register
>> state?  Because, if not, everything of importance will leak out
>> through the VMCB and/or GPRs.
> 
> No, it doesn't.  And SEV is very limited unless you paravirtualize
> everything.
> 
> For example, the hypervisor needs to read some instruction bytes from
> memory, and instruction bytes are always encrypted (15.34.5 in the APM).
>  So you're pretty much restricted to IN/OUT operations (not even
> INS/OUTS) on emulated (non-assigned) devices, paravirtualized MSRs, and
> hypercalls.  These are the only operations that connect the guest and
> the hypervisor, where the vmexit doesn't have the need to e.g. walk
> guest page tables (also always encrypted).  It possibly can be made to
> work once the guest boots, and a modern UEFI firmware probably can cope
> with it too just like a kernel can, but you need to ensure that your
> hardware has no memory BARs for example.  And I/O port space is not very
> abundant.

The instruction bytes stored in the VMCB at offset 0xd0 for a data
side #NPF are stored un-encrypted (which is not clearly documented in
the APM). This allows for the hypervisor to perform MMIO on emulated
devices. Because the hardware provides enough information on VMEXIT
events, such as exit codes, decode assist, etc., the hypervisor has
the information it needs to perform the operation without having to
read the guest pagetables and/or the guest instruction stream from
guest memory. There are a few minor corner cases (e.g. rep ins) and
there will be more info on those when the SEV patches are submitted.

> 
> Even in order to emulate I/O ports or RDMSR/WRMSR or process hypercalls,
> the hypervisor needs to read the GPRs.  The VMCB doesn't store guest
> GPRs, not even on SEV-enabled processors.  Accordingly, the hypervisor
> has access to the guest GPRs on every exit.

In this initial version of SEV support the hardware does not encrypt
the guest save state and the hypervisor does have access to the GPRs.

> 
> In general, SEV provides mitigation only.  Even if the hypervisor cannot
> write known plaintext directly to memory, an accomplice virtual machine
> can e.g. use the network to spray the attacked VM's memory.  At least

Can you elaborate further on this? The accomplice VM will not have
access to the encryption key of the target VM and cannot accomplish
any spraying that the hypervisor itself cannot do.

> it's not as easy as "disable NX under the guest's feet and redirect RIP"
> (pte.nx is reserved if efer.nxe=0, all you get is a #PF).  But the
> hypervisor can still disable SMEP and SMAP, it can use hardware
> breakpoints to leak information through the registers, and it can do all
> the other attacks you mentioned.  If AMD had rdrand/rdseed, it could
> replace the output with not so random values, and so on.

AMD added support for the rdrand in some of the later fam16h models.

> 
> It's surely better than nothing, but "encryption that really is nothing
> more than mitigation" is pretty weird.  I'm waiting for cloud vendors to
> sell this as the best thing since sliced bread, when in reality it's
> just mitigation.  I wonder how wise it is to merge SEV in its current
> state---and since security is not my specialty I am definitely looking
> for advice on this.
> 

In this first generation of SEV, we are targeting a threat model very
similar to the one used by SMEP and SMAP. Specifically, SEV protects a
guest from a benign but vulnerable hypervisor, where a malicious guest
or unprivileged process exploits a system/hypervisor interface in an
attempt to read or modify the guest's memory.  But, like SMEP and SMAP,
if an attacker has the ability to arbitrarily execute code in the
kernel, he would be able to circumvent the control. AMD has a vision
for this generation of SEV to be foundational to future generations
that defend against stronger attacks.

Thanks,
Tom

> Paolo
> 
> ps: I'm now reminded of this patch:
> 
> commit dab429a798a8ab3377136e09dda55ea75a41648d
> Author: David Kaplan 
> Date:   Mon Mar 2 13:43:37 2015 -0600
> 
> kvm: svm: make wbinvd faster
> 
> No need to re-decode WBINVD since we know what it is from the
> intercept.
> 
> Signed-off-by: David Kaplan 
> [extracted from larger unlrelated patch, forward ported,
>  tested,style cleanup]
> Signed-off-by: Joel Schopp 
> Reviewed-by: Radim Krčmář 
> Signed-off-by: Marcelo Tosatti 
> 
> and I wonder if the larger unlrelated patch had anything to do with SEV!
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH v9 4/8] iommu/msi-iommu: initialization

2016-05-09 Thread Alex Williamson
On Wed,  4 May 2016 11:40:03 +
Eric Auger  wrote:

> iommu_get/put_msi_cookie allocates/frees the resource used to store
> and ref count the MSI doorbell mappings. iommu_msi_set_aperture
> initializes the iova domain used for MSI IOVA allocation and sets the
> iommu domain's msi geometry.
> 
> The implementation relies on dma-iommu API and iova API.
> 
> New msi functions are fully implemented if CONFIG_IOMMU_MSI is set.
> 
> Signed-off-by: Eric Auger 
> 
> ---
> v9:
> - remove is_aperture_set and use iommu_domain_msi_aperture_valid helper
>   instead
> - set iommu domain's msi geometry
> 
> v8:
> - new design where msi-iommu relies on dma-iommu
> - remove the iommu_domain * from the doorbell_mapping struct
> - added is_aperture_set
> 
> v7:
> - fix locking
> - add iova_cache_get/put
> - static inline functions when CONFIG_IOMMU_DMA_RESERVED is not set
> - introduce struct reserved_iova_domain to encapsulate prot info &
>   add prot parameter in alloc_reserved_iova_domain
> 
> v5 -> v6:
> - use spin lock instead of mutex
> 
> v3 -> v4:
> - formerly in "iommu/arm-smmu: implement alloc/free_reserved_iova_domain" &
>   "iommu: add alloc/free_reserved_iova_domain"
> 
> v2 -> v3:
> - remove iommu_alloc_reserved_iova_domain & iommu_free_reserved_iova_domain
>   static implementation in case CONFIG_IOMMU_API is not set
> 
> v1 -> v2:
> - moved from vfio API to IOMMU API
> ---
>  drivers/iommu/Kconfig |  7 
>  drivers/iommu/Makefile|  1 +
>  drivers/iommu/msi-iommu.c | 97 
> +++
>  include/linux/msi-iommu.h | 65 +++
>  4 files changed, 170 insertions(+)
>  create mode 100644 drivers/iommu/msi-iommu.c
>  create mode 100644 include/linux/msi-iommu.h
> 
> diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
> index dd1dc39..0078b72 100644
> --- a/drivers/iommu/Kconfig
> +++ b/drivers/iommu/Kconfig
> @@ -74,6 +74,11 @@ config IOMMU_DMA
>   select IOMMU_IOVA
>   select NEED_SG_DMA_LENGTH
>  
> +# IOMMU MSI mapping
> +config IOMMU_MSI
> + bool
> + select IOMMU_DMA
> +
>  config FSL_PAMU
>   bool "Freescale IOMMU support"
>   depends on PPC32
> @@ -307,6 +312,7 @@ config SPAPR_TCE_IOMMU
>  config ARM_SMMU
>   bool "ARM Ltd. System MMU (SMMU) Support"
>   depends on (ARM64 || ARM) && MMU
> + select IOMMU_MSI
>   select IOMMU_API
>   select IOMMU_IO_PGTABLE_LPAE
>   select ARM_DMA_USE_IOMMU if ARM
> @@ -320,6 +326,7 @@ config ARM_SMMU
>  config ARM_SMMU_V3
>   bool "ARM Ltd. System MMU Version 3 (SMMUv3) Support"
>   depends on ARM64 && PCI
> + select IOMMU_MSI
>   select IOMMU_API
>   select IOMMU_IO_PGTABLE_LPAE
>   select GENERIC_MSI_IRQ_DOMAIN
> diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
> index c6edb31..a381e66 100644
> --- a/drivers/iommu/Makefile
> +++ b/drivers/iommu/Makefile
> @@ -2,6 +2,7 @@ obj-$(CONFIG_IOMMU_API) += iommu.o
>  obj-$(CONFIG_IOMMU_API) += iommu-traces.o
>  obj-$(CONFIG_IOMMU_API) += iommu-sysfs.o
>  obj-$(CONFIG_IOMMU_DMA) += dma-iommu.o
> +obj-$(CONFIG_IOMMU_MSI) += msi-iommu.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE) += io-pgtable.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE_ARMV7S) += io-pgtable-arm-v7s.o
>  obj-$(CONFIG_IOMMU_IO_PGTABLE_LPAE) += io-pgtable-arm.o
> diff --git a/drivers/iommu/msi-iommu.c b/drivers/iommu/msi-iommu.c
> new file mode 100644
> index 000..4292957
> --- /dev/null
> +++ b/drivers/iommu/msi-iommu.c
> @@ -0,0 +1,97 @@
> +/*
> + * Reserved IOVA Management
> + *
> + * Copyright (c) 2015 Linaro Ltd.
> + *  www.linaro.org
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License version 2 as
> + * published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU General Public License for more details.
> + *
> + */
> +
> +#include 
> +#include 
> +#include 
> +#include 
> +#include 
> +
> +struct doorbell_mapping {
> + struct kref kref;
> + struct list_headnext;
> + phys_addr_t addr;
> + dma_addr_t  iova;
> + size_t  size;
> +};
> +
> +struct doorbell_mapping_info {
> + struct list_head list; /* list of doorbell mapping entries */
> + spinlock_t lock;
> +};
> +
> +int iommu_get_msi_cookie(struct iommu_domain *domain)
> +{
> + struct doorbell_mapping_info *dmi;
> + int ret;
> +
> + if (domain->msi_cookie || domain->iova_cookie)
> + return -EINVAL;
> +
> + ret = iommu_get_dma_cookie(domain);
> + if (ret)
> + return ret;
> +
> + dmi = kzalloc(sizeof(*dmi), GFP_KERNEL);
> +
> + INIT_LIST_HEAD(>list);
> + spin_lock_init(>lock);
> + 

Re: [PATCH 1/5] dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi

2016-05-09 Thread Rob Herring
On Mon, May 09, 2016 at 04:00:12PM +0800, honghui.zh...@mediatek.com wrote:
> From: Honghui Zhang 
> 
> This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
> add descriptions of binding for mediatek generation one iommu and smi.
> 
> Signed-off-by: Honghui Zhang 
> ---
>  .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
>  .../memory-controllers/mediatek,smi-common.txt | 21 +-
>  .../memory-controllers/mediatek,smi-larb.txt   |  4 +-
>  include/dt-bindings/memory/mt2701-larb-port.h  | 85 
> ++
>  4 files changed, 115 insertions(+), 8 deletions(-)
>  create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h
> 
> diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt 
> b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> index cd1b1cd..9a4a5b5 100644
> --- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> +++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
> @@ -1,7 +1,9 @@
>  * Mediatek IOMMU Architecture Implementation
>  
> -  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
> -uses the ARM Short-Descriptor translation table format for address 
> translation.
> +  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
> +this M4U have two generations of HW architecture. Generation one use flat

s/use/uses/

> +pagetable, and only support 4K size page mapping. Generation two uses the

s/support/supports/

> +ARM Short-Descriptor translation table format for address translation.
>  
>About the M4U Hardware Block Diagram, please check below:
>  
> @@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, 
> PP, VLD in the
>  video decode local arbiter, all these ports are according to the video HW.
>  
>  Required properties:
> -- compatible : must be "mediatek,mt8173-m4u".
> +- compatible : must be one of the following string:
> + "mediatek,mt2701-m4u" for mt2701 which use generation one m4u HW.
> + "mediatek,mt8173-m4u" for mt8173 which use generation two m4u HW.
>  - reg : m4u register base and size.
>  - interrupts : the interrupt of m4u.
>  - clocks : must contain one entry for each clock-names.
> @@ -46,7 +50,8 @@ Required properties:
>   according to the local arbiter index, like larb0, larb1, larb2...
>  - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
>   Specifies the mtk_m4u_id as defined in
> - dt-binding/memory/mt8173-larb-port.h.
> + dt-binding/memory/mt2701-larb-port.h for mt2701 and
> + dt-binding/memory/mt8173-larb-port.h for mt8173
>  
>  Example:
>   iommu: iommu@10205000 {
> diff --git 
> a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
>  
> b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> index 06a83ce..80c0e22 100644
> --- 
> a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> +++ 
> b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
> @@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
>  
>  The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
>  
> +Mediatek SMI have two generation HW architecture, mt8173 use the secondary

s/generation/generations of/
s/use/uses/
s/secondary/second/

> +generation of SMI HW while mt2701 use the first generation HW of SMI.

s/use/uses/

> +
> +There's slight differences between the two SMI, for generation 2, the
> +register which control the iommu port is at each larb's register base. But
> +for generation 1, the register is at smi ao base(smi always on register
> +base). Besides that, the smi async clock should be prepare and enabled for

s/prepare/prepared/

> +SMI generation 1 to transform the smi clock into emi clock domain, but no

s/no/that is not/

> +needed for SMI generation 2.
> +
>  Required properties:
> -- compatible : must be "mediatek,mt8173-smi-common"
> +- compatible : must be one of :
> + "mediatek,mt2701-smi-common"
> + "mediatek,mt8173-smi-common"
>  - reg : the register and size of the SMI block.
>  - power-domains : a phandle to the power domain of this local arbiter.
>  - clocks : Must contain an entry for each entry in clock-names.
> -- clock-names : must contain 2 entries, as follows:
> +- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
> +  for generation 2 smi HW as follows:
>- "apb" : Advanced Peripheral Bus clock, It's the clock for setting
>   the register.
>- "smi" : It's the clock for transfer data and command.
> -  They may be the same if both source clocks are the same.
> + They may be the same if both source clocks are the same.
> +  - "async" : asynchronous clock, it help transform the smi clock into the 
> emi
> +   clock domain, this clock is only needed by generation 1 smi HW.
>  
>  Example:
>

[PATCHv6 8/8] ARM: dts: r8a7791: add iommus to dmac0 and dmac1

2016-05-09 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund 
Acked-by: Laurent Pinchart 
---
 arch/arm/boot/dts/r8a7791.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7791.dtsi b/arch/arm/boot/dts/r8a7791.dtsi
index 4f01b64..dc81c90 100644
--- a/arch/arm/boot/dts/r8a7791.dtsi
+++ b/arch/arm/boot/dts/r8a7791.dtsi
@@ -313,6 +313,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -344,6 +359,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.8.2

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

[PATCHv6 4/8] arm: dma-mapping: add {map, unmap}_resource for iommu ops

2016-05-09 Thread Niklas Söderlund
Add methods to map/unmap device resources addresses for dma_map_ops that
are IOMMU aware. This is needed to map a device MMIO register from a
physical address.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 arch/arm/mm/dma-mapping.c | 63 +++
 1 file changed, 63 insertions(+)

diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index deac58d..d5fe32b 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -1962,6 +1962,63 @@ static void arm_iommu_unmap_page(struct device *dev, 
dma_addr_t handle,
__free_iova(mapping, iova, len);
 }
 
+/**
+ * arm_iommu_map_resource - map a device resource for DMA
+ * @dev: valid struct device pointer
+ * @phys_addr: physical address of resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static dma_addr_t arm_iommu_map_resource(struct device *dev,
+   phys_addr_t phys_addr, size_t size,
+   enum dma_data_direction dir, struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t dma_addr;
+   int ret, prot;
+   phys_addr_t addr = phys_addr & PAGE_MASK;
+   int offset = phys_addr & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   dma_addr = __alloc_iova(mapping, size);
+   if (dma_addr == DMA_ERROR_CODE)
+   return dma_addr;
+
+   prot = __dma_direction_to_prot(dir) | IOMMU_MMIO;
+
+   ret = iommu_map(mapping->domain, dma_addr, addr, len, prot);
+   if (ret < 0)
+   goto fail;
+
+   return dma_addr + offset;
+fail:
+   __free_iova(mapping, dma_addr, size);
+   return DMA_ERROR_CODE;
+}
+
+/**
+ * arm_iommu_unmap_resource - unmap a device DMA resource
+ * @dev: valid struct device pointer
+ * @dma_handle: DMA address to resource
+ * @size: size of resource to map
+ * @dir: DMA transfer direction
+ */
+static void arm_iommu_unmap_resource(struct device *dev, dma_addr_t dma_handle,
+   size_t size, enum dma_data_direction dir,
+   struct dma_attrs *attrs)
+{
+   struct dma_iommu_mapping *mapping = to_dma_iommu_mapping(dev);
+   dma_addr_t iova = dma_handle & PAGE_MASK;
+   int offset = dma_handle & ~PAGE_MASK;
+   int len = PAGE_ALIGN(size + offset);
+
+   if (!iova)
+   return;
+
+   iommu_unmap(mapping->domain, iova, len);
+   __free_iova(mapping, iova, len);
+}
+
 static void arm_iommu_sync_single_for_cpu(struct device *dev,
dma_addr_t handle, size_t size, enum dma_data_direction dir)
 {
@@ -2006,6 +2063,9 @@ struct dma_map_ops iommu_ops = {
.sync_sg_for_cpu= arm_iommu_sync_sg_for_cpu,
.sync_sg_for_device = arm_iommu_sync_sg_for_device,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
@@ -2021,6 +2081,9 @@ struct dma_map_ops iommu_coherent_ops = {
.map_sg = arm_coherent_iommu_map_sg,
.unmap_sg   = arm_coherent_iommu_unmap_sg,
 
+   .map_resource   = arm_iommu_map_resource,
+   .unmap_resource = arm_iommu_unmap_resource,
+
.set_dma_mask   = arm_dma_set_mask,
 };
 
-- 
2.8.2

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

[PATCHv6 5/8] dmaengine: rcar-dmac: group slave configuration

2016-05-09 Thread Niklas Söderlund
Group slave address and transfer size in own structs for source and
destination. This is in preparation for hooking up the dma-mapping API
to the slave addresses.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 drivers/dma/sh/rcar-dmac.c | 38 ++
 1 file changed, 22 insertions(+), 16 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index dfb1792..b0c3bb2 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -118,14 +118,22 @@ struct rcar_dmac_desc_page {
sizeof(struct rcar_dmac_xfer_chunk))
 
 /*
+ * struct rcar_dmac_chan_slave - Slave configuration
+ * @slave_addr: slave memory address
+ * @xfer_size: size (in bytes) of hardware transfers
+ */
+struct rcar_dmac_chan_slave {
+   phys_addr_t slave_addr;
+   unsigned int xfer_size;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
  * @index: index of this channel in the controller
- * @src_xfer_size: size (in bytes) of hardware transfers on the source side
- * @dst_xfer_size: size (in bytes) of hardware transfers on the destination 
side
- * @src_slave_addr: slave source memory address
- * @dst_slave_addr: slave destination memory address
+ * @src: slave memory address and size on the source side
+ * @dst: slave memory address and size on the destination side
  * @mid_rid: hardware MID/RID for the DMA client using this channel
  * @lock: protects the channel CHCR register and the desc members
  * @desc.free: list of free descriptors
@@ -142,10 +150,8 @@ struct rcar_dmac_chan {
void __iomem *iomem;
unsigned int index;
 
-   unsigned int src_xfer_size;
-   unsigned int dst_xfer_size;
-   dma_addr_t src_slave_addr;
-   dma_addr_t dst_slave_addr;
+   struct rcar_dmac_chan_slave src;
+   struct rcar_dmac_chan_slave dst;
int mid_rid;
 
spinlock_t lock;
@@ -793,13 +799,13 @@ static void rcar_dmac_chan_configure_desc(struct 
rcar_dmac_chan *chan,
case DMA_DEV_TO_MEM:
chcr = RCAR_DMACHCR_DM_INC | RCAR_DMACHCR_SM_FIXED
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->src_xfer_size;
+   xfer_size = chan->src.xfer_size;
break;
 
case DMA_MEM_TO_DEV:
chcr = RCAR_DMACHCR_DM_FIXED | RCAR_DMACHCR_SM_INC
 | RCAR_DMACHCR_RS_DMARS;
-   xfer_size = chan->dst_xfer_size;
+   xfer_size = chan->dst.xfer_size;
break;
 
case DMA_MEM_TO_MEM:
@@ -1038,7 +1044,7 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, false);
 }
@@ -1093,7 +1099,7 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
}
 
dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src_slave_addr : rchan->dst_slave_addr;
+? rchan->src.slave_addr : rchan->dst.slave_addr;
desc = rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
  dir, flags, true);
 
@@ -1110,10 +1116,10 @@ static int rcar_dmac_device_config(struct dma_chan 
*chan,
 * We could lock this, but you shouldn't be configuring the
 * channel, while using it...
 */
-   rchan->src_slave_addr = cfg->src_addr;
-   rchan->dst_slave_addr = cfg->dst_addr;
-   rchan->src_xfer_size = cfg->src_addr_width;
-   rchan->dst_xfer_size = cfg->dst_addr_width;
+   rchan->src.slave_addr = cfg->src_addr;
+   rchan->dst.slave_addr = cfg->dst_addr;
+   rchan->src.xfer_size = cfg->src_addr_width;
+   rchan->dst.xfer_size = cfg->dst_addr_width;
 
return 0;
 }
-- 
2.8.2

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

[PATCHv6 6/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-05-09 Thread Niklas Söderlund
Enable slave transfers to a device behind a IPMMU by mapping the slave
addresses using the dma-mapping API.

Signed-off-by: Niklas Söderlund 
---
 drivers/dma/sh/rcar-dmac.c | 82 +-
 1 file changed, 74 insertions(+), 8 deletions(-)

diff --git a/drivers/dma/sh/rcar-dmac.c b/drivers/dma/sh/rcar-dmac.c
index b0c3bb2..8592598 100644
--- a/drivers/dma/sh/rcar-dmac.c
+++ b/drivers/dma/sh/rcar-dmac.c
@@ -128,6 +128,18 @@ struct rcar_dmac_chan_slave {
 };
 
 /*
+ * struct rcar_dmac_chan_map - Map of slave device phys to dma address
+ * @addr: slave dma address
+ * @dir: direction of mapping
+ * @slave: slave configuration that is mapped
+ */
+struct rcar_dmac_chan_map {
+   dma_addr_t addr;
+   enum dma_data_direction dir;
+   struct rcar_dmac_chan_slave slave;
+};
+
+/*
  * struct rcar_dmac_chan - R-Car Gen2 DMA Controller Channel
  * @chan: base DMA channel object
  * @iomem: channel I/O memory base
@@ -152,6 +164,7 @@ struct rcar_dmac_chan {
 
struct rcar_dmac_chan_slave src;
struct rcar_dmac_chan_slave dst;
+   struct rcar_dmac_chan_map map;
int mid_rid;
 
spinlock_t lock;
@@ -1027,13 +1040,65 @@ rcar_dmac_prep_dma_memcpy(struct dma_chan *chan, 
dma_addr_t dma_dest,
  DMA_MEM_TO_MEM, flags, false);
 }
 
+static int rcar_dmac_map_slave_addr(struct dma_chan *chan,
+   enum dma_transfer_direction dir)
+{
+   struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
+   struct rcar_dmac_chan_map *map = >map;
+   phys_addr_t dev_addr;
+   size_t dev_size;
+   enum dma_data_direction dev_dir;
+
+   if (dir == DMA_DEV_TO_MEM) {
+   dev_addr = rchan->src.slave_addr;
+   dev_size = rchan->src.xfer_size;
+   dev_dir = DMA_TO_DEVICE;
+   } else {
+   dev_addr = rchan->dst.slave_addr;
+   dev_size = rchan->dst.xfer_size;
+   dev_dir = DMA_FROM_DEVICE;
+   }
+
+   /* Reuse current map if possible. */
+   if (dev_addr == map->slave.slave_addr &&
+   dev_size == map->slave.xfer_size &&
+   dev_dir == map->dir)
+   return 0;
+
+   /* Remove old mapping if present. */
+   if (map->slave.xfer_size)
+   dma_unmap_resource(chan->device->dev, map->addr,
+  map->slave.xfer_size, map->dir, NULL);
+   map->slave.xfer_size = 0;
+
+   /* Create new slave address map. */
+   map->addr = dma_map_resource(chan->device->dev, dev_addr, dev_size,
+dev_dir, NULL);
+
+   if (dma_mapping_error(chan->device->dev, map->addr)) {
+   dev_err(chan->device->dev,
+   "chan%u: failed to map %zx@%pap", rchan->index,
+   dev_size, _addr);
+   return -EIO;
+   }
+
+   dev_dbg(chan->device->dev, "chan%u: map %zx@%pap to %pad dir: %s\n",
+   rchan->index, dev_size, _addr, >addr,
+   dev_dir == DMA_TO_DEVICE ? "DMA_TO_DEVICE" : "DMA_FROM_DEVICE");
+
+   map->slave.slave_addr = dev_addr;
+   map->slave.xfer_size = dev_size;
+   map->dir = dev_dir;
+
+   return 0;
+}
+
 static struct dma_async_tx_descriptor *
 rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct scatterlist *sgl,
unsigned int sg_len, enum dma_transfer_direction dir,
unsigned long flags, void *context)
 {
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
-   dma_addr_t dev_addr;
 
/* Someone calling slave DMA on a generic channel? */
if (rchan->mid_rid < 0 || !sg_len) {
@@ -1043,9 +1108,10 @@ rcar_dmac_prep_slave_sg(struct dma_chan *chan, struct 
scatterlist *sgl,
return NULL;
}
 
-   dev_addr = dir == DMA_DEV_TO_MEM
-? rchan->src.slave_addr : rchan->dst.slave_addr;
-   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, dev_addr,
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
+   return rcar_dmac_chan_prep_sg(rchan, sgl, sg_len, rchan->map.addr,
  dir, flags, false);
 }
 
@@ -1059,7 +1125,6 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
struct rcar_dmac_chan *rchan = to_rcar_dmac_chan(chan);
struct dma_async_tx_descriptor *desc;
struct scatterlist *sgl;
-   dma_addr_t dev_addr;
unsigned int sg_len;
unsigned int i;
 
@@ -1071,6 +1136,9 @@ rcar_dmac_prep_dma_cyclic(struct dma_chan *chan, 
dma_addr_t buf_addr,
return NULL;
}
 
+   if (rcar_dmac_map_slave_addr(chan, dir))
+   return NULL;
+
sg_len = buf_len / period_len;
if (sg_len > RCAR_DMAC_MAX_SG_LEN) {
dev_err(chan->device->dev,
@@ -1098,9 +1166,7 @@ 

[PATCHv6 7/8] ARM: dts: r8a7790: add iommus to dmac0 and dmac1

2016-05-09 Thread Niklas Söderlund
A unconfirmed hardware bug prevents channel 0 and 15 to be used by the
DMAC together with the IPMMU. The DMAC driver will disable the channels
reducing the effective number of channels to 14 per DMAC.

Signed-off-by: Niklas Söderlund 
Acked-by: Laurent Pinchart 
---
 arch/arm/boot/dts/r8a7790.dtsi | 30 ++
 1 file changed, 30 insertions(+)

diff --git a/arch/arm/boot/dts/r8a7790.dtsi b/arch/arm/boot/dts/r8a7790.dtsi
index 404ef2b..2912320 100644
--- a/arch/arm/boot/dts/r8a7790.dtsi
+++ b/arch/arm/boot/dts/r8a7790.dtsi
@@ -336,6 +336,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 0>,
+<_ds 1>,
+<_ds 2>,
+<_ds 3>,
+<_ds 4>,
+<_ds 5>,
+<_ds 6>,
+<_ds 7>,
+<_ds 8>,
+<_ds 9>,
+<_ds 10>,
+<_ds 11>,
+<_ds 12>,
+<_ds 13>,
+<_ds 14>;
};
 
dmac1: dma-controller@e672 {
@@ -367,6 +382,21 @@
power-domains = <_clocks>;
#dma-cells = <1>;
dma-channels = <15>;
+   iommus = <_ds 15>,
+<_ds 16>,
+<_ds 17>,
+<_ds 18>,
+<_ds 19>,
+<_ds 20>,
+<_ds 21>,
+<_ds 22>,
+<_ds 23>,
+<_ds 24>,
+<_ds 25>,
+<_ds 26>,
+<_ds 27>,
+<_ds 28>,
+<_ds 29>;
};
 
audma0: dma-controller@ec70 {
-- 
2.8.2

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

[PATCHv6 3/8] dma-mapping: add dma_{map,unmap}_resource

2016-05-09 Thread Niklas Söderlund
Map/Unmap a device MMIO resource from a physical address. If no dma_map_ops
method is available the operation is a no-op.

Signed-off-by: Niklas Söderlund 
---
 Documentation/DMA-API.txt   | 22 +-
 include/linux/dma-mapping.h | 36 
 2 files changed, 53 insertions(+), 5 deletions(-)

diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
index 45ef3f2..c7e5f99 100644
--- a/Documentation/DMA-API.txt
+++ b/Documentation/DMA-API.txt
@@ -277,14 +277,26 @@ and  parameters are provided to do partial page 
mapping, it is
 recommended that you never use these unless you really know what the
 cache width is.
 
+dma_addr_t
+dma_map_resource(struct device *dev, phys_addr_t phys_addr, size_t size,
+enum dma_data_direction dir, struct dma_attrs *attrs)
+
+void
+dma_unmap_resource(struct device *dev, dma_addr_t addr, size_t size,
+  enum dma_data_direction dir, struct dma_attrs *attrs)
+
+API for mapping and unmapping for MMIO resources. All the notes and
+warnings for the other mapping APIs apply here. The API should only be
+used to map device MMIO resources, mapping of RAM is not permitted.
+
 int
 dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
 
-In some circumstances dma_map_single() and dma_map_page() will fail to create
-a mapping. A driver can check for these errors by testing the returned
-DMA address with dma_mapping_error(). A non-zero return value means the mapping
-could not be created and the driver should take appropriate action (e.g.
-reduce current DMA mapping usage or delay and try again later).
+In some circumstances dma_map_single(), dma_map_page() and dma_map_resource()
+will fail to create a mapping. A driver can check for these errors by testing
+the returned DMA address with dma_mapping_error(). A non-zero return value
+means the mapping could not be created and the driver should take appropriate
+action (e.g. reduce current DMA mapping usage or delay and try again later).
 
int
dma_map_sg(struct device *dev, struct scatterlist *sg,
diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 8617fa1..dd228ce 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -218,6 +218,42 @@ static inline void dma_unmap_page(struct device *dev, 
dma_addr_t addr,
debug_dma_unmap_page(dev, addr, size, dir, false);
 }
 
+static inline dma_addr_t dma_map_resource(struct device *dev,
+ phys_addr_t phys_addr,
+ size_t size,
+ enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+   unsigned long pfn = __phys_to_pfn(phys_addr);
+   dma_addr_t addr;
+
+   BUG_ON(!valid_dma_direction(dir));
+
+   /* Don't allow RAM to be mapped */
+   BUG_ON(pfn_valid(pfn));
+
+   addr = phys_addr;
+   if (ops->map_resource)
+   addr = ops->map_resource(dev, phys_addr, size, dir, attrs);
+
+   debug_dma_map_resource(dev, phys_addr, size, dir, addr);
+
+   return addr;
+}
+
+static inline void dma_unmap_resource(struct device *dev, dma_addr_t addr,
+ size_t size, enum dma_data_direction dir,
+ struct dma_attrs *attrs)
+{
+   struct dma_map_ops *ops = get_dma_ops(dev);
+
+   BUG_ON(!valid_dma_direction(dir));
+   if (ops->unmap_resource)
+   ops->unmap_resource(dev, addr, size, dir, attrs);
+   debug_dma_unmap_resource(dev, addr, size, dir);
+}
+
 static inline void dma_sync_single_for_cpu(struct device *dev, dma_addr_t addr,
   size_t size,
   enum dma_data_direction dir)
-- 
2.8.2

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

[PATCHv6 2/8] dma-debug: add support for resource mappings

2016-05-09 Thread Niklas Söderlund
A MMIO mapped resource can not be represented by a struct page so a new
debug type is needed to handle this. This patch add such type and
functionality to add/remove entries and how to translate them to a
physical address.

Signed-off-by: Niklas Söderlund 
---
 include/linux/dma-debug.h | 19 +
 lib/dma-debug.c   | 52 +--
 2 files changed, 69 insertions(+), 2 deletions(-)

diff --git a/include/linux/dma-debug.h b/include/linux/dma-debug.h
index fe8cb61..c7d844f 100644
--- a/include/linux/dma-debug.h
+++ b/include/linux/dma-debug.h
@@ -56,6 +56,13 @@ extern void debug_dma_alloc_coherent(struct device *dev, 
size_t size,
 extern void debug_dma_free_coherent(struct device *dev, size_t size,
void *virt, dma_addr_t addr);
 
+extern void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+  size_t size, int direction,
+  dma_addr_t dma_addr);
+
+extern void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+size_t size, int direction);
+
 extern void debug_dma_sync_single_for_cpu(struct device *dev,
  dma_addr_t dma_handle, size_t size,
  int direction);
@@ -141,6 +148,18 @@ static inline void debug_dma_free_coherent(struct device 
*dev, size_t size,
 {
 }
 
+static inline void debug_dma_map_resource(struct device *dev, phys_addr_t addr,
+ size_t size, int direction,
+ dma_addr_t dma_addr)
+{
+}
+
+static inline void debug_dma_unmap_resource(struct device *dev,
+   dma_addr_t dma_addr, size_t size,
+   int direction)
+{
+}
+
 static inline void debug_dma_sync_single_for_cpu(struct device *dev,
 dma_addr_t dma_handle,
 size_t size, int direction)
diff --git a/lib/dma-debug.c b/lib/dma-debug.c
index 4a1515f..fb12d5c 100644
--- a/lib/dma-debug.c
+++ b/lib/dma-debug.c
@@ -43,6 +43,7 @@ enum {
dma_debug_page,
dma_debug_sg,
dma_debug_coherent,
+   dma_debug_resource,
 };
 
 enum map_err_types {
@@ -150,8 +151,9 @@ static const char *const maperr2str[] = {
[MAP_ERR_CHECKED] = "dma map error checked",
 };
 
-static const char *type2name[4] = { "single", "page",
-   "scather-gather", "coherent" };
+static const char *type2name[5] = { "single", "page",
+   "scather-gather", "coherent",
+   "resource" };
 
 static const char *dir2name[4] = { "DMA_BIDIRECTIONAL", "DMA_TO_DEVICE",
   "DMA_FROM_DEVICE", "DMA_NONE" };
@@ -397,6 +399,9 @@ static void hash_bucket_del(struct dma_debug_entry *entry)
 
 static unsigned long long phys_addr(struct dma_debug_entry *entry)
 {
+   if (entry->type == dma_debug_resource)
+   return PHYS_PFN(entry->pfn) + entry->offset;
+
return page_to_phys(pfn_to_page(entry->pfn)) + entry->offset;
 }
 
@@ -1493,6 +1498,49 @@ void debug_dma_free_coherent(struct device *dev, size_t 
size,
 }
 EXPORT_SYMBOL(debug_dma_free_coherent);
 
+void debug_dma_map_resource(struct device *dev, phys_addr_t addr, size_t size,
+   int direction, dma_addr_t dma_addr)
+{
+   struct dma_debug_entry *entry;
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   entry = dma_entry_alloc();
+   if (!entry)
+   return;
+
+   entry->type = dma_debug_resource;
+   entry->dev  = dev;
+   entry->pfn  = __phys_to_pfn(addr);
+   entry->offset   = addr - PHYS_PFN(entry->pfn);
+   entry->size = size;
+   entry->dev_addr = dma_addr;
+   entry->direction= direction;
+   entry->map_err_type = MAP_ERR_NOT_CHECKED;
+
+   add_dma_entry(entry);
+}
+EXPORT_SYMBOL(debug_dma_map_resource);
+
+void debug_dma_unmap_resource(struct device *dev, dma_addr_t dma_addr,
+ size_t size, int direction)
+{
+   struct dma_debug_entry ref = {
+   .type   = dma_debug_resource,
+   .dev= dev,
+   .dev_addr   = dma_addr,
+   .size   = size,
+   .direction  = direction,
+   };
+
+   if (unlikely(dma_debug_disabled()))
+   return;
+
+   check_unmap();
+}
+EXPORT_SYMBOL(debug_dma_unmap_resource);
+
 void debug_dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle,
   size_t size, int direction)
 {
-- 
2.8.2


[PATCHv6 0/8] dmaengine: rcar-dmac: add iommu support for slave transfers

2016-05-09 Thread Niklas Söderlund
Hi,

This series tries to solve the problem with DMA with device registers
(MMIO registers) that are behind an IOMMU for the rcar-dmac driver. A
recent patch '9575632 (dmaengine: make slave address physical)'
clarifies that DMA slave address provided by clients is the physical
address. This puts the task of mapping the DMA slave address from a
phys_addr_t to a dma_addr_t on the DMA engine.

Without an IOMMU this is easy since the phys_addr_t and dma_addr_t are
the same and no special care is needed. However if you have a IOMMU you
need to map the DMA slave phys_addr_t to a dma_addr_t using something
like this.

This series is based on top of and requires the patches from Robin
Murphy in the tag 'arm/io-pgtable' from the iommu repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu.git

It's tested on a Koelsch with CONFIG_IPMMU_VMSA and by enabling the
ipmmu_ds node in r8a7791.dtsi. I verified operation by interacting with
/dev/mmcblk1 and the serial console which both are devices behind the
iommu.

Furthermore I have audited to the best of my ability all call paths
involved to make sure that the dma_addr_t obtained from
dma_map_resource() to is not used in a way where it would be expected
for the mapping to be RAM (have a struct page). Many thanks to Christoph
Hellwig and Laurent Pinchart for there input in this effort.

  * drivers/dma/sh/rcar-dmac.c
Once the phys_addr_t is mapped to a dma_addr_t using
dma_map_resource() it is only used to check that the transferee do not
cross 4GB boundaries and then only directly written to HW registers.

  * drivers/iommu/iommu.c
- iommu_map()
  Check that it's align to min page size or return -EINVAL then calls
  domain->ops->map()

  * drivers/iommu/ipmmu-vmsa.c
- ipmmu_map()
  No logic only calls domain->ops->map()

  * drivers/iommu/io-pgtable-arm.c
- arm_lpae_map()
  No logic only calls __arm_lpae_map()
- __arm_lpae_map()
  No logic only calls arm_lpae_init_pte()
- arm_lpae_init_pte()
  Used to get a pte:
pte |= pfn_to_iopte(paddr >> data->pg_shift, data);

  * drivers/iommu/io-pgtable-arm-v7s.c
- arm_v7s_map()
  No logic only calls __arm_v7s_map()
- __arm_v7s_map()
  No logic only calls arm_v7s_init_pte()
- arm_v7s_init_pte
  Used to get a pte:
pte |= paddr & ARM_V7S_LVL_MASK(lvl);

  * ARM dma-mapping
- dma_unmap_*
  Only valid unmap is dma_unmap_resource() all others are an invalid
  use case.
- dma_sync_single_*
  Invalid use case, memory that is mapped is device memory
- dma_common_mmap() and dma_mmap_attrs()
  Invalid use case
- dma_common_get_sgtable() and dma_get_sgtable_attrs()
  Invalid use case, only for dma_alloc_* allocated memory,
- dma_mapping_error()
  OK

While working on the dma-debug parts of this series I found an unrelated
issue with drivers/iommu/io-pgtable-arm.c and CONFIG_DMA_API_DEBUG on
the Koelsch. I tried to address this in the thread
https://lkml.org/lkml/2016/5/8/33 , however it turned out my solution
was not the correct one. I have not tried to address this further so
running this series with CONFIG_DMA_API_DEBUG will trigger this warning
but is unrelated to this work.

* Changes since v5
- Add dma-debug work which adds a new mapping type for the resource
  mapping which correctly can be translated to a physical address.
- Drop patches from Robin Murphy since they now are accepted in the
  iommu repository and base the series on that tree instead.
- Add a review tag from Laurent.

* Changes since v4
- Move the mapping from phys_addr_t to dma_addr_t from slave_config to the
  prepare calls. This way we know the direction of the mapping and don't have
  to use DMA_BIDIRECTIONAL. Thanks Vinod for suggesting this.
- To be clear that the data type for slave addresses are changed add a patch
  that only changes the data type to phys_addr_t.
- Fixed up commit messages.

* Changes since v3
- Folded in a fix from Robin to his patch.
- Added a check to make sure dma_map_resource can not be used to map RAM as
  pointed out by Robin. I use BUG_ON to enforce this. It might not be the best
  method but I saw no other good way since DMA_ERROR_CODE might not be defined
  on all platforms.
- Added comment about that DTS changes will disable 2 DMA channels due to a HW
  (?) but in the DMAC.
- Dropped the use of dma_attrs, no longer needed.
- Collected Acked-by and Reviewed-by from Laurent.
- Various indentation fix ups.

* Changes since v2
- Drop patch to add dma_{map,unmap}_page_attrs.
- Add dma_{map,unmap}_resource to handle the mapping without involving a
  'struct page'. Thanks Laurent and Robin for pointing this out.
- Use size instead of address to keep track of if a mapping exist or not
  since addr == 0 is valid. Thanks Laurent.
- Pick up patch from Robin with Laurents ack (hope it's OK for me to
  attach the ack?) to add IOMMU_MMIO.
- Fix bug in rcar_dmac_device_config where the error 

[PATCHv6 1/8] dma-mapping: add {map,unmap}_resource to dma_map_ops

2016-05-09 Thread Niklas Söderlund
Add methods to handle mapping of device resources from a physical
address. This is needed for example to be able to map MMIO FIFO
registers to a IOMMU.

Signed-off-by: Niklas Söderlund 
Reviewed-by: Laurent Pinchart 
---
 include/linux/dma-mapping.h | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/include/linux/dma-mapping.h b/include/linux/dma-mapping.h
index 0e4d3a6..8617fa1 100644
--- a/include/linux/dma-mapping.h
+++ b/include/linux/dma-mapping.h
@@ -49,6 +49,12 @@ struct dma_map_ops {
 struct scatterlist *sg, int nents,
 enum dma_data_direction dir,
 struct dma_attrs *attrs);
+   dma_addr_t (*map_resource)(struct device *dev, phys_addr_t phys_addr,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
+   void (*unmap_resource)(struct device *dev, dma_addr_t dma_handle,
+  size_t size, enum dma_data_direction dir,
+  struct dma_attrs *attrs);
void (*sync_single_for_cpu)(struct device *dev,
dma_addr_t dma_handle, size_t size,
enum dma_data_direction dir);
-- 
2.8.2

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

[PATCH v2] iommu/arm-smmu: Use per-domain page sizes.

2016-05-09 Thread Robin Murphy
Now that we can accurately reflect the context format we choose for each
domain, do that instead of imposing the global lowest-common-denominator
restriction and potentially ending up with nothing. We currently have a
strict 1:1 correspondence between domains and context banks, so we don't
need to entertain the possibility of multiple formats _within_ a domain.

Signed-off-by: Will Deacon 
[rm: split from original patch, added SMMUv3]
Signed-off-by: Robin Murphy 
---

Changes from v1: Rebased onto iommu/core to accommodate SMMUv2 changes.

 drivers/iommu/arm-smmu-v3.c | 19 ++-
 drivers/iommu/arm-smmu.c| 27 +++
 2 files changed, 25 insertions(+), 21 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4ff73ff64e49..ebab33e77d67 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -590,6 +590,7 @@ struct arm_smmu_device {
 
unsigned long   ias; /* IPA */
unsigned long   oas; /* PA */
+   unsigned long   pgsize_bitmap;
 
 #define ARM_SMMU_MAX_ASIDS (1 << 16)
unsigned intasid_bits;
@@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct 
arm_smmu_domain *smmu_domain,
return 0;
 }
 
-static struct iommu_ops arm_smmu_ops;
-
 static int arm_smmu_domain_finalise(struct iommu_domain *domain)
 {
int ret;
@@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain 
*domain)
}
 
pgtbl_cfg = (struct io_pgtable_cfg) {
-   .pgsize_bitmap  = arm_smmu_ops.pgsize_bitmap,
+   .pgsize_bitmap  = smmu->pgsize_bitmap,
.ias= ias,
.oas= oas,
.tlb= _smmu_gather_ops,
@@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct iommu_domain 
*domain)
if (!pgtbl_ops)
return -ENOMEM;
 
-   arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+   domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
smmu_domain->pgtbl_ops = pgtbl_ops;
 
ret = finalise_stage_fn(smmu_domain, _cfg);
@@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct arm_smmu_device 
*smmu)
 {
u32 reg;
bool coherent;
-   unsigned long pgsize_bitmap = 0;
 
/* IDR0 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct arm_smmu_device 
*smmu)
 
/* Page sizes */
if (reg & IDR5_GRAN64K)
-   pgsize_bitmap |= SZ_64K | SZ_512M;
+   smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
if (reg & IDR5_GRAN16K)
-   pgsize_bitmap |= SZ_16K | SZ_32M;
+   smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
if (reg & IDR5_GRAN4K)
-   pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
+   smmu->pgsize_bitmap |= SZ_4K | SZ_2M | SZ_1G;
 
-   arm_smmu_ops.pgsize_bitmap &= pgsize_bitmap;
+   if (arm_smmu_ops.pgsize_bitmap == -1UL)
+   arm_smmu_ops.pgsize_bitmap = smmu->pgsize_bitmap;
+   else
+   arm_smmu_ops.pgsize_bitmap |= smmu->pgsize_bitmap;
 
/* Output address size */
switch (reg & IDR5_OAS_MASK << IDR5_OAS_SHIFT) {
diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 7cd4ad98904a..0360919a5737 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -351,6 +351,7 @@ struct arm_smmu_device {
unsigned long   va_size;
unsigned long   ipa_size;
unsigned long   pa_size;
+   unsigned long   pgsize_bitmap;
 
u32 num_global_irqs;
u32 num_context_irqs;
@@ -396,8 +397,6 @@ struct arm_smmu_domain {
struct iommu_domain domain;
 };
 
-static struct iommu_ops arm_smmu_ops;
-
 static DEFINE_SPINLOCK(arm_smmu_devices_lock);
 static LIST_HEAD(arm_smmu_devices);
 
@@ -957,7 +956,7 @@ static int arm_smmu_init_domain_context(struct iommu_domain 
*domain,
}
 
pgtbl_cfg = (struct io_pgtable_cfg) {
-   .pgsize_bitmap  = arm_smmu_ops.pgsize_bitmap,
+   .pgsize_bitmap  = smmu->pgsize_bitmap,
.ias= ias,
.oas= oas,
.tlb= _smmu_gather_ops,
@@ -971,8 +970,8 @@ static int arm_smmu_init_domain_context(struct iommu_domain 
*domain,
goto out_clear_smmu;
}
 
-   /* Update our support page sizes to reflect the page table format */
-   arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+   /* Update the domain's page sizes to reflect the page table format */
+   domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
 
/* Initialise the context bank 

Re: [PATCH] iommu/amd: Set AMD iommu callbacks for platform bus driver

2016-05-09 Thread Joerg Roedel
On Mon, May 09, 2016 at 08:17:12PM +0800, Wan Zongshun wrote:
> Currently, Only New eMMC driver will rely on this sdhci-acpi.c, but
> I could not find a suitable ifdef XXX micro to limit this
> platform_bus_type here like AMBA bus type before.
> 
> Do you think this MMC_SDHCI_ACPI is ok?

Okay, looks like platform_bus_type does not depend on any config-symbol.
So the patch is fine, but please add a comment why the iommu-ops are
needed on the platform bus.


Joerg

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


Re: [PATCH 0/5] Introduce per-domain page sizes

2016-05-09 Thread Joerg Roedel
On Mon, May 09, 2016 at 04:18:39PM +0100, Robin Murphy wrote:
> Bah, I saw last week's "Merge remote-tracking branch
> 'will/for-joerg/arm-smmu/updates' into HEAD" commit on that branch
> without spotting it was no longer up to date, sorry. Yes, it's
> probably safest if I rebase on top of your merge of everything else
> - I'll keep an eye out.

My tree is pushed now, you can rebase this one patch on the core branch
and resend.


Thanks,

Joerg

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


Re: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 2/3: msi changes

2016-05-09 Thread Chalamarla, Tirumalesh





On 5/9/16, 12:48 AM, "Eric Auger"  wrote:

>Hi Chalarmala,
>On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
>> Hi Eric,
>> 
>> Does this series supports gicv3-its emulation?
>> Do we have a tree with all the dependent patches
>GICv3 ITS emulation support comes with:
>[PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
>http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738
>
>My series just allows PCI device MSI transactions to reach the host MSI
>frame through the SMMU. Only host GICv2m has been tested at the moment
>with a guest exposed with a GICv2m too.


I wanted to test this series on Cavium Thunder, but the only mode supported is 
Gicv3 with ITS, is there a chance 
That I get a tree with all the dependencies?
>
>Best Regards
>
>Eric
>
>
>> 
>> 
>> 
>> 
>> 
>> Thanks,
>> Tirumalesh. 
>> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" 
>> > eric.au...@linaro.org> wrote:
>> 
>>> This series implements the MSI address mapping/unmapping in the MSI layer.
>>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>>> are not allowed to sleep, we simply look for the already existing binding.
>>>
>>> A new MSI domain info flag value is introduced to report whether the msi
>>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>>> advertising it. This flag value will be used by VFIO subsystem to
>>> determine whether MSI forwarding is safe.
>>>
>>> More details & context can be found at:
>>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>>
>>> Best Regards
>>>
>>> Eric
>>>
>>> Applies on top of PART 1/3. Also depends on
>>> [PATCH 1/3] iommu: Add MMIO mapping type,
>>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>>
>>> Git: complete series available at
>>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>>
>>> This branch contains all parts in v9.
>>>
>>> History:
>>>
>>> v8 -> v9:
>>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>>  doorbell is percpu
>>> - decouple irq_data parsing from the actual mapping/unmapping in
>>>  msi_handle_doorbell_mappings
>>> - fix misc style issues
>>>
>>> v7 -> v8:
>>> take into account Marc's comments:
>>> - use iommu_msi_msg_pa_to_va with new proto
>>> - change in irq_chip_msi_doorbell_info struct definition:
>>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>>> - cleanups in v2m irqchip
>>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>>  can be found
>>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>>
>>> v6 -> v7:
>>> - do alloc/map handling on pci_enable_msi and search on 
>>> msi_(de)domain_activate
>>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>>  of doorbells
>>>
>>> RFC v5 -> patch v6:
>>> - split to ease the review process
>>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>>  checks IOMMU_DOMAIN_DMA type)
>>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>>  unmap the previous doorbell when the new one has been mapped & written to
>>>  the device, ie. irq_chip_write_msi_msg.
>>> - "msi: msi_compose wrapper removed" following change above
>>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>>
>>> RFC v4 -> RFC v5:
>>> - take into account Thomas' comments on MSI related patches
>>>  - split "msi: IOMMU map the doorbell address when needed"
>>>  - increase readability and add comments
>>>  - fix style issues
>>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>>> - fix compilation issue with CONFIG_IOMMU API unset
>>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>>
>>> RFC v3 -> v4:
>>> - Move doorbell mapping/unmapping in msi.c
>>> - fix ref count issue on set_affinity: in case of a change in the address
>>>  the previous address is decremented
>>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>>  case for platform MSI controllers
>>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>>  to reserved IOVA management (looking like dma-iommu glue)
>>> - series reordering to ease the review:
>>>  - first part is related to IOMMU
>>>  - second related to MSI sub-system
>>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>>   size/alignment problematic - which I did not ignore - but I don't know
>>>   how much I can do at the moment]
>>>
>>> RFC v2 

Re: [PATCH 0/5] Introduce per-domain page sizes

2016-05-09 Thread Robin Murphy

On 09/05/16 15:51, Joerg Roedel wrote:

On Mon, May 09, 2016 at 12:45:39PM +0100, Robin Murphy wrote:

Thanks a lot! I was expecting to pick this up again after the merge
window and post an updated version then; as you may already have
found, patch 5 conflicts somewhat with the SMMUv2 context format
changes in Will's updates branch. The correct resolution requires a
bit of rewriting, so below is what that patch looks like when
rebased on top of Will's branch. If you'd prefer it in actual merge
resolution format, shout and I'll give that a go.


Okay, hmm, but the patch does not apply here, even after fixing the line
breaks. I'll push my tree soon, can you rebase this patch on-top the
core branch then? It should already contain patches 1-4.


Bah, I saw last week's "Merge remote-tracking branch 
'will/for-joerg/arm-smmu/updates' into HEAD" commit on that branch 
without spotting it was no longer up to date, sorry. Yes, it's probably 
safest if I rebase on top of your merge of everything else - I'll keep 
an eye out.


Thanks,
Robin.




Joerg



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


Re: [RFC PATCH v1 00/18] x86: Secure Memory Encryption (AMD)

2016-05-09 Thread Paolo Bonzini


On 02/05/2016 20:31, Andy Lutomirski wrote:
> And did the SEV implementation remember to encrypt the guest register
> state?  Because, if not, everything of importance will leak out
> through the VMCB and/or GPRs.

No, it doesn't.  And SEV is very limited unless you paravirtualize
everything.

For example, the hypervisor needs to read some instruction bytes from
memory, and instruction bytes are always encrypted (15.34.5 in the APM).
 So you're pretty much restricted to IN/OUT operations (not even
INS/OUTS) on emulated (non-assigned) devices, paravirtualized MSRs, and
hypercalls.  These are the only operations that connect the guest and
the hypervisor, where the vmexit doesn't have the need to e.g. walk
guest page tables (also always encrypted).  It possibly can be made to
work once the guest boots, and a modern UEFI firmware probably can cope
with it too just like a kernel can, but you need to ensure that your
hardware has no memory BARs for example.  And I/O port space is not very
abundant.

Even in order to emulate I/O ports or RDMSR/WRMSR or process hypercalls,
the hypervisor needs to read the GPRs.  The VMCB doesn't store guest
GPRs, not even on SEV-enabled processors.  Accordingly, the hypervisor
has access to the guest GPRs on every exit.

In general, SEV provides mitigation only.  Even if the hypervisor cannot
write known plaintext directly to memory, an accomplice virtual machine
can e.g. use the network to spray the attacked VM's memory.  At least
it's not as easy as "disable NX under the guest's feet and redirect RIP"
(pte.nx is reserved if efer.nxe=0, all you get is a #PF).  But the
hypervisor can still disable SMEP and SMAP, it can use hardware
breakpoints to leak information through the registers, and it can do all
the other attacks you mentioned.  If AMD had rdrand/rdseed, it could
replace the output with not so random values, and so on.

It's surely better than nothing, but "encryption that really is nothing
more than mitigation" is pretty weird.  I'm waiting for cloud vendors to
sell this as the best thing since sliced bread, when in reality it's
just mitigation.  I wonder how wise it is to merge SEV in its current
state---and since security is not my specialty I am definitely looking
for advice on this.

Paolo

ps: I'm now reminded of this patch:

commit dab429a798a8ab3377136e09dda55ea75a41648d
Author: David Kaplan 
Date:   Mon Mar 2 13:43:37 2015 -0600

kvm: svm: make wbinvd faster

No need to re-decode WBINVD since we know what it is from the
intercept.

Signed-off-by: David Kaplan 
[extracted from larger unlrelated patch, forward ported,
 tested,style cleanup]
Signed-off-by: Joel Schopp 
Reviewed-by: Radim Krčmář 
Signed-off-by: Marcelo Tosatti 

and I wonder if the larger unlrelated patch had anything to do with SEV!
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu

Re: [PATCH 0/5] Introduce per-domain page sizes

2016-05-09 Thread Joerg Roedel
On Mon, May 09, 2016 at 12:45:39PM +0100, Robin Murphy wrote:
> Thanks a lot! I was expecting to pick this up again after the merge
> window and post an updated version then; as you may already have
> found, patch 5 conflicts somewhat with the SMMUv2 context format
> changes in Will's updates branch. The correct resolution requires a
> bit of rewriting, so below is what that patch looks like when
> rebased on top of Will's branch. If you'd prefer it in actual merge
> resolution format, shout and I'll give that a go.

Okay, hmm, but the patch does not apply here, even after fixing the line
breaks. I'll push my tree soon, can you rebase this patch on-top the
core branch then? It should already contain patches 1-4.


Joerg

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


Re: [PATCH 0/5] Introduce per-domain page sizes

2016-05-09 Thread Robin Murphy

Hi Joerg,

On 09/05/16 12:21, Joerg Roedel wrote:

On Thu, Apr 07, 2016 at 06:42:03PM +0100, Robin Murphy wrote:

Hi all,

Since this area seems to be in vogue at the moment, here's what I was
working on when the related patches[1][2] popped up, which happens to
be more or less the intersection of both. As I recycled some of Will's
old series as a starting point, I've retained the cleanup patches from
that with their original acks - hope that's OK.

Fortunately, this already looks rather like parts of Joerg's plan[3],
so I hope it's a suitable first step. Below is a quick hacked-up example
of the kind of caller-controlled special use-case alluded to, using the
SMMU/HDLCD combo on Juno - for a 'real' implementation of this we'd want
the group-based domain allocation call so the driver could throw the
device at that and get its own non-default DMA ops domain to play with.

Robin.

[1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12774
[2]:http://thread.gmane.org/gmane.linux.kernel.iommu/12901
[3]:http://article.gmane.org/gmane.linux.kernel.iommu/12937

Robin Murphy (4):
   iommu: of: enforce const-ness of struct iommu_ops
   iommu: Allow selecting page sizes per domain
   iommu/dma: Finish optimising higher-order allocations
   iommu/arm-smmu: Use per-domain page sizes.

Will Deacon (1):
   iommu: remove unused priv field from struct iommu_ops


Okay, I am still no happy that this lifts the requirements of the
iommu-api for the arm-smmu driver. But to get there we need more core
changes and this code is a step in the right direction, so I applied it.


Thanks a lot! I was expecting to pick this up again after the merge 
window and post an updated version then; as you may already have found, 
patch 5 conflicts somewhat with the SMMUv2 context format changes in 
Will's updates branch. The correct resolution requires a bit of 
rewriting, so below is what that patch looks like when rebased on top of 
Will's branch. If you'd prefer it in actual merge resolution format, 
shout and I'll give that a go.


Thanks,
Robin.

--->8---
commit a940dae4e124523bc1cf282c8f36c79f960a0805
Author: Robin Murphy 
Date:   Mon Mar 14 14:25:07 2016 +

iommu/arm-smmu: Use per-domain page sizes.

Now that we can accurately reflect the context format we choose for 
each
domain, do that instead of imposing the global 
lowest-common-denominator

restriction and potentially ending up with nothing. We currently have a
strict 1:1 correspondence between domains and context banks, so we 
don't
need to entertain the possibility of multiple formats _within_ a 
domain.


Signed-off-by: Will Deacon 
[rm: split from original patch, added SMMUv3]
Signed-off-by: Robin Murphy 

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 4ff73ff64e49..ebab33e77d67 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -590,6 +590,7 @@ struct arm_smmu_device {

unsigned long   ias; /* IPA */
unsigned long   oas; /* PA */
+   unsigned long   pgsize_bitmap;

 #define ARM_SMMU_MAX_ASIDS (1 << 16)
unsigned intasid_bits;
@@ -1516,8 +1517,6 @@ static int arm_smmu_domain_finalise_s2(struct 
arm_smmu_domain *smmu_domain,

return 0;
 }

-static struct iommu_ops arm_smmu_ops;
-
 static int arm_smmu_domain_finalise(struct iommu_domain *domain)
 {
int ret;
@@ -1555,7 +1554,7 @@ static int arm_smmu_domain_finalise(struct 
iommu_domain *domain)

}

pgtbl_cfg = (struct io_pgtable_cfg) {
-   .pgsize_bitmap  = arm_smmu_ops.pgsize_bitmap,
+   .pgsize_bitmap  = smmu->pgsize_bitmap,
.ias= ias,
.oas= oas,
.tlb= _smmu_gather_ops,
@@ -1566,7 +1565,7 @@ static int arm_smmu_domain_finalise(struct 
iommu_domain *domain)

if (!pgtbl_ops)
return -ENOMEM;

-   arm_smmu_ops.pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
+   domain->pgsize_bitmap = pgtbl_cfg.pgsize_bitmap;
smmu_domain->pgtbl_ops = pgtbl_ops;

ret = finalise_stage_fn(smmu_domain, _cfg);
@@ -2410,7 +2409,6 @@ static int arm_smmu_device_probe(struct 
arm_smmu_device *smmu)

 {
u32 reg;
bool coherent;
-   unsigned long pgsize_bitmap = 0;

/* IDR0 */
reg = readl_relaxed(smmu->base + ARM_SMMU_IDR0);
@@ -2541,13 +2539,16 @@ static int arm_smmu_device_probe(struct 
arm_smmu_device *smmu)


/* Page sizes */
if (reg & IDR5_GRAN64K)
-   pgsize_bitmap |= SZ_64K | SZ_512M;
+   smmu->pgsize_bitmap |= SZ_64K | SZ_512M;
if (reg & IDR5_GRAN16K)
-   pgsize_bitmap |= SZ_16K | SZ_32M;
+   smmu->pgsize_bitmap |= SZ_16K | SZ_32M;
if (reg & IDR5_GRAN4K)
-   pgsize_bitmap |= SZ_4K | 

Re: [PATCH V4 0/4] Code refine for Intel IOMMU

2016-05-09 Thread Joerg Roedel
On Sun, May 08, 2016 at 01:22:53PM +, Wei Yang wrote:
> >Wei Yang (4):
> >  iommu/vt-d: replace *hdr with {drhd/atsr}[0] in struct
> >dmar_{drhd/atsr}_unit
> >  iommu/vt-d: use zero-sized array in DMAR related ACPI structures
> >  iommu/vt-d: check Register Base Address at the beginning of
> >dmar_parse_one_drhd()
> >  iommu/vt-d: refine dmar_acpi_dev_scope_init() with
> >dmar_walk_dmar_table()

Okay, I've ignored this so far as I don't see where you are going with
this refactoring. The patches as-is don't make much sense to me other
than creating conflicts with other vt-d driver changes.



Joerg

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


Re: [PATCH 0/5] Introduce per-domain page sizes

2016-05-09 Thread Joerg Roedel
On Thu, Apr 07, 2016 at 06:42:03PM +0100, Robin Murphy wrote:
> Hi all,
> 
> Since this area seems to be in vogue at the moment, here's what I was
> working on when the related patches[1][2] popped up, which happens to
> be more or less the intersection of both. As I recycled some of Will's
> old series as a starting point, I've retained the cleanup patches from
> that with their original acks - hope that's OK.
> 
> Fortunately, this already looks rather like parts of Joerg's plan[3],
> so I hope it's a suitable first step. Below is a quick hacked-up example
> of the kind of caller-controlled special use-case alluded to, using the
> SMMU/HDLCD combo on Juno - for a 'real' implementation of this we'd want
> the group-based domain allocation call so the driver could throw the
> device at that and get its own non-default DMA ops domain to play with.
> 
> Robin.
> 
> [1]:http://thread.gmane.org/gmane.linux.kernel.iommu/12774
> [2]:http://thread.gmane.org/gmane.linux.kernel.iommu/12901
> [3]:http://article.gmane.org/gmane.linux.kernel.iommu/12937
> 
> Robin Murphy (4):
>   iommu: of: enforce const-ness of struct iommu_ops
>   iommu: Allow selecting page sizes per domain
>   iommu/dma: Finish optimising higher-order allocations
>   iommu/arm-smmu: Use per-domain page sizes.
> 
> Will Deacon (1):
>   iommu: remove unused priv field from struct iommu_ops

Okay, I am still no happy that this lifts the requirements of the
iommu-api for the arm-smmu driver. But to get there we need more core
changes and this code is a step in the right direction, so I applied it.

Thanks,

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


Re: [PATCH V2 RFC] fixup! virtio: convert to use DMA api

2016-05-09 Thread Paolo Bonzini


On 28/04/2016 17:37, Michael S. Tsirkin wrote:
> > All the internally-emulated devices *can* be either translated or
> > untranslated. That's just a matter of software. Surely, you currently
> > *can't* have translated assigned devices (until someone implements the
> > whole VT-d page table shadowing or whatever), so you'll be barred from
> > assigning a device to a slot which *previously* had an untranslated
> > device. But so what? Put it in a different slot instead.
> 
> Unfortunately people got used to be able to put any device
> in any slot, and built external tools around that ability.
> It's rather painful to break this assumption.

Once you move to PCIe, a lot of things become more complicated.  This is
just one of them; instead of needing half a dozen PCI bridges, you'll
need half a dozen plus one.

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


Re: [PATCH] iommu/amd: Set AMD iommu callbacks for platform bus driver

2016-05-09 Thread Joerg Roedel
On Thu, Apr 14, 2016 at 09:28:53AM -0400, Wan Zongshun wrote:
> From: Wan Zongshun 
> 
> AMD has more drivers will use ACPI to platform bus driver later,
> all those devices need iommu support, such as eMMC acpi driver.
> 
> Signed-off-by: Wan Zongshun 
> ---
>  drivers/iommu/amd_iommu.c | 4 
>  1 file changed, 4 insertions(+)
> 
> diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
> index c430c10..547cdd4 100644
> --- a/drivers/iommu/amd_iommu.c
> +++ b/drivers/iommu/amd_iommu.c
> @@ -21,6 +21,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -2980,6 +2981,9 @@ int __init amd_iommu_init_api(void)
>   if (err)
>   return err;
>  #endif
> + err = bus_set_iommu(_bus_type, _iommu_ops);
> + if (err)
> + return err;

Is the platform_bus_type always defined or does this code needs to be
guarded by another ifdef?



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


Re: [PATCH v2 1/2] PCI: Add PCI device flag PCI_DEV_FLAGS_DMA_ALIAS_ROOT

2016-05-09 Thread Robin Murphy

On 08/05/16 10:33, Jayachandran C via iommu wrote:

Add a new flag PCI_DEV_FLAGS_DMA_ALIAS_ROOT to limit the DMA alias
search to go no further than the bridge where the IOMMU is attached.

This has been added to support Broadcom's Vulcan which has the SMMUv3
and GIC ITS associated with an intermediate bridge in the PCI topology.
Traversing to buses above would hit internal glue bridges which will
change the RID.


Can you not just have the relevant callback function detect the relevant 
node and terminate the walk of its own accord? That's what I was aiming 
for in this patch for the IOMMU setup:


http://article.gmane.org/gmane.linux.kernel.iommu/12456

Is there some flaw in that approach I've missed?

Robin.


Update the function pci_for_each_dma_alias() to stop when it see a
bridge with this flag set.

Signed-off-by: Jayachandran C 
---

Here is v2 of the patch, the previous discussion is at
http://lists.linuxfoundation.org/pipermail/iommu/2016-February/015668.html

v1->v2 changes:
  - dropped the BAR quirk (not needed)
  - moved from using the 'skip' flag for some bridges to using
similar approach to stop the traversal at the bridge with
PCI_DEV_FLAGS_DMA_ALIAS_ROOT

Comments and suggestions are welcome

JC.

  drivers/pci/search.c | 4 
  include/linux/pci.h  | 2 ++
  2 files changed, 6 insertions(+)

diff --git a/drivers/pci/search.c b/drivers/pci/search.c
index a20ce7d..3ea9c27 100644
--- a/drivers/pci/search.c
+++ b/drivers/pci/search.c
@@ -56,6 +56,10 @@ int pci_for_each_dma_alias(struct pci_dev *pdev,

tmp = bus->self;

+   /* stop at bridge where translation unit is associated */
+   if (tmp->dev_flags & PCI_DEV_FLAGS_DMA_ALIAS_ROOT)
+   return ret;
+
/*
 * PCIe-to-PCI/X bridges alias transactions from downstream
 * devices using the subordinate bus number (PCI Express to
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 932ec74..b6f832b 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -176,6 +176,8 @@ enum pci_dev_flags {
PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
/* Get VPD from function 0 VPD */
PCI_DEV_FLAGS_VPD_REF_F0 = (__force pci_dev_flags_t) (1 << 8),
+   /* a non-root bridge where translation occurs, stop alias search here */
+   PCI_DEV_FLAGS_DMA_ALIAS_ROOT = (__force pci_dev_flags_t) (1 << 9),
  };

  enum pci_irq_reroute_variant {



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


Re: [PATCH 0/2] Fix incorrect warning from dma-debug

2016-05-09 Thread Robin Murphy

Hi Niklas,

On 08/05/16 11:59, Niklas Söderlund wrote:

Hi,

While using CONFIG_DMA_API_DEBUG i came across this warning which I
think is a false positive. As shown dma_sync_single_for_device() are
called from the dma_map_single() call path. This triggers the warning
since the dma-debug code have not yet been made aware of the mapping.


Almost right ;) The thing being mapped (the SPI device's buffer) and the 
thing being synced (the IOMMU's PTE) are entirely unrelated. Due to the 
current of_iommu_init() setup, the IOMMU is probed long before 
dma_debug_init() gets called, therefore DMA debug is missing entries for 
some of the initial page table mappings and gets confused when we update 
them later.



I try to solve this by introducing __dma_sync_single_for_device() which
do not call into the dma-debug code. I'm no expert and this might be a
bad way of solving the problem but it allowed me to keep working.


The simple fix should be to just call dma_debug_init() from a 
sufficiently earlier initcall level. The best would be to sort out a 
proper device dependency order to avoid the whole early-IOMMU-creation 
thing entirely.


Robin.


[ cut here ]
WARNING: CPU: 0 PID: 1 at lib/dma-debug.c:1209 check_sync+0x154/0x5e4
ipmmu-vmsa e674.mmu: DMA-API: device driver tries to sync DMA memory it has 
not allocated [device address=0x6e89b008] [size=8 bytes]
CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc5-00012-g52e78c1-dirty #1
Hardware name: Generic R8A7791 (Flattened Device Tree)
Backtrace:
[] (dump_backtrace) from [] (show_stack+0x18/0x1c)
  r7:c03ebad0 r6:0009 r5:6093 r4:
[] (show_stack) from [] (dump_stack+0x84/0xa4)
[] (dump_stack) from [] (__warn+0xd0/0x100)
  r5: r4:ef05dac8
[] (__warn) from [] (warn_slowpath_fmt+0x40/0x48)
  r9:0001 r8: r7:c0c69c40 r6:c0c02754 r5:ef05db78 r4:ef222810
[] (warn_slowpath_fmt) from [] (check_sync+0x154/0x5e4)
  r3:c0945b6f r2:c0936e85
[] (check_sync) from [] 
(debug_dma_sync_single_for_device+0x64/0x70)
  r10:0009 r9:000c r8:ee89b008 r7: r6:6e89b008 r5:
  r4:6e89b008
[] (debug_dma_sync_single_for_device) from [] 
(__arm_lpae_set_pte.part.0+0x80/0x8c)
  r5:0001 r4:ef222810
[] (__arm_lpae_set_pte.part.0) from [] 
(__arm_lpae_map+0x298/0x2f0)
  r7:0008 r6:ef25e000 r4:ee898500
[] (__arm_lpae_map) from [] (arm_lpae_map+0xcc/0xe4)
  r10:c0465f40 r9:1000 r8:4000 r7: r6:6f25c000 r5:
  r4:08c0
[] (arm_lpae_map) from [] (ipmmu_map+0x38/0x40)
  r7:4000 r6: r5:1000 r4:c0465a4c
[] (ipmmu_map) from [] (iommu_map+0xf8/0x15c)
  r4:ee895608
[] (iommu_map) from [] 
(arm_coherent_iommu_map_page+0x1d4/0x2d4)
  r10:ef386940 r9:1000 r8: r7: r6:4000 r5:
  r4:
[] (arm_coherent_iommu_map_page) from [] 
(arm_iommu_map_page+0x6c/0x74)
  r10:c0c61f44 r9:ef19d210 r8:0001 r7:1000 r6: r5:ec5ddb80
  r4:
[] (arm_iommu_map_page) from [] 
(sh_msiof_spi_probe+0x430/0x7b0)
  r9: r8:c0213624 r7:ef19d210 r6:ef242800 r5:ef1b4010 r4:ef242af0
[] (sh_msiof_spi_probe) from [] 
(platform_drv_probe+0x58/0xa8)
  r10: r9: r8:c0c1f8d4 r7:c0c7e910 r6:c0c1f8d4 r5:ef1b4010
  r4:c04f7934
[] (platform_drv_probe) from [] 
(driver_probe_device+0x13c/0x2a4)
  r7:c0c7e910 r6: r5:c0c7e900 r4:ef1b4010
[] (driver_probe_device) from [] (__driver_attach+0x88/0xac)
  r9:c0c34000 r8:c0a3c010 r7:c0c1cf08 r6:c0c1f8d4 r5:ef1b4044 r4:ef1b4010
[] (__driver_attach) from [] (bus_for_each_dev+0x74/0x98)
  r7:c0c1cf08 r6:c049e8f0 r5:c0c1f8d4 r4:
[] (bus_for_each_dev) from [] (driver_attach+0x20/0x28)
  r6:ef1cc200 r5: r4:c0c1f8d4
[] (driver_attach) from [] (bus_add_driver+0xd4/0x1e4)
[] (bus_add_driver) from [] (driver_register+0xa4/0xe8)
  r7:c0a3c010 r6: r5:c0a1e400 r4:c0c1f8d4
[] (driver_register) from [] 
(__platform_driver_register+0x38/0x4c)
  r5:c0a1e400 r4:ee958fc0
[] (__platform_driver_register) from [] 
(sh_msiof_spi_drv_init+0x18/0x20)
[] (sh_msiof_spi_drv_init) from [] 
(do_one_initcall+0x10c/0x1c0)
[] (do_one_initcall) from [] 
(kernel_init_freeable+0x128/0x1f4)
  r9:c0c34000 r8:c0c34000 r7:c0a47e60 r6:c0a3c83c r5:00bd r4:0006
[] (kernel_init_freeable) from [] (kernel_init+0x10/0x118)
  r9:[1.879529] ata1: link resume succeeded after 1 retries
  r8: r7: r6: r5:c071066c r4:
[] (kernel_init) from [] (ret_from_fork+0x14/0x2c)
  r5:c071066c r4:
---[ end trace 6eb9a3df3009d491 ]---

Niklas Söderlund (2):
   dma-mapping: add __dma_sync_single_for_device()
   iommu/io-pgtable-arm: use __dma_sync_single_for_device()

  drivers/iommu/io-pgtable-arm.c | 2 +-
  include/linux/dma-mapping.h| 9 -
  2 files changed, 9 insertions(+), 2 deletions(-)

--
2.8.2


___
linux-arm-kernel mailing list
linux-arm-ker...@lists.infradead.org

Re: [PATCH 2/2] iommu/io-pgtable-arm: use __dma_sync_single_for_device()

2016-05-09 Thread Will Deacon
On Sun, May 08, 2016 at 12:59:56PM +0200, Niklas Söderlund wrote:
> The call to dma_sync_single_for_device() can be reached from
> dma_map_single(). If CONFIG_DMA_API_DEBUG is enabled this would result
> in a check that the mapping being synced is valid. Since the call to
> dma_map_single is not yet completed the mapping is not recorded in
> dma-debug and the check fails and a warning is printed. Avoid this
> warning by calling __dma_sync_single_for_device() which don't preform
> this check.

Hmm, I don't understand why this would trigger that warning. The memory
being sync'd here is the page table memory, not the buffer being mapped.
The page table memory is "mapped" using dma_map_single in
__arm_lpae_alloc_pages, so it sounds like the issue something else.

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


Re: [PATCH v9 5/7] vfio/type1: also check IRQ remapping capability at msi domain

2016-05-09 Thread Eric Auger
Hi Chalamarla,
On 05/05/2016 09:23 PM, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" 
>  eric.au...@linaro.org> wrote:
> 
>> On x86 IRQ remapping is abstracted by the IOMMU. On ARM this is abstracted
>> by the msi controller. vfio_safe_irq_domain allows to check whether
>> interrupts are "safe" for a given device. They are if the device does
>> not use MSI or if the device uses MSI and the msi-parent controller
>> supports IRQ remapping.
>>
>> Then we check at group level if all devices have safe interrupts: if not,
>> we only allow the group to be attached if allow_unsafe_interrupts is set.
>>
>> At this point ARM sMMU still advertises IOMMU_CAP_INTR_REMAP. This is
>> changed in next patch.
> 
> Will this work in systems with multiple ITS?
Yes it should support multiple ITS.

Please note however that the series does not yet implement the
msi_doorbell_info callback in GICv3 ITS PCIe/platform irqchip. Without
that, the pci_enable is going to fail. I am going to submit a separate
RFC for that but I can't test it at the moment.

Best Regards

Eric
>>
>> Signed-off-by: Eric Auger 
>>
>> ---
>> v3 -> v4:
>> - rename vfio_msi_parent_irq_remapping_capable into vfio_safe_irq_domain
>>  and irq_remapping into safe_irq_domains
>>
>> v2 -> v3:
>> - protect vfio_msi_parent_irq_remapping_capable with
>>  CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> ---
>> drivers/vfio/vfio_iommu_type1.c | 44 
>> +++--
>> 1 file changed, 42 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c 
>> b/drivers/vfio/vfio_iommu_type1.c
>> index 4d3a6f1..2fc8197 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -37,6 +37,8 @@
>> #include 
>> #include 
>> #include 
>> +#include 
>> +#include 
>>
>> #define DRIVER_VERSION  "0.2"
>> #define DRIVER_AUTHOR   "Alex Williamson "
>> @@ -777,6 +779,33 @@ static int vfio_bus_type(struct device *dev, void *data)
>>  return 0;
>> }
>>
>> +/**
>> + * vfio_safe_irq_domain: returns whether the irq domain
>> + * the device is attached to is safe with respect to MSI isolation.
>> + * If the irq domain is not an MSI domain, we return it is safe.
>> + *
>> + * @dev: device handle
>> + * @data: unused
>> + * returns 0 if the irq domain is safe, -1 if not.
>> + */
>> +static int vfio_safe_irq_domain(struct device *dev, void *data)
>> +{
>> +#ifdef CONFIG_GENERIC_MSI_IRQ_DOMAIN
>> +struct irq_domain *domain;
>> +struct msi_domain_info *info;
>> +
>> +domain = dev_get_msi_domain(dev);
>> +if (!domain)
>> +return 0;
>> +
>> +info = msi_get_domain_info(domain);
>> +
>> +if (!(info->flags & MSI_FLAG_IRQ_REMAPPING))
>> +return -1;
>> +#endif
>> +return 0;
>> +}
>> +
>> static int vfio_iommu_replay(struct vfio_iommu *iommu,
>>   struct vfio_domain *domain)
>> {
>> @@ -870,7 +899,7 @@ static int vfio_iommu_type1_attach_group(void 
>> *iommu_data,
>>  struct vfio_group *group, *g;
>>  struct vfio_domain *domain, *d;
>>  struct bus_type *bus = NULL;
>> -int ret;
>> +int ret, safe_irq_domains;
>>
>>  mutex_lock(>lock);
>>
>> @@ -893,6 +922,13 @@ static int vfio_iommu_type1_attach_group(void 
>> *iommu_data,
>>
>>  group->iommu_group = iommu_group;
>>
>> +/*
>> + * Determine if all the devices of the group have a safe irq domain
>> + * with respect to MSI isolation
>> + */
>> +safe_irq_domains = !iommu_group_for_each_dev(iommu_group, ,
>> +   vfio_safe_irq_domain);
>> +
>>  /* Determine bus_type in order to allocate a domain */
>>  ret = iommu_group_for_each_dev(iommu_group, , vfio_bus_type);
>>  if (ret)
>> @@ -920,8 +956,12 @@ static int vfio_iommu_type1_attach_group(void 
>> *iommu_data,
>>  INIT_LIST_HEAD(>group_list);
>>  list_add(>next, >group_list);
>>
>> +/*
>> + * to advertise safe interrupts either the IOMMU or the MSI controllers
>> + * must support IRQ remapping/interrupt translation
>> + */
>>  if (!allow_unsafe_interrupts &&
>> -!iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
>> +(!iommu_capable(bus, IOMMU_CAP_INTR_REMAP) && !safe_irq_domains)) {
>>  pr_warn("%s: No interrupt remapping support.  Use the module 
>> param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this 
>> platform\n",
>> __func__);
>>  ret = -EPERM;
>> -- 
>> 1.9.1
>>
>>
>> ___
>> linux-arm-kernel mailing list
>> linux-arm-ker...@lists.infradead.org
>> http://lists.infradead.org/mailman/listinfo/linux-arm-kernel

___
iommu mailing list
iommu@lists.linux-foundation.org

[PATCH 4/5] iommu/mediatek: add support for mtk iommu generation one HW

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

Mediatek SoC's M4U have two generations of HW architcture. Generation one
use flat, one layer pagetable, and was shipped with ARM architecture, it
only support 4K size page mapping. MT2701 SoC use this generation one
m4u HW. Generation two uses the ARM short-descriptor translation table
format for address translation, and was shipped with ARM64 architecture,
MT8173 use this generation two m4u HW. All the two generation iommu HW
only have one iommu domain, and all it's iommu clients share the same
iova address.

These two generation m4u HW have slit different register groups and
register offset, but most register names are the same. This patch add iommu
support for mediatek SoC mt2701.

Signed-off-by: Honghui Zhang 
---
 drivers/iommu/Kconfig|  19 ++
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/mtk_iommu.h|   4 +
 drivers/iommu/mtk_iommu_v1.c | 767 +++
 4 files changed, 791 insertions(+)
 create mode 100644 drivers/iommu/mtk_iommu_v1.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index dd1dc39..2e17d70 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -354,4 +354,23 @@ config MTK_IOMMU
 
  If unsure, say N here.
 
+config MTK_IOMMU_V1
+   bool "MTK IOMMU Version 1 (M4U gen1) Support"
+   depends on ARM || ARM64
+   depends on ARCH_MEDIATEK || COMPILE_TEST
+   select ARM_DMA_USE_IOMMU
+   select IOMMU_API
+   select IOMMU_DMA
+   select MEMORY
+   select MTK_SMI
+   select COMMON_CLK_MT2701_MMSYS
+   select COMMON_CLK_MT2701_IMGSYS
+   select COMMON_CLK_MT2701_VDECSYS
+   help
+ Support for the M4U on certain Mediatek SoCs. M4U generation 1 HW is
+ Multimedia Memory Managememt Unit. This option enables remapping of
+ DMA memory accesses for the multimedia subsystem.
+
+ if unsure, say N here.
+
 endif # IOMMU_SUPPORT
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index c6edb31..778baf5 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -18,6 +18,7 @@ obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
 obj-$(CONFIG_IRQ_REMAP) += intel_irq_remapping.o irq_remapping.o
 obj-$(CONFIG_MTK_IOMMU) += mtk_iommu.o
+obj-$(CONFIG_MTK_IOMMU_V1) += mtk_iommu_v1.o
 obj-$(CONFIG_OMAP_IOMMU) += omap-iommu.o
 obj-$(CONFIG_OMAP_IOMMU_DEBUG) += omap-iommu-debug.o
 obj-$(CONFIG_ROCKCHIP_IOMMU) += rockchip-iommu.o
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
index 5656355..c894784 100644
--- a/drivers/iommu/mtk_iommu.h
+++ b/drivers/iommu/mtk_iommu.h
@@ -48,6 +48,10 @@ struct mtk_iommu_domain {
struct io_pgtable_ops   *iop;
 
struct iommu_domain domain;
+   size_t  pgt_size;
+   void*pgt_va;
+   dma_addr_t  pgt_pa;
+   void*cookie;
 };
 
 struct mtk_iommu_data {
diff --git a/drivers/iommu/mtk_iommu_v1.c b/drivers/iommu/mtk_iommu_v1.c
new file mode 100644
index 000..1fece92
--- /dev/null
+++ b/drivers/iommu/mtk_iommu_v1.c
@@ -0,0 +1,767 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include "mtk_iommu.h"
+
+#define REG_MMU_PT_BASE_ADDR   0x000
+
+#define F_ALL_INVLD0x2
+#define F_MMU_INV_RANGE0x1
+#define F_INVLD_EN0BIT(0)
+#define F_INVLD_EN1BIT(1)
+
+#define F_MMU_FAULT_VA_MSK 0xf000
+#define MTK_PROTECT_PA_ALIGN   128
+
+#define REG_MMU_CTRL_REG   0x210
+#define F_MMU_CTRL_COHERENT_EN BIT(8)
+#define REG_MMU_IVRP_PADDR 0x214
+#define REG_MMU_INT_CONTROL0x220
+#define F_INT_TRANSLATION_FAULTBIT(0)
+#define F_INT_MAIN_MULTI_HIT_FAULT BIT(1)
+#define F_INT_INVALID_PA_FAULT BIT(2)
+#define F_INT_ENTRY_REPLACEMENT_FAULT  BIT(3)
+#define F_INT_TABLE_WALK_FAULT 

[PATCH 2/5] iommu/mediatek: move the common struct into header file

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

Move the struct defines of mtk iommu into a new header files for
common use.

Signed-off-by: Honghui Zhang 
---
 drivers/iommu/mtk_iommu.c | 62 +---
 drivers/iommu/mtk_iommu.h | 90 +++
 2 files changed, 91 insertions(+), 61 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h

diff --git a/drivers/iommu/mtk_iommu.c b/drivers/iommu/mtk_iommu.c
index db74553..a6b7846 100644
--- a/drivers/iommu/mtk_iommu.c
+++ b/drivers/iommu/mtk_iommu.c
@@ -34,7 +34,7 @@
 #include 
 #include 
 
-#include "io-pgtable.h"
+#include "mtk_iommu.h"
 
 #define REG_MMU_PT_BASE_ADDR   0x000
 
@@ -93,49 +93,8 @@
 
 #define MTK_PROTECT_PA_ALIGN   128
 
-struct mtk_iommu_suspend_reg {
-   u32 standard_axi_mode;
-   u32 dcm_dis;
-   u32 ctrl_reg;
-   u32 int_control0;
-   u32 int_main_control;
-};
-
-struct mtk_iommu_client_priv {
-   struct list_headclient;
-   unsigned intmtk_m4u_id;
-   struct device   *m4udev;
-};
-
-struct mtk_iommu_domain {
-   spinlock_t  pgtlock; /* lock for page table */
-
-   struct io_pgtable_cfg   cfg;
-   struct io_pgtable_ops   *iop;
-
-   struct iommu_domain domain;
-};
-
-struct mtk_iommu_data {
-   void __iomem*base;
-   int irq;
-   struct device   *dev;
-   struct clk  *bclk;
-   phys_addr_t protect_base; /* protect memory base */
-   struct mtk_iommu_suspend_regreg;
-   struct mtk_iommu_domain *m4u_dom;
-   struct iommu_group  *m4u_group;
-   struct mtk_smi_iommusmi_imu;  /* SMI larb iommu info */
-   boolenable_4GB;
-};
-
 static struct iommu_ops mtk_iommu_ops;
 
-static struct mtk_iommu_domain *to_mtk_domain(struct iommu_domain *dom)
-{
-   return container_of(dom, struct mtk_iommu_domain, domain);
-}
-
 static void mtk_iommu_tlb_flush_all(void *cookie)
 {
struct mtk_iommu_data *data = cookie;
@@ -552,25 +511,6 @@ static int mtk_iommu_hw_init(const struct mtk_iommu_data 
*data)
return 0;
 }
 
-static int compare_of(struct device *dev, void *data)
-{
-   return dev->of_node == data;
-}
-
-static int mtk_iommu_bind(struct device *dev)
-{
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-   return component_bind_all(dev, >smi_imu);
-}
-
-static void mtk_iommu_unbind(struct device *dev)
-{
-   struct mtk_iommu_data *data = dev_get_drvdata(dev);
-
-   component_unbind_all(dev, >smi_imu);
-}
-
 static const struct component_master_ops mtk_iommu_com_ops = {
.bind   = mtk_iommu_bind,
.unbind = mtk_iommu_unbind,
diff --git a/drivers/iommu/mtk_iommu.h b/drivers/iommu/mtk_iommu.h
new file mode 100644
index 000..5656355
--- /dev/null
+++ b/drivers/iommu/mtk_iommu.h
@@ -0,0 +1,90 @@
+/*
+ * Copyright (c) 2015-2016 MediaTek Inc.
+ * Author: Yong Wu 
+ *   : Honghui Zhang 
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ */
+
+#ifndef _MTK_IOMMU_H_
+#define _MTK_IOMMU_H_
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#include "io-pgtable.h"
+
+struct mtk_iommu_suspend_reg {
+   u32 standard_axi_mode;
+   u32 dcm_dis;
+   u32 ctrl_reg;
+   u32 int_control0;
+   u32 int_main_control;
+};
+
+struct mtk_iommu_client_priv {
+   struct list_headclient;
+   unsigned intmtk_m4u_id;
+   struct device   *m4udev;
+};
+
+struct mtk_iommu_domain {
+   spinlock_t  pgtlock; /* lock for page table */
+
+   struct io_pgtable_cfg   cfg;
+   struct io_pgtable_ops   *iop;
+
+   struct iommu_domain domain;
+};
+
+struct mtk_iommu_data {
+   void __iomem*base;
+   int irq;
+   struct device   *dev;
+   struct clk 

[PATCH 0/5] MT2701 iommu support

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

  Mediatek's m4u(Multimedia Memory Management Unit) and SMI(Smart
Multimedia Interface)have two generations HW. They basically sharing the
same hardware block diagram, but have some difference as below:

  Generation one m4u only support one layer, flat pagetable addressing, and
only support 4K size page mapping. While generation two m4u support 2
levels of pagetable which use the ARM short-descriptor translation table
format for address translation.
They have slight different register base and register offset.
They have very different HW ports defines.

  Generaion one SMI have additional "async" clock which transform the smi
clock into emi clock domain, this clock should be prepare and enabled for
cMI generation one HW.
The register which control the iommu need to translation the address or not
for a particular port is located at smi ao base(smi always on register
base) for generation one SMI HW, but located at each larb's register base
for generation two HW.

This patch set add mt2701 iommu support, it's based on 4.6-rc1 and James
Liao's "Add clock support for Mediatek MT2701 v7[1]" and "Mediatek MT2701
SCPSYS power domain support v6[2]" patch.

[1] 
http://lists.infradead.org/pipermail/linux-mediatek/2016-February/004030.html
[2] http://www.spinics.net/lists/arm-kernel/msg497028.html

Honghui Zhang (5):
  dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and
smi
  iommu/mediatek: move the common struct into header file
  memory/mediatek: add support for mt2701
  iommu/mediatek: add support for mtk iommu generation one HW
  ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

 .../devicetree/bindings/iommu/mediatek,iommu.txt   |  13 +-
 .../memory-controllers/mediatek,smi-common.txt |  21 +-
 .../memory-controllers/mediatek,smi-larb.txt   |   4 +-
 arch/arm/boot/dts/mt2701.dtsi  |  51 ++
 drivers/iommu/Kconfig  |  19 +
 drivers/iommu/Makefile |   1 +
 drivers/iommu/mtk_iommu.c  |  62 +-
 drivers/iommu/mtk_iommu.h  |  94 +++
 drivers/iommu/mtk_iommu_v1.c   | 767 +
 drivers/memory/mtk-smi.c   | 168 -
 include/dt-bindings/memory/mt2701-larb-port.h  |  85 +++
 11 files changed, 1197 insertions(+), 88 deletions(-)
 create mode 100644 drivers/iommu/mtk_iommu.h
 create mode 100644 drivers/iommu/mtk_iommu_v1.c
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

-- 
1.8.1.1.dirty

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


[PATCH 5/5] ARM: dts: mt2701: add iommu/smi dtsi node for mt2701

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

Add the dtsi node of iommu and smi for mt2701.

Signed-off-by: Honghui Zhang 
---
 arch/arm/boot/dts/mt2701.dtsi | 51 +++
 1 file changed, 51 insertions(+)

diff --git a/arch/arm/boot/dts/mt2701.dtsi b/arch/arm/boot/dts/mt2701.dtsi
index 42d5a37..363de0d 100644
--- a/arch/arm/boot/dts/mt2701.dtsi
+++ b/arch/arm/boot/dts/mt2701.dtsi
@@ -16,6 +16,7 @@
 #include 
 #include 
 #include 
+#include 
 #include "skeleton64.dtsi"
 #include "mt2701-pinfunc.h"
 
@@ -160,6 +161,16 @@
clock-names = "system-clk", "rtc-clk";
};
 
+   smi_common: smi@1000c000 {
+   compatible = "mediatek,mt2701-smi-common";
+   reg = <0 0x1000c000 0 0x1000>;
+   clocks = < CLK_INFRA_SMI>,
+< CLK_MM_SMI_COMMON>,
+< CLK_INFRA_SMI>;
+   clock-names = "apb", "smi", "async";
+   power-domains = < MT2701_POWER_DOMAIN_DISP>;
+   };
+
sysirq: interrupt-controller@10200100 {
compatible = "mediatek,mt2701-sysirq",
 "mediatek,mt6577-sysirq";
@@ -169,6 +180,16 @@
reg = <0 0x10200100 0 0x1c>;
};
 
+   iommu: mmsys_iommu@10205000 {
+   compatible = "mediatek,mt2701-m4u";
+   reg = <0 0x10205000 0 0x1000>;
+   interrupts = ;
+   clocks = < CLK_INFRA_M4U>;
+   clock-names = "bclk";
+   mediatek,larbs = <  >;
+   #iommu-cells = <1>;
+   };
+
apmixedsys: syscon@10209000 {
compatible = "mediatek,mt2701-apmixedsys", "syscon";
reg = <0 0x10209000 0 0x1000>;
@@ -234,6 +255,16 @@
status = "disabled";
};
 
+   larb0: larb@1401 {
+   compatible = "mediatek,mt2701-smi-larb";
+   reg = <0 0x1401 0 0x1000>;
+   mediatek,smi = <_common>;
+   clocks = < CLK_MM_SMI_LARB0>,
+< CLK_MM_SMI_LARB0>;
+   clock-names = "apb", "smi";
+   power-domains = < MT2701_POWER_DOMAIN_DISP>;
+   };
+
imgsys: syscon@1500 {
compatible = "mediatek,mt2701-imgsys", "syscon";
reg = <0 0x1500 0 0x1000>;
@@ -241,6 +272,16 @@
status = "disabled";
};
 
+   larb2: larb@15001000 {
+   compatible = "mediatek,mt2701-smi-larb";
+   reg = <0 0x15001000 0 0x1000>;
+   mediatek,smi = <_common>;
+   clocks = < CLK_IMG_SMI_COMM>,
+< CLK_IMG_SMI_COMM>;
+   clock-names = "apb", "smi";
+   power-domains = < MT2701_POWER_DOMAIN_ISP>;
+   };
+
vdecsys: syscon@1600 {
compatible = "mediatek,mt2701-vdecsys", "syscon";
reg = <0 0x1600 0 0x1000>;
@@ -248,6 +289,16 @@
status = "disabled";
};
 
+   larb1: larb@1601 {
+   compatible = "mediatek,mt2701-smi-larb";
+   reg = <0 0x1601 0 0x1000>;
+   mediatek,smi = <_common>;
+   clocks = < CLK_VDEC_CKGEN>,
+< CLK_VDEC_LARB>;
+   clock-names = "apb", "smi";
+   power-domains = < MT2701_POWER_DOMAIN_VDEC>;
+   };
+
hifsys: syscon@1a00 {
compatible = "mediatek,mt2701-hifsys", "syscon";
reg = <0 0x1a00 0 0x1000>;
-- 
1.8.1.1.dirty

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


[PATCH 3/5] memory/mediatek: add support for mt2701

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

Mediatek SMI have two generation HW architecture, mt8173 use the
secondary generation of SMI HW while mt2701 use the first generation
HW of SMI.

There's slight differences between the two generation, for generation 2,
the register which control the iommu port access PA or IOVA is at each
larb's register base. But for generation 1, the register is at smi ao
base(smi always on register base).
Besides that, the smi async clock should be prepare and enabled for SMI
generation 1 HW to transform the smi clock into emi clock domain, but no
needed for SMI generation 2.

This patch add SMI driver for mt2701 which use generation 1 SMI HW.

Signed-off-by: Honghui Zhang 
---
 drivers/memory/mtk-smi.c | 168 +--
 1 file changed, 149 insertions(+), 19 deletions(-)

diff --git a/drivers/memory/mtk-smi.c b/drivers/memory/mtk-smi.c
index 089091f..0a47382 100644
--- a/drivers/memory/mtk-smi.c
+++ b/drivers/memory/mtk-smi.c
@@ -21,19 +21,50 @@
 #include 
 #include 
 #include 
+#include 
 
 #define SMI_LARB_MMU_EN0xf00
+#define REG_SMI_SECUR_CON_BASE 0x5c0
+
+/* every register control 8 port, register offset 0x4 */
+#define REG_SMI_SECUR_CON_OFFSET(id)   (((id) >> 3) << 2)
+#define REG_SMI_SECUR_CON_ADDR(id) \
+   (REG_SMI_SECUR_CON_BASE + REG_SMI_SECUR_CON_OFFSET(id))
+
+/*
+ * every port have 4 bit to control, bit[port + 3] control virtual or physical,
+ * bit[port + 2 : port + 1] control the domain, bit[port] control the security
+ * or non-security.
+ */
+#define SMI_SECUR_CON_VAL_MSK(id)  (~(0xf << (((id) & 0x7) << 2)))
+#define SMI_SECUR_CON_VAL_VIRT(id) BITid) & 0x7) << 2) + 3)
+/* mt2701 domain should be set to 3 */
+#define SMI_SECUR_CON_VAL_DOMAIN(id)   (0x3 << id) & 0x7) << 2) + 1))
+
+struct mtk_smi_larb_gen {
+   int port_in_larb[MTK_LARB_NR_MAX + 1];
+   void (*config_port)(struct device *);
+};
 
 struct mtk_smi {
-   struct device   *dev;
-   struct clk  *clk_apb, *clk_smi;
+   struct device   *dev;
+   struct clk  *clk_apb, *clk_smi;
+   struct clk  *clk_async; /*only needed by mt2701*/
+   void __iomem*smi_ao_base;
 };
 
 struct mtk_smi_larb { /* larb: local arbiter */
-   struct mtk_smi  smi;
-   void __iomem*base;
-   struct device   *smi_common_dev;
-   u32 *mmu;
+   struct mtk_smi  smi;
+   void __iomem*base;
+   struct device   *smi_common_dev;
+   const struct mtk_smi_larb_gen   *larb_gen;
+   int larbid;
+   u32 *mmu;
+};
+
+enum mtk_smi_gen {
+   MTK_SMI_GEN1,
+   MTK_SMI_GEN2
 };
 
 static int mtk_smi_enable(const struct mtk_smi *smi)
@@ -71,6 +102,7 @@ static void mtk_smi_disable(const struct mtk_smi *smi)
 int mtk_smi_larb_get(struct device *larbdev)
 {
struct mtk_smi_larb *larb = dev_get_drvdata(larbdev);
+   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
int ret;
 
@@ -87,8 +119,7 @@ int mtk_smi_larb_get(struct device *larbdev)
}
 
/* Configure the iommu info for this larb */
-   writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
-
+   larb_gen->config_port(larbdev);
return 0;
 }
 
@@ -124,6 +155,45 @@ mtk_smi_larb_bind(struct device *dev, struct device 
*master, void *data)
return -ENODEV;
 }
 
+static void mtk_smi_larb_config_port(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+
+   writel(*larb->mmu, larb->base + SMI_LARB_MMU_EN);
+}
+
+
+static void mtk_smi_larb_config_port_gen1(struct device *dev)
+{
+   struct mtk_smi_larb *larb = dev_get_drvdata(dev);
+   const struct mtk_smi_larb_gen *larb_gen = larb->larb_gen;
+   struct mtk_smi *common = dev_get_drvdata(larb->smi_common_dev);
+   int i, m4u_port_id, larb_port_num;
+   u32 sec_con_val, reg_val;
+
+   m4u_port_id = larb_gen->port_in_larb[larb->larbid];
+   larb_port_num = larb_gen->port_in_larb[larb->larbid + 1]
+   - larb_gen->port_in_larb[larb->larbid];
+
+   for (i = 0; i < larb_port_num; i++, m4u_port_id++) {
+   if (*larb->mmu & BIT(i)) {
+   /* bit[port + 3] controls the virtual or physical */
+   sec_con_val = SMI_SECUR_CON_VAL_VIRT(m4u_port_id);
+   } else {
+   /* do not need to enable m4u for this port */
+   continue;
+   }
+   reg_val = readl(common->smi_ao_base
+   + REG_SMI_SECUR_CON_ADDR(m4u_port_id));
+   reg_val &= SMI_SECUR_CON_VAL_MSK(m4u_port_id);
+   reg_val |= sec_con_val;

[PATCH 1/5] dt-bindings: mediatek: add descriptions for mediatek mt2701 iommu and smi

2016-05-09 Thread honghui.zhang
From: Honghui Zhang 

This patch defines the local arbitor port IDs for mediatek SoC MT2701 and
add descriptions of binding for mediatek generation one iommu and smi.

Signed-off-by: Honghui Zhang 
---
 .../devicetree/bindings/iommu/mediatek,iommu.txt   | 13 +++-
 .../memory-controllers/mediatek,smi-common.txt | 21 +-
 .../memory-controllers/mediatek,smi-larb.txt   |  4 +-
 include/dt-bindings/memory/mt2701-larb-port.h  | 85 ++
 4 files changed, 115 insertions(+), 8 deletions(-)
 create mode 100644 include/dt-bindings/memory/mt2701-larb-port.h

diff --git a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt 
b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
index cd1b1cd..9a4a5b5 100644
--- a/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
+++ b/Documentation/devicetree/bindings/iommu/mediatek,iommu.txt
@@ -1,7 +1,9 @@
 * Mediatek IOMMU Architecture Implementation
 
-  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U) which
-uses the ARM Short-Descriptor translation table format for address translation.
+  Some Mediatek SOCs contain a Multimedia Memory Management Unit (M4U), and
+this M4U have two generations of HW architecture. Generation one use flat
+pagetable, and only support 4K size page mapping. Generation two uses the
+ARM Short-Descriptor translation table format for address translation.
 
   About the M4U Hardware Block Diagram, please check below:
 
@@ -36,7 +38,9 @@ in each larb. Take a example, There are many ports like MC, 
PP, VLD in the
 video decode local arbiter, all these ports are according to the video HW.
 
 Required properties:
-- compatible : must be "mediatek,mt8173-m4u".
+- compatible : must be one of the following string:
+   "mediatek,mt2701-m4u" for mt2701 which use generation one m4u HW.
+   "mediatek,mt8173-m4u" for mt8173 which use generation two m4u HW.
 - reg : m4u register base and size.
 - interrupts : the interrupt of m4u.
 - clocks : must contain one entry for each clock-names.
@@ -46,7 +50,8 @@ Required properties:
according to the local arbiter index, like larb0, larb1, larb2...
 - iommu-cells : must be 1. This is the mtk_m4u_id according to the HW.
Specifies the mtk_m4u_id as defined in
-   dt-binding/memory/mt8173-larb-port.h.
+   dt-binding/memory/mt2701-larb-port.h for mt2701 and
+   dt-binding/memory/mt8173-larb-port.h for mt8173
 
 Example:
iommu: iommu@10205000 {
diff --git 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
index 06a83ce..80c0e22 100644
--- 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
+++ 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-common.txt
@@ -2,16 +2,31 @@ SMI (Smart Multimedia Interface) Common
 
 The hardware block diagram please check bindings/iommu/mediatek,iommu.txt
 
+Mediatek SMI have two generation HW architecture, mt8173 use the secondary
+generation of SMI HW while mt2701 use the first generation HW of SMI.
+
+There's slight differences between the two SMI, for generation 2, the
+register which control the iommu port is at each larb's register base. But
+for generation 1, the register is at smi ao base(smi always on register
+base). Besides that, the smi async clock should be prepare and enabled for
+SMI generation 1 to transform the smi clock into emi clock domain, but no
+needed for SMI generation 2.
+
 Required properties:
-- compatible : must be "mediatek,mt8173-smi-common"
+- compatible : must be one of :
+   "mediatek,mt2701-smi-common"
+   "mediatek,mt8173-smi-common"
 - reg : the register and size of the SMI block.
 - power-domains : a phandle to the power domain of this local arbiter.
 - clocks : Must contain an entry for each entry in clock-names.
-- clock-names : must contain 2 entries, as follows:
+- clock-names : must contain 3 entries for generation 1 smi HW and 2 entries
+  for generation 2 smi HW as follows:
   - "apb" : Advanced Peripheral Bus clock, It's the clock for setting
the register.
   - "smi" : It's the clock for transfer data and command.
-  They may be the same if both source clocks are the same.
+   They may be the same if both source clocks are the same.
+  - "async" : asynchronous clock, it help transform the smi clock into the emi
+ clock domain, this clock is only needed by generation 1 smi HW.
 
 Example:
smi_common: smi@14022000 {
diff --git 
a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt 
b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
index 55ff3b7..21277a5 100644
--- a/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
+++ b/Documentation/devicetree/bindings/memory-controllers/mediatek,smi-larb.txt
@@ -3,7 +3,9 @@ 

Re: [PATCH v9 4/7] vfio: allow reserved msi iova registration

2016-05-09 Thread Eric Auger
Hi Chalamarla,
On 05/05/2016 09:22 PM, Chalamarla, Tirumalesh wrote:
> 
> 
> 
> 
> 
> On 5/4/16, 4:54 AM, "linux-arm-kernel on behalf of Eric Auger" 
>  eric.au...@linaro.org> wrote:
> 
>> The user is allowed to register a reserved MSI IOVA range by using the
>> DMA MAP API and setting the new flag: VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA.
>> This region is stored in the vfio_dma rb tree. At that point the iova
>> range is not mapped to any target address yet. The host kernel will use
>> those iova when needed, typically when MSIs are allocated.
>>
>> Signed-off-by: Eric Auger 
>> Signed-off-by: Bharat Bhushan 
>>
>> ---
>> v7 -> v8:
>> - use iommu_msi_set_aperture function. There is no notion of
>>  unregistration anymore since the reserved msi slot remains
>>  until the container gets closed.
>>
>> v6 -> v7:
>> - use iommu_free_reserved_iova_domain
>> - convey prot attributes downto dma-reserved-iommu iova domain creation
>> - reserved bindings teardown now performed on iommu domain destruction
>> - rename VFIO_DMA_MAP_FLAG_MSI_RESERVED_IOVA into
>> VFIO_DMA_MAP_FLAG_RESERVED_MSI_IOVA
>> - change title
>> - pass the protection attribute to dma-reserved-iommu API
>>
>> v3 -> v4:
>> - use iommu_alloc/free_reserved_iova_domain exported by dma-reserved-iommu
>> - protect vfio_register_reserved_iova_range implementation with
>>  CONFIG_IOMMU_DMA_RESERVED
>> - handle unregistration by user-space and on vfio_iommu_type1 release
>>
>> v1 -> v2:
>> - set returned value according to alloc_reserved_iova_domain result
>> - free the iova domains in case any error occurs
>>
>> RFC v1 -> v1:
>> - takes into account Alex comments, based on
>>  [RFC PATCH 1/6] vfio: Add interface for add/del reserved iova region:
>> - use the existing dma map/unmap ioctl interface with a flag to register
>>  a reserved IOVA range. A single reserved iova region is allowed.
>> ---
>> drivers/vfio/vfio_iommu_type1.c | 78 
>> -
>> include/uapi/linux/vfio.h   | 10 +-
>> 2 files changed, 86 insertions(+), 2 deletions(-)
>>
>> diff --git a/drivers/vfio/vfio_iommu_type1.c 
>> b/drivers/vfio/vfio_iommu_type1.c
>> index 94a9916..4d3a6f1 100644
>> --- a/drivers/vfio/vfio_iommu_type1.c
>> +++ b/drivers/vfio/vfio_iommu_type1.c
>> @@ -36,6 +36,7 @@
>> #include 
>> #include 
>> #include 
>> +#include 
>>
>> #define DRIVER_VERSION  "0.2"
>> #define DRIVER_AUTHOR   "Alex Williamson "
>> @@ -445,6 +446,20 @@ static void vfio_unmap_unpin(struct vfio_iommu *iommu, 
>> struct vfio_dma *dma)
>>  vfio_lock_acct(-unlocked);
>> }
>>
>> +static int vfio_set_msi_aperture(struct vfio_iommu *iommu,
>> +dma_addr_t iova, size_t size)
>> +{
>> +struct vfio_domain *d;
>> +int ret = 0;
>> +
>> +list_for_each_entry(d, >domain_list, next) {
>> +ret = iommu_msi_set_aperture(d->domain, iova, iova + size - 1);
>> +if (ret)
>> +break;
>> +}
>> +return ret;
>> +}
>> +
>> static void vfio_remove_dma(struct vfio_iommu *iommu, struct vfio_dma *dma)
>> {
>>  vfio_unmap_unpin(iommu, dma);
>> @@ -693,6 +708,63 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu,
>>  return ret;
>> }
>>
>> +static int vfio_register_msi_range(struct vfio_iommu *iommu,
>> +   struct vfio_iommu_type1_dma_map *map)
>> +{
>> +dma_addr_t iova = map->iova;
>> +size_t size = map->size;
>> +int ret = 0;
>> +struct vfio_dma *dma;
>> +unsigned long order;
>> +uint64_t mask;
>> +
>> +/* Verify that none of our __u64 fields overflow */
>> +if (map->size != size || map->iova != iova)
>> +return -EINVAL;
>> +
>> +order =  __ffs(vfio_pgsize_bitmap(iommu));
>> +mask = ((uint64_t)1 << order) - 1;
>> +
>> +WARN_ON(mask & PAGE_MASK);
>> +
>> +if (!size || (size | iova) & mask)
>> +return -EINVAL;
>> +
>> +/* Don't allow IOVA address wrap */
>> +if (iova + size - 1 < iova)
>> +return -EINVAL;
>> +
>> +mutex_lock(>lock);
>> +
>> +if (vfio_find_dma(iommu, iova, size, VFIO_IOVA_ANY)) {
>> +ret =  -EEXIST;
>> +goto unlock;
>> +}
>> +
>> +dma = kzalloc(sizeof(*dma), GFP_KERNEL);
>> +if (!dma) {
>> +ret = -ENOMEM;
>> +goto unlock;
>> +}
>> +
>> +dma->iova = iova;
>> +dma->size = size;
>> +dma->type = VFIO_IOVA_RESERVED;
>> +
>> +ret = vfio_set_msi_aperture(iommu, iova, size);
>> +if (ret)
>> +goto free_unlock;
>> +
>> +vfio_link_dma(iommu, dma);
>> +goto unlock;
>> +
>> +free_unlock:
>> +kfree(dma);
>> +unlock:
>> +mutex_unlock(>lock);
>> +return ret;
>> +}
>> +
>> static int vfio_bus_type(struct device *dev, void *data)
>> {
>>  struct bus_type **bus = data;
>> @@ -1062,7 +1134,8 @@ 

Re: [PATCH v9 0/8] KVM PCIe/MSI passthrough on ARM/ARM64: kernel part 2/3: msi changes

2016-05-09 Thread Eric Auger
Hi Chalarmala,
On 05/05/2016 07:44 PM, Chalamarla, Tirumalesh wrote:
> Hi Eric,
> 
> Does this series supports gicv3-its emulation?
> Do we have a tree with all the dependent patches
GICv3 ITS emulation support comes with:
[PATCH v4 00/12] KVM: arm64: GICv3 ITS emulation
http://permalink.gmane.org/gmane.comp.emulators.kvm.arm.devel/5738

My series just allows PCI device MSI transactions to reach the host MSI
frame through the SMMU. Only host GICv2m has been tested at the moment
with a guest exposed with a GICv2m too.

Best Regards

Eric


> 
> 
> 
> 
> 
> Thanks,
> Tirumalesh. 
> On 5/4/16, 8:18 AM, "linux-arm-kernel on behalf of Eric Auger" 
>  eric.au...@linaro.org> wrote:
> 
>> This series implements the MSI address mapping/unmapping in the MSI layer.
>> IOMMU binding happens on pci_enable_msi since this function can sleep and
>> return errors. On msi_domain_set_affinity, msi_domain_(de)activate, which
>> are not allowed to sleep, we simply look for the already existing binding.
>>
>> A new MSI domain info flag value is introduced to report whether the msi
>> domain implements IRQ remapping. GIC v3 ITS is the first MSI controller
>> advertising it. This flag value will be used by VFIO subsystem to
>> determine whether MSI forwarding is safe.
>>
>> More details & context can be found at:
>> http://www.linaro.org/blog/core-dump/kvm-pciemsi-passthrough-armarm64/
>>
>> Best Regards
>>
>> Eric
>>
>> Applies on top of PART 1/3. Also depends on
>> [PATCH 1/3] iommu: Add MMIO mapping type,
>> http://comments.gmane.org/gmane.linux.kernel.iommu/12869
>>
>> Git: complete series available at
>> https://git.linaro.org/people/eric.auger/linux.git/shortlog/refs/heads/v4.6-rc6-pcie-passthrough-v9-msi-v9
>>
>> This branch contains all parts in v9.
>>
>> History:
>>
>> v8 -> v9:
>> - use a union in irq_chip_msi_doorbell_info + boolean telling whether the
>>  doorbell is percpu
>> - decouple irq_data parsing from the actual mapping/unmapping in
>>  msi_handle_doorbell_mappings
>> - fix misc style issues
>>
>> v7 -> v8:
>> take into account Marc's comments:
>> - use iommu_msi_msg_pa_to_va with new proto
>> - change in irq_chip_msi_doorbell_info struct definition:
>>  prot and size became shared between all doorbells and phys_addr_t __percpu
>> - cleanups in v2m irqchip
>> - eventually did not touch MSI_FLAG_IRQ_REMAPPING naming
>> - On msi_handle_doorbell_mappings, stop on the first irqchip where doorbells
>>  can be found
>> - fix resource deallocation on mapping failure in msi_domain_alloc_irqs
>>
>> v6 -> v7:
>> - do alloc/map handling on pci_enable_msi and search on 
>> msi_(de)domain_activate
>> - add msi_doorbell_info callback in irq-chip to retrieve the characteristics
>>  of doorbells
>>
>> RFC v5 -> patch v6:
>> - split to ease the review process
>> - rebase on default iommu domain code (irq_data_to_msi_mapping_domain
>>  checks IOMMU_DOMAIN_DMA type)
>> - fix unmap sequence on msi_domain_set_affinity (reported by Marc):
>>  unmap the previous doorbell when the new one has been mapped & written to
>>  the device, ie. irq_chip_write_msi_msg.
>> - "msi: msi_compose wrapper removed" following change above
>> - add size parameter to iommu_get_reserved_iova API following Marc's request
>>
>> RFC v4 -> RFC v5:
>> - take into account Thomas' comments on MSI related patches
>>  - split "msi: IOMMU map the doorbell address when needed"
>>  - increase readability and add comments
>>  - fix style issues
>> - split "iommu: Add DOMAIN_ATTR_MSI_MAPPING attribute"
>> - platform ITS now advertises IOMMU_CAP_INTR_REMAP
>> - fix compilation issue with CONFIG_IOMMU API unset
>> - arm-smmu-v3 now advertises DOMAIN_ATTR_MSI_MAPPING
>>
>> RFC v3 -> v4:
>> - Move doorbell mapping/unmapping in msi.c
>> - fix ref count issue on set_affinity: in case of a change in the address
>>  the previous address is decremented
>> - doorbell map/unmap now is done on msi composition. Should allow the use
>>  case for platform MSI controllers
>> - create dma-reserved-iommu.h/c exposing/implementing a new API dedicated
>>  to reserved IOVA management (looking like dma-iommu glue)
>> - series reordering to ease the review:
>>  - first part is related to IOMMU
>>  - second related to MSI sub-system
>>  - third related to VFIO (except arm-smmu IOMMU_CAP_INTR_REMAP removal)
>> - expose the number of requested IOVA pages through VFIO_IOMMU_GET_INFO
>>  [this partially addresses Marc's comments on iommu_get/put_single_reserved
>>   size/alignment problematic - which I did not ignore - but I don't know
>>   how much I can do at the moment]
>>
>> RFC v2 -> RFC v3:
>> - should fix wrong handling of some CONFIG combinations:
>>  CONFIG_IOVA, CONFIG_IOMMU_API, CONFIG_PCI_MSI_IRQ_DOMAIN
>> - fix MSI_FLAG_IRQ_REMAPPING setting in GICv3 ITS (although not tested)
>>
>> PATCH v1 -> RFC v2:
>> - reverted to RFC since it looks more reasonable ;-) the code is split
>>  between VFIO, IOMMU, MSI controller and I