[PATCH 3/3] arm64: dts: Add dts node for hi6220 smmu driver

2015-11-17 Thread Chen Feng
Add iommu node for hi6220 SoC platform

Signed-off-by: Chen Feng 
---
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi | 13 +
 1 file changed, 13 insertions(+)

diff --git a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi 
b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
index 82d2488..589424a 100644
--- a/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
+++ b/arch/arm64/boot/dts/hisilicon/hi6220.dtsi
@@ -208,5 +208,18 @@
clock-names = "uartclk", "apb_pclk";
status = "disabled";
};
+
+   iommu: iommu@f421 {
+   compatible = "hisilicon,hi6220-smmu";
+   reg = <0x0 0xf421 0x0 0x1000>;
+   interrupts = ;
+   clocks = <&sys_ctrl HI6220_MMU_CLK>,
+<&media_ctrl HI6220_MED_MMU>,
+<&sys_ctrl HI6220_MEDIA_PLL_SRC>;
+   clock-names = "smmu",
+ "media-sc",
+ "smmu-peri";
+   #iommu-cells = <0>;
+   };
};
 };
-- 
1.9.1

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


[PATCH 2/3] iommu/hisilicon: Add hi6220-SoC smmu driver

2015-11-17 Thread Chen Feng
Add iommu driver for hi6220 SoC platform.The smmu on hi6220
SoC is for media system.And the media IP use the same page-table.
It supports only one-to-one mapping from iova to phys address.

Signed-off-by: Chen Feng 
---
 drivers/iommu/Kconfig|  11 +
 drivers/iommu/Makefile   |   1 +
 drivers/iommu/hi6220_iommu.c | 492 +++
 3 files changed, 504 insertions(+)
 create mode 100644 drivers/iommu/hi6220_iommu.c

diff --git a/drivers/iommu/Kconfig b/drivers/iommu/Kconfig
index b9094e9..7c13521 100644
--- a/drivers/iommu/Kconfig
+++ b/drivers/iommu/Kconfig
@@ -84,6 +84,17 @@ config IOMMU_PGTABLES_L2
def_bool y
depends on MSM_IOMMU && MMU && SMP && CPU_DCACHE_DISABLE=n
 
+config HI6220_IOMMU
+   bool "Hi6220 IOMMU Support"
+   depends on ARM64
+   select IOMMU_API
+   select IOMMU_IOVA
+   help
+ Enable IOMMU Driver for hi6220 SoC. The IOMMU API and IOMMU IOVA
+ is also selected.
+
+ If unsure, say N.
+
 # AMD IOMMU support
 config AMD_IOMMU
bool "AMD IOMMU support"
diff --git a/drivers/iommu/Makefile b/drivers/iommu/Makefile
index 68faca02..cdb2b83 100644
--- a/drivers/iommu/Makefile
+++ b/drivers/iommu/Makefile
@@ -12,6 +12,7 @@ obj-$(CONFIG_AMD_IOMMU_V2) += amd_iommu_v2.o
 obj-$(CONFIG_ARM_SMMU) += arm-smmu.o
 obj-$(CONFIG_ARM_SMMU_V3) += arm-smmu-v3.o
 obj-$(CONFIG_DMAR_TABLE) += dmar.o
+obj-$(CONFIG_HI6220_IOMMU) += hi6220_iommu.o
 obj-$(CONFIG_INTEL_IOMMU) += intel-iommu.o
 obj-$(CONFIG_INTEL_IOMMU_SVM) += intel-svm.o
 obj-$(CONFIG_IPMMU_VMSA) += ipmmu-vmsa.o
diff --git a/drivers/iommu/hi6220_iommu.c b/drivers/iommu/hi6220_iommu.c
new file mode 100644
index 000..a546d43
--- /dev/null
+++ b/drivers/iommu/hi6220_iommu.c
@@ -0,0 +1,492 @@
+/*
+ * Hisilicon Hi6220 IOMMU driver
+ *
+ * Copyright (c) 2015 Hisilicon Limited.
+ *
+ * Author: Chen Feng 
+ *
+ * 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.
+ */
+
+#define pr_fmt(fmt) "IOMMU: " fmt
+
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+#include 
+
+#define SMMU_CTRL_OFFSET (0x)
+#define SMMU_ENABLE_OFFSET   (0x0004)
+#define SMMU_PTBR_OFFSET (0x0008)
+#define SMMU_START_OFFSET(0x000C)
+#define SMMU_END_OFFSET  (0x0010)
+#define SMMU_INTMASK_OFFSET  (0x0014)
+#define SMMU_RINTSTS_OFFSET  (0x0018)
+#define SMMU_MINTSTS_OFFSET  (0x001C)
+#define SMMU_INTCLR_OFFSET   (0x0020)
+#define SMMU_STATUS_OFFSET   (0x0024)
+#define SMMU_AXIID_OFFSET(0x0028)
+#define SMMU_CNTCTRL_OFFSET  (0x002C)
+#define SMMU_TRANSCNT_OFFSET (0x0030)
+#define SMMU_L0TLBHITCNT_OFFSET  (0x0034)
+#define SMMU_L1TLBHITCNT_OFFSET  (0x0038)
+#define SMMU_WRAPCNT_OFFSET  (0x003C)
+#define SMMU_SEC_START_OFFSET(0x0040)
+#define SMMU_SEC_END_OFFSET  (0x0044)
+#define SMMU_VERSION_OFFSET  (0x0048)
+#define SMMU_IPTSRC_OFFSET   (0x004C)
+#define SMMU_IPTPA_OFFSET(0x0050)
+#define SMMU_TRBA_OFFSET (0x0054)
+#define SMMU_BYS_START_OFFSET(0x0058)
+#define SMMU_BYS_END_OFFSET  (0x005C)
+#define SMMU_RAM_OFFSET  (0x1000)
+
+#define SMMU_CTRL_INVALID(BIT(10))
+#define SMMU_SR_REGS_NUM (15)
+#define SMMU_REGS_SGMT_END   (0x60)
+#define PAGE_ENTRY_VALID (0x1)
+#define IOPAGE_SHIFT (12)
+#define IOVA_PFN(addr)   ((addr) >> IOPAGE_SHIFT)
+#define IOVA_PAGE_SZ (SZ_4K)
+
+/**
+ * The iova address from 0 ~ 2G
+ */
+#define IOVA_START   (0x0)
+#define IOVA_END (0x8000)
+
+struct hi6220_smmu {
+   unsigned int irq;
+   void __iomem *reg_base;
+   struct clk *smmu_peri_clk;
+   struct clk *smmu_clk;
+   struct clk *media_sc_clk;
+   spinlock_t spinlock; /*spinlock for tlb invalid*/
+   dma_addr_t pgtable_phy;
+   void *pgtable_virt;
+   u32  pgtable_size;
+   u32  *sr_data;
+};
+
+struct hi6220_domain {
+   struct hi6220_smmu *smmu_dev;
+   struct iommu_domain io_domain;
+};
+
+static struct hi6220_smmu *smmu_dev_handle;
+static struct iova_domain iova_allocator;
+
+static struct hi6220_domain *to_hi6220_domain(struct iommu_domain *dom)
+{
+   return container_of(dom, struct hi6220_domain, io_domain);
+}
+
+static inline void __smmu_writel(struct hi6220_smmu *smmu_dev, u32 value,
+unsigned long offset)
+{
+   writel(value, smmu_dev->reg_base + offset);
+}
+
+static inline u32 __smmu_readl(struct hi6220_smmu *smmu_dev,
+  unsigned long offset)
+{
+   return readl(smmu_dev->reg_base + offset);
+

[PATCH 1/3] docs: iommu: Documentation for iommu in hi6220 SoC

2015-11-17 Thread Chen Feng
Documentation for hi6220 iommu driver.

Signed-off-by: Chen Feng 
---
 .../bindings/iommu/hisi,hi6220-iommu.txt   | 32 ++
 1 file changed, 32 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt

diff --git a/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt 
b/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
new file mode 100644
index 000..44f9101
--- /dev/null
+++ b/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
@@ -0,0 +1,32 @@
+Hi6220 SoC SMMU Device Driver devicetree document
+The media system shared the same smmu IP to access DDR memory. And all
+media IP used the same page table.
+
+Below binding describes the system mmu for media system in hi6220 platform
+
+Required properties:
+- compatible: should contain "hisilicon,hi6220-smmu".
+- reg: A tuple of base address and size of System MMU registers.
+- clocks: a list of phandle + clock-specifier pairs, one for each entry
+  in clock-names.
+- clock-names: should contain:
+  * "smmu"
+  * "media-sc"
+  * "smmu-peri"
+- interrupts: An interrupt specifier for interrupt signal of System MMU.
+- #iommu-cells: The iommu-cells should be 0. Because no additional information
+  needs to be encoded in the specifier.
+
+Examples:
+   iommu@f421 {
+   compatible = "hisilicon,hi6220-smmu";
+   reg = <0x0 0xf421 0x0 0x1000>;
+   interrupts = ;
+   clocks = <&sys_ctrl HI6220_MMU_CLK>,
+<&media_ctrl HI6220_MED_MMU>,
+<&sys_ctrl HI6220_MEDIA_PLL_SRC>;
+   clock-names = "smmu",
+ "media-sc",
+ "smmu-peri";
+   #iommu-cells = <0>;
+   };
-- 
1.9.1

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


Re: [PATCH v6 1/3] iommu: Implement common IOMMU ops for DMA mapping

2015-11-17 Thread Marek Szyprowski

Hello,

I'm really sorry do late joining this discussion, but I was terribly 
busy with other things.


On 2015-10-30 02:17, Daniel Kurtz wrote:

+linux-media & VIDEOBUF2 FRAMEWORK maintainers since this is about the
v4l2-contig's usage of the DMA API.

Hi Robin,

On Tue, Oct 27, 2015 at 12:55 AM, Robin Murphy  wrote:

On 26/10/15 13:44, Yong Wu wrote:

On Thu, 2015-10-01 at 20:13 +0100, Robin Murphy wrote:
[...]

+/*
+ * The DMA API client is passing in a scatterlist which could describe
+ * any old buffer layout, but the IOMMU API requires everything to be
+ * aligned to IOMMU pages. Hence the need for this complicated bit of
+ * impedance-matching, to be able to hand off a suitably-aligned list,
+ * but still preserve the original offsets and sizes for the caller.
+ */
+int iommu_dma_map_sg(struct device *dev, struct scatterlist *sg,
+   int nents, int prot)
+{
+   struct iommu_domain *domain = iommu_get_domain_for_dev(dev);
+   struct iova_domain *iovad = domain->iova_cookie;
+   struct iova *iova;
+   struct scatterlist *s, *prev = NULL;
+   dma_addr_t dma_addr;
+   size_t iova_len = 0;
+   int i;
+
+   /*
+* Work out how much IOVA space we need, and align the segments
to
+* IOVA granules for the IOMMU driver to handle. With some clever
+* trickery we can modify the list in-place, but reversibly, by
+* hiding the original data in the as-yet-unused DMA fields.
+*/
+   for_each_sg(sg, s, nents, i) {
+   size_t s_offset = iova_offset(iovad, s->offset);
+   size_t s_length = s->length;
+
+   sg_dma_address(s) = s->offset;
+   sg_dma_len(s) = s_length;
+   s->offset -= s_offset;
+   s_length = iova_align(iovad, s_length + s_offset);
+   s->length = s_length;
+
+   /*
+* The simple way to avoid the rare case of a segment
+* crossing the boundary mask is to pad the previous one
+* to end at a naturally-aligned IOVA for this one's
size,
+* at the cost of potentially over-allocating a little.
+*/
+   if (prev) {
+   size_t pad_len = roundup_pow_of_two(s_length);
+
+   pad_len = (pad_len - iova_len) & (pad_len - 1);
+   prev->length += pad_len;


Hi Robin,
While our v4l2 testing, It seems that we met a problem here.
Here we update prev->length again, Do we need update
sg_dma_len(prev) again too?

Some function like vb2_dc_get_contiguous_size[1] always get
sg_dma_len(s) to compare instead of s->length. so it may break
unexpectedly while sg_dma_len(s) is not same with s->length.


This is just tweaking the faked-up length that we hand off to iommu_map_sg()
(see also the iova_align() above), to trick it into bumping this segment up
to a suitable starting IOVA. The real length at this point is stashed in
sg_dma_len(s), and will be copied back into s->length in __finalise_sg(), so
both will hold the same true length once we return to the caller.

Yes, it does mean that if you have a list where the segment lengths are page
aligned but not monotonically decreasing, e.g. {64k, 16k, 64k}, then you'll
still end up with a gap between the second and third segments, but that's
fine because the DMA API offers no guarantees about what the resulting DMA
addresses will be (consider the no-IOMMU case where they would each just be
"mapped" to their physical address). If that breaks v4l, then it's probably
v4l's DMA API use that needs looking at (again).

Hmm, I thought the DMA API maps a (possibly) non-contiguous set of
memory pages into a contiguous block in device memory address space.
This would allow passing a dma mapped buffer to device dma using just
a device address and length.
IIUC, the change above breaks this model by inserting gaps in how the
buffer is mapped to device memory, such that the buffer is no longer
contiguous in dma address space.

Here is the code in question from
drivers/media/v4l2-core/videobuf2-dma-contig.c :

static unsigned long vb2_dc_get_contiguous_size(struct sg_table *sgt)
{
 struct scatterlist *s;
 dma_addr_t expected = sg_dma_address(sgt->sgl);
 unsigned int i;
 unsigned long size = 0;

 for_each_sg(sgt->sgl, s, sgt->nents, i) {
 if (sg_dma_address(s) != expected)
 break;
 expected = sg_dma_address(s) + sg_dma_len(s);
 size += sg_dma_len(s);
 }
 return size;
}


static void *vb2_dc_get_userptr(void *alloc_ctx, unsigned long vaddr,
 unsigned long size, enum dma_data_direction dma_dir)
{
 struct vb2_dc_conf *conf = alloc_ctx;
 struct vb2_dc_buf *buf;
 struct frame_vector *vec;
 unsigned long offset;
 int n_pages, i;
 int ret = 0;
 struct sg_table *sgt;
  

Re: [RFC/PATCH] media: omap3isp: Set maximum DMA segment size

2015-11-17 Thread Marek Szyprowski

Hi Laurent,

I really have no idea how this problem should be addressed. I've already 
proposed
to handle it in videobuf2-dc, but this has been rejected. Maybe the only 
way will
be to add dma_set_max_seg_size(isp->dev, DMA_BIT_MASK(32)) to every v4l2 
driver,

which use videobuf2-dc and add a check in videobuf2-dc.

Best regards
--
Marek Szyprowski, PhD
Samsung R&D Institute Poland

On 2015-11-09 15:18, Laurent Pinchart wrote:

Hello everybody,

Ping ?

On Tuesday 13 October 2015 16:18:36 Laurent Pinchart wrote:

The maximum DMA segment size controls the IOMMU mapping granularity. Its
default value is 64kB, resulting in potentially non-contiguous IOMMU
mappings. Configure it to 4GB to ensure that buffers get mapped
contiguously.

Signed-off-by: Laurent Pinchart 
---
  drivers/media/platform/omap3isp/isp.c | 4 
  drivers/media/platform/omap3isp/isp.h | 1 +
  2 files changed, 5 insertions(+)

I'm posting this as an RFC because I'm not happy with the patch, even if it
gets the job done.

On ARM the maximum DMA segment size is used when creating IOMMU mappings. As
a large number of devices require contiguous memory buffers (this is a very
common requirement for video-related embedded devices) the default 64kB
value doesn't work.

I haven't investigated the history behind this API in details but I have a
feeling something is not quite right. We force most drivers to explicitly
set the maximum segment size from a default that seems valid for specific
use cases only. Furthermore, as the DMA parameters are not stored directly
in struct device this require allocation of external memory for which we
have no proper management rule, making automatic handling of the DMA
parameters in frameworks or helper functions cumbersome (for a discussion
on this topic see http://www.spinics.net/lists/linux-media/msg92467.html
and http://lists.infradead.org/pipermail/linux-arm-kernel/2014-> 
November/305913.html).

Is it time to fix this mess ?

diff --git a/drivers/media/platform/omap3isp/isp.c
b/drivers/media/platform/omap3isp/isp.c index 17430a6ed85a..ebf7dc76e94d
100644
--- a/drivers/media/platform/omap3isp/isp.c
+++ b/drivers/media/platform/omap3isp/isp.c
@@ -2444,6 +2444,10 @@ static int isp_probe(struct platform_device *pdev)
if (ret)
goto error;

+   isp->dev->dma_parms = &isp->dma_parms;
+   dma_set_max_seg_size(isp->dev, DMA_BIT_MASK(32));
+   dma_set_seg_boundary(isp->dev, 0x);
+
platform_set_drvdata(pdev, isp);

/* Regulators */
diff --git a/drivers/media/platform/omap3isp/isp.h
b/drivers/media/platform/omap3isp/isp.h index e579943175c4..4b2231cf01be
100644
--- a/drivers/media/platform/omap3isp/isp.h
+++ b/drivers/media/platform/omap3isp/isp.h
@@ -193,6 +193,7 @@ struct isp_device {
u32 syscon_offset;
u32 phy_type;

+   struct device_dma_parameters dma_parms;
struct dma_iommu_mapping *mapping;

/* ISP Obj */


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


[PATCH RFC 0/3] Add iommu support for hi6220 HiKey board

2015-11-17 Thread Chen Feng
The patch sets add iommu support for Hi6220 SoC. Current testing and support
board is Hikey which is one of 96boards.
It is an arm64 open source board. For more information about this board,
please access https://www.96boards.org.

The Architecture of SMMU on Hi6220 SoC:

   +--+
   |  |
   | +-+  ++  +-+   +---+ |
   | |   ADE   |  |  ISP   |  |  V/J codec  |   |  G3D  | |
   | +|+  +---|+  +--|--+   +---|---| |
   |  |   |  |  | |
   | -v---v--v--v-|
   |   Media Bus  |
   | |---||
   | |   ||
   | +---v---v+   |
   | |SMMU|   |
   | +--|-|---+   |
   || |   |
   +|-|---+
| |
   +v-v---+
   |  DDRC|
   +--+

Note:
The media system share the same smmu IP to access DDR memory. And all
media IP use the same page table. The hi6220 iommu driver also uses the
iova api to manage an iova allocator to ensure that the caller get different
iova address.
The caller can use the follow sample code to map phy and iova address.

eg:
struct iommu_domain *domain = iommu_domain_alloc(bus);
iommu_attach_device(domain, dev);
struct iova_domain *iovad = (struct iova_domain *)m_dev->archdata.iommu;
struct iova * t_iova = alloc_iova(iovad, size, limit_pfn, align);
iommu_map(domain, t_iova->pfn_lo << 12, phy_addr, size, port);

The patch sets are based on 4.4-RC1

Chen Feng (3):
  docs: iommu: Documentation for iommu in hi6220 SoC
  iommu/hisilicon: Add hi6220-SoC smmu driver
  arm64: dts: Add dts node for hi6220 smmu driver

 .../bindings/iommu/hisi,hi6220-iommu.txt   |  32 ++
 arch/arm64/boot/dts/hisilicon/hi6220.dtsi  |  13 +
 drivers/iommu/Kconfig  |  11 +
 drivers/iommu/Makefile |   1 +
 drivers/iommu/hi6220_iommu.c   | 492 +
 5 files changed, 549 insertions(+)
 create mode 100644 
Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
 create mode 100644 drivers/iommu/hi6220_iommu.c

-- 
1.9.1

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


[PATCH 1/4] iommu/amd: Do proper access checking before calling handle_mm_fault()

2015-11-17 Thread Joerg Roedel
From: Joerg Roedel 

The handle_mm_fault function expects the caller to do the
access checks. Not doing so and calling the function with
wrong permissions is a bug (catched by a BUG_ON).
So fix this bug by adding proper access checking to the io
page-fault code in the AMD IOMMUv2 driver.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu_v2.c | 20 ++--
 1 file changed, 18 insertions(+), 2 deletions(-)

diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index d21d4ed..7caf2fa 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -494,6 +494,22 @@ static void handle_fault_error(struct fault *fault)
}
 }
 
+static bool access_error(struct vm_area_struct *vma, struct fault *fault)
+{
+   unsigned long requested = 0;
+
+   if (fault->flags & PPR_FAULT_EXEC)
+   requested |= VM_EXEC;
+
+   if (fault->flags & PPR_FAULT_READ)
+   requested |= VM_READ;
+
+   if (fault->flags & PPR_FAULT_WRITE)
+   requested |= VM_WRITE;
+
+   return (requested & ~vma->vm_flags) != 0;
+}
+
 static void do_fault(struct work_struct *work)
 {
struct fault *fault = container_of(work, struct fault, work);
@@ -516,8 +532,8 @@ static void do_fault(struct work_struct *work)
goto out;
}
 
-   if (!(vma->vm_flags & (VM_READ | VM_EXEC | VM_WRITE))) {
-   /* handle_mm_fault would BUG_ON() */
+   /* Check if we have the right permissions on the vma */
+   if (access_error(vma, fault)) {
up_read(&mm->mmap_sem);
handle_fault_error(fault);
goto out;
-- 
1.9.1

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


[PATCH 0/4 v2] Implement access checks in iommu page fault paths

2015-11-17 Thread Joerg Roedel
Hi,

here is the second version of the patch-set to implement
proper access checks into the io-page-fault handlers of the
AMD IOMMU and Intel VT-d drivers.

Two additional patches clean up the AMD part a bit further.
Since I can't test this this code myself due to lack of
hardware or software that utilizes it, I'd appreciate some
external testing.

It took me a while to get these out, mostly because I tried
to setup my own HSA test environment to at least test the
AMD changes myself. That failed, so I am sending this out
with another request for testing.

Oded, Jesse, would you two please test these patches and
report back? Thanks a lot!


Joerg

Changes since v1:

* Updated the access_error functions based on
  Linus' feedback
* Rebased to v4.4-rc1

Joerg Roedel (4):
  iommu/amd: Do proper access checking before calling handle_mm_fault()
  iommu/amd: Correctly set flags for handle_mm_fault call
  iommu/amd: Cleanup error handling in do_fault()
  iommu/vt-d: Do access checks before calling handle_mm_fault()

 drivers/iommu/amd_iommu_v2.c | 54 +++-
 drivers/iommu/intel-svm.c| 20 
 2 files changed, 53 insertions(+), 21 deletions(-)

-- 
1.9.1

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


[PATCH 3/4] iommu/amd: Cleanup error handling in do_fault()

2015-11-17 Thread Joerg Roedel
From: Joerg Roedel 

Get rid of the three error paths that look the same and move
error handling to a single place.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu_v2.c | 24 
 1 file changed, 8 insertions(+), 16 deletions(-)

diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index a7edbd6..6a28b74 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -514,10 +514,10 @@ static void do_fault(struct work_struct *work)
 {
struct fault *fault = container_of(work, struct fault, work);
struct vm_area_struct *vma;
+   int ret = VM_FAULT_ERROR;
unsigned int flags = 0;
struct mm_struct *mm;
u64 address;
-   int ret;
 
mm = fault->state->mm;
address = fault->address;
@@ -529,31 +529,23 @@ static void do_fault(struct work_struct *work)
 
down_read(&mm->mmap_sem);
vma = find_extend_vma(mm, address);
-   if (!vma || address < vma->vm_start) {
+   if (!vma || address < vma->vm_start)
/* failed to get a vma in the right range */
-   up_read(&mm->mmap_sem);
-   handle_fault_error(fault);
goto out;
-   }
 
/* Check if we have the right permissions on the vma */
-   if (access_error(vma, fault)) {
-   up_read(&mm->mmap_sem);
-   handle_fault_error(fault);
+   if (access_error(vma, fault))
goto out;
-   }
 
ret = handle_mm_fault(mm, vma, address, flags);
-   if (ret & VM_FAULT_ERROR) {
-   /* failed to service fault */
-   up_read(&mm->mmap_sem);
-   handle_fault_error(fault);
-   goto out;
-   }
 
+out:
up_read(&mm->mmap_sem);
 
-out:
+   if (ret & VM_FAULT_ERROR)
+   /* failed to service fault */
+   handle_fault_error(fault);
+
finish_pri_tag(fault->dev_state, fault->state, fault->tag);
 
put_pasid_state(fault->state);
-- 
1.9.1

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


[PATCH 2/4] iommu/amd: Correctly set flags for handle_mm_fault call

2015-11-17 Thread Joerg Roedel
From: Joerg Roedel 

Instead of just checking for a write access, calculate the
flags that are passed to handle_mm_fault() more precisly and
use the pre-defined macros.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/amd_iommu_v2.c | 14 +-
 1 file changed, 9 insertions(+), 5 deletions(-)

diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index 7caf2fa..a7edbd6 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -513,16 +513,20 @@ static bool access_error(struct vm_area_struct *vma, 
struct fault *fault)
 static void do_fault(struct work_struct *work)
 {
struct fault *fault = container_of(work, struct fault, work);
-   struct mm_struct *mm;
struct vm_area_struct *vma;
+   unsigned int flags = 0;
+   struct mm_struct *mm;
u64 address;
-   int ret, write;
-
-   write = !!(fault->flags & PPR_FAULT_WRITE);
+   int ret;
 
mm = fault->state->mm;
address = fault->address;
 
+   if (fault->flags & PPR_FAULT_USER)
+   flags |= FAULT_FLAG_USER;
+   if (fault->flags & PPR_FAULT_WRITE)
+   flags |= FAULT_FLAG_WRITE;
+
down_read(&mm->mmap_sem);
vma = find_extend_vma(mm, address);
if (!vma || address < vma->vm_start) {
@@ -539,7 +543,7 @@ static void do_fault(struct work_struct *work)
goto out;
}
 
-   ret = handle_mm_fault(mm, vma, address, write);
+   ret = handle_mm_fault(mm, vma, address, flags);
if (ret & VM_FAULT_ERROR) {
/* failed to service fault */
up_read(&mm->mmap_sem);
-- 
1.9.1

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


[PATCH 4/4] iommu/vt-d: Do access checks before calling handle_mm_fault()

2015-11-17 Thread Joerg Roedel
From: Joerg Roedel 

Not doing so is a bug and might trigger a BUG_ON in
handle_mm_fault(). So add the proper permission checks
before calling into mm code.

Signed-off-by: Joerg Roedel 
---
 drivers/iommu/intel-svm.c | 20 
 1 file changed, 20 insertions(+)

diff --git a/drivers/iommu/intel-svm.c b/drivers/iommu/intel-svm.c
index c69e3f9..5046483 100644
--- a/drivers/iommu/intel-svm.c
+++ b/drivers/iommu/intel-svm.c
@@ -484,6 +484,23 @@ struct page_req_dsc {
 };
 
 #define PRQ_RING_MASK ((0x1000 << PRQ_ORDER) - 0x10)
+
+static bool access_error(struct vm_area_struct *vma, struct page_req_dsc *req)
+{
+   unsigned long requested = 0;
+
+   if (req->exe_req)
+   requested |= VM_EXEC;
+
+   if (req->rd_req)
+   requested |= VM_READ;
+
+   if (req->wr_req)
+   requested |= VM_WRITE;
+
+   return (requested & ~vma->vm_flags) != 0;
+}
+
 static irqreturn_t prq_event_thread(int irq, void *d)
 {
struct intel_iommu *iommu = d;
@@ -539,6 +556,9 @@ static irqreturn_t prq_event_thread(int irq, void *d)
if (!vma || address < vma->vm_start)
goto invalid;
 
+   if (access_error(vma, req))
+   goto invalid;
+
ret = handle_mm_fault(svm->mm, vma, address,
  req->wr_req ? FAULT_FLAG_WRITE : 0);
if (ret & VM_FAULT_ERROR)
-- 
1.9.1

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


Re: [RFC V3] iommu: arm-smmu: correct group reference count

2015-11-17 Thread Will Deacon
On Tue, Nov 10, 2015 at 09:56:26AM +0800, Peng Fan wrote:
> The basic flow for add a device:
>  arm_smmu_add_device
> |->iommu_group_get_for_dev
> |->iommu_group_get
>  return group;  (1)
> |->ops->device_group : Init/increase reference count to/by 1.
> |->iommu_group_add_device : Increase reference count by 1.
>return group   (2)
> |->return 0;
> 
> Since we are adding one device, the flow is (2) and the group reference
> count will be increased by 2. So, we need to add iommu_group_put at the
> end of arm_smmu_add_device to decrease the count by 1.
> 
> Signed-off-by: Peng Fan 
> Cc: Will Deacon 
> ---
>  drivers/iommu/arm-smmu-v3.c | 7 ++-
>  drivers/iommu/arm-smmu.c| 2 ++
>  2 files changed, 8 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index 4e5118a..ac333ee 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -1825,8 +1825,10 @@ static int arm_smmu_add_device(struct device *dev)
>   pci_for_each_dma_alias(pdev, __arm_smmu_get_pci_sid, &sid);
>   for (i = 0; i < smmu_group->num_sids; ++i) {
>   /* If we already know about this SID, then we're done */
> - if (smmu_group->sids[i] == sid)
> + if (smmu_group->sids[i] == sid) {
> + iommu_group_put(group);
>   return 0;
> + }
>   }
>  
>   /* Check the SID is in range of the SMMU and our stream table */
> @@ -1855,6 +1857,9 @@ static int arm_smmu_add_device(struct device *dev)
>   /* Add the new SID */
>   sids[smmu_group->num_sids - 1] = sid;
>   smmu_group->sids = sids;
> +
> + iommu_group_put(group);
> +
>   return 0;

I still think this is wrong for the failure path. If we fail during
add_device, then we want to put things back like they were, which is
what the out_put_group label is for. That means dropping the refcount
for the group *and* the refcount for the device. The nasty part is that
we don't know if we were responsible for adding the device to the group,
but it looks like we already assume that in ->remove_device.

The best bet is probably something like the diff below.

Thoughts?

Will

--->8

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index 86480480895d..db03c2fb1319 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1804,13 +1804,13 @@ static int arm_smmu_add_device(struct device *dev)
smmu = arm_smmu_get_for_pci_dev(pdev);
if (!smmu) {
ret = -ENOENT;
-   goto out_put_group;
+   goto out_remove_dev;
}
 
smmu_group = kzalloc(sizeof(*smmu_group), GFP_KERNEL);
if (!smmu_group) {
ret = -ENOMEM;
-   goto out_put_group;
+   goto out_remove_dev;
}
 
smmu_group->ste.valid   = true;
@@ -1826,20 +1826,20 @@ static int arm_smmu_add_device(struct device *dev)
for (i = 0; i < smmu_group->num_sids; ++i) {
/* If we already know about this SID, then we're done */
if (smmu_group->sids[i] == sid)
-   return 0;
+   goto out_put_group;
}
 
/* Check the SID is in range of the SMMU and our stream table */
if (!arm_smmu_sid_in_range(smmu, sid)) {
ret = -ERANGE;
-   goto out_put_group;
+   goto out_remove_dev;
}
 
/* Ensure l2 strtab is initialised */
if (smmu->features & ARM_SMMU_FEAT_2_LVL_STRTAB) {
ret = arm_smmu_init_l2_strtab(smmu, sid);
if (ret)
-   goto out_put_group;
+   goto out_remove_dev;
}
 
/* Resize the SID array for the group */
@@ -1849,16 +1849,20 @@ static int arm_smmu_add_device(struct device *dev)
if (!sids) {
smmu_group->num_sids--;
ret = -ENOMEM;
-   goto out_put_group;
+   goto out_remove_dev;
}
 
/* Add the new SID */
sids[smmu_group->num_sids - 1] = sid;
smmu_group->sids = sids;
-   return 0;
 
 out_put_group:
iommu_group_put(group);
+   return 0;
+
+out_remove_dev:
+   iommu_group_remove_device(dev);
+   iommu_group_put(group);
return ret;
 }
 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH] IOMMU: arm-smmu-v3: Use STE.S1STALLD only when supported

2015-11-17 Thread Will Deacon
Hi Prem,

Thanks for the patch. Just a few minor comments...

On Mon, Nov 16, 2015 at 02:18:20PM +0530, pmall...@broadcom.com wrote:
> From: Prem Mallappa 
> 
> Also fix the STALLD check.

Can you extend the commit message please to explain that it is ILLEGAL
to set STE.S1STALLD to 1 if stage 1 is enabled and either the stall or
terminate models are not supported?

> Signed-off-by: Prem Mallappa 
> ---
>  drivers/iommu/arm-smmu-v3.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
> index ed409cb..804671c 100644
> --- a/drivers/iommu/arm-smmu-v3.c
> +++ b/drivers/iommu/arm-smmu-v3.c
> @@ -38,7 +38,9 @@
>  #define IDR0_ST_LVL_SHIFT27
>  #define IDR0_ST_LVL_MASK 0x3
>  #define IDR0_ST_LVL_2LVL (1 << IDR0_ST_LVL_SHIFT)
> -#define IDR0_STALL_MODEL (3 << 24)
> +#define IDR0_STALL_SHIFT 24

To keep the style consistent, can you also add IDR0_STALL_MASK please...

> +#define IDR0_STALL_MODEL_STALL   0x0
> +#define IDR0_STALL_MODEL_FORCE   0x2

... and shift these guys left by IDR0_STALL_SHIFT?

>
>  #define IDR0_TTENDIAN_SHIFT  21
>  #define IDR0_TTENDIAN_MASK   0x3
>  #define IDR0_TTENDIAN_LE (2 << IDR0_TTENDIAN_SHIFT)
> @@ -1051,12 +1053,14 @@ static void arm_smmu_write_strtab_ent(struct 
> arm_smmu_device *smmu, u32 sid,
>STRTAB_STE_1_S1C_CACHE_WBRA
><< STRTAB_STE_1_S1COR_SHIFT |
>STRTAB_STE_1_S1C_SH_ISH << STRTAB_STE_1_S1CSH_SHIFT |
> -  STRTAB_STE_1_S1STALLD |
>  #ifdef CONFIG_PCI_ATS
>STRTAB_STE_1_EATS_TRANS << STRTAB_STE_1_EATS_SHIFT |
>  #endif
>STRTAB_STE_1_STRW_NSEL1 << STRTAB_STE_1_STRW_SHIFT);
>  
> + if (smmu->features & ARM_SMMU_FEAT_STALLS)
> + dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
> +
>   val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK
>   << STRTAB_STE_0_S1CTXPTR_SHIFT) |
>   STRTAB_STE_0_CFG_S1_TRANS;
> @@ -2483,8 +2487,14 @@ static int arm_smmu_device_probe(struct 
> arm_smmu_device *smmu)
>   dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent 
> property (%s)\n",
>coherent ? "true" : "false");
>  
> - if (reg & IDR0_STALL_MODEL)
> + switch ((reg >> IDR0_STALL_SHIFT) & 0x3) {

Then structure this more like the TTENDIAN code:

  switch (reg & IDR0_STALL_MASK << IDR0_STALL_SHIFT) {

> + case IDR0_STALL_MODEL_STALL:
> + case IDR0_STALL_MODEL_FORCE:
>   smmu->features |= ARM_SMMU_FEAT_STALLS;
> + break;
> + default:
> + break;
> + }

I think you can drop the default case, or does GCC complain?

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


[PATCH] iommu/arm-smmu: Convert DMA buffer allocations to the managed API

2015-11-17 Thread Will Deacon
The ARM SMMUv3 driver uses dma_{alloc,free}_coherent to manage its
queues and configuration data structures.

This patch converts the driver to the managed (dmam_*) API, so that
resources are freed automatically on device teardown. This greatly
simplifies the failure paths and allows us to remove a bunch of
handcrafted freeing code.

Signed-off-by: Will Deacon 
---
 drivers/iommu/arm-smmu-v3.c | 132 +++-
 1 file changed, 21 insertions(+), 111 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index e0032c098b32..86480480895d 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -1122,8 +1122,8 @@ static int arm_smmu_init_l2_strtab(struct arm_smmu_device 
*smmu, u32 sid)
strtab = &cfg->strtab[(sid >> STRTAB_SPLIT) * STRTAB_L1_DESC_DWORDS];
 
desc->span = STRTAB_SPLIT + 1;
-   desc->l2ptr = dma_zalloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
- GFP_KERNEL);
+   desc->l2ptr = dmam_alloc_coherent(smmu->dev, size, &desc->l2ptr_dma,
+ GFP_KERNEL | __GFP_ZERO);
if (!desc->l2ptr) {
dev_err(smmu->dev,
"failed to allocate l2 stream table for SID %u\n",
@@ -1428,10 +1428,10 @@ static void arm_smmu_domain_free(struct iommu_domain 
*domain)
struct arm_smmu_s1_cfg *cfg = &smmu_domain->s1_cfg;
 
if (cfg->cdptr) {
-   dma_free_coherent(smmu_domain->smmu->dev,
- CTXDESC_CD_DWORDS << 3,
- cfg->cdptr,
- cfg->cdptr_dma);
+   dmam_free_coherent(smmu_domain->smmu->dev,
+  CTXDESC_CD_DWORDS << 3,
+  cfg->cdptr,
+  cfg->cdptr_dma);
 
arm_smmu_bitmap_free(smmu->asid_map, cfg->cd.asid);
}
@@ -1456,8 +1456,9 @@ static int arm_smmu_domain_finalise_s1(struct 
arm_smmu_domain *smmu_domain,
if (IS_ERR_VALUE(asid))
return asid;
 
-   cfg->cdptr = dma_zalloc_coherent(smmu->dev, CTXDESC_CD_DWORDS << 3,
-&cfg->cdptr_dma, GFP_KERNEL);
+   cfg->cdptr = dmam_alloc_coherent(smmu->dev, CTXDESC_CD_DWORDS << 3,
+&cfg->cdptr_dma,
+GFP_KERNEL | __GFP_ZERO);
if (!cfg->cdptr) {
dev_warn(smmu->dev, "failed to allocate context descriptor\n");
ret = -ENOMEM;
@@ -1936,7 +1937,7 @@ static int arm_smmu_init_one_queue(struct arm_smmu_device 
*smmu,
 {
size_t qsz = ((1 << q->max_n_shift) * dwords) << 3;
 
-   q->base = dma_alloc_coherent(smmu->dev, qsz, &q->base_dma, GFP_KERNEL);
+   q->base = dmam_alloc_coherent(smmu->dev, qsz, &q->base_dma, GFP_KERNEL);
if (!q->base) {
dev_err(smmu->dev, "failed to allocate queue (0x%zx bytes)\n",
qsz);
@@ -1956,23 +1957,6 @@ static int arm_smmu_init_one_queue(struct 
arm_smmu_device *smmu,
return 0;
 }
 
-static void arm_smmu_free_one_queue(struct arm_smmu_device *smmu,
-   struct arm_smmu_queue *q)
-{
-   size_t qsz = ((1 << q->max_n_shift) * q->ent_dwords) << 3;
-
-   dma_free_coherent(smmu->dev, qsz, q->base, q->base_dma);
-}
-
-static void arm_smmu_free_queues(struct arm_smmu_device *smmu)
-{
-   arm_smmu_free_one_queue(smmu, &smmu->cmdq.q);
-   arm_smmu_free_one_queue(smmu, &smmu->evtq.q);
-
-   if (smmu->features & ARM_SMMU_FEAT_PRI)
-   arm_smmu_free_one_queue(smmu, &smmu->priq.q);
-}
-
 static int arm_smmu_init_queues(struct arm_smmu_device *smmu)
 {
int ret;
@@ -1982,49 +1966,20 @@ static int arm_smmu_init_queues(struct arm_smmu_device 
*smmu)
ret = arm_smmu_init_one_queue(smmu, &smmu->cmdq.q, ARM_SMMU_CMDQ_PROD,
  ARM_SMMU_CMDQ_CONS, CMDQ_ENT_DWORDS);
if (ret)
-   goto out;
+   return ret;
 
/* evtq */
ret = arm_smmu_init_one_queue(smmu, &smmu->evtq.q, ARM_SMMU_EVTQ_PROD,
  ARM_SMMU_EVTQ_CONS, EVTQ_ENT_DWORDS);
if (ret)
-   goto out_free_cmdq;
+   return ret;
 
/* priq */
if (!(smmu->features & ARM_SMMU_FEAT_PRI))
return 0;
 
-   ret = arm_smmu_init_one_queue(smmu, &smmu->priq.q, ARM_SMMU_PRIQ_PROD,
- ARM_SMMU_PRIQ_CONS, PRIQ_ENT_DWORDS);
-   if (ret)
-   goto out_free_evtq;
-
-   return 0;
-
-out_free_evtq:
-   arm_smmu_free_one_queue(smmu, &smmu->evtq.q);
-out_free_cmdq:
-   arm_smmu_free_one_queue(smmu, &smmu->cmdq.q);
-out:
-   

[PATCH] IOMMU: arm-smmu-v3: Use STE.S1STALLD only when supported

2015-11-17 Thread pmallapp
From: Prem Mallappa 

Also fix the STALLD check.

Signed-off-by: Prem Mallappa 
---
 drivers/iommu/arm-smmu-v3.c | 16 +---
 1 file changed, 13 insertions(+), 3 deletions(-)

diff --git a/drivers/iommu/arm-smmu-v3.c b/drivers/iommu/arm-smmu-v3.c
index ed409cb..804671c 100644
--- a/drivers/iommu/arm-smmu-v3.c
+++ b/drivers/iommu/arm-smmu-v3.c
@@ -38,7 +38,9 @@
 #define IDR0_ST_LVL_SHIFT  27
 #define IDR0_ST_LVL_MASK   0x3
 #define IDR0_ST_LVL_2LVL   (1 << IDR0_ST_LVL_SHIFT)
-#define IDR0_STALL_MODEL   (3 << 24)
+#define IDR0_STALL_SHIFT   24
+#define IDR0_STALL_MODEL_STALL 0x0
+#define IDR0_STALL_MODEL_FORCE 0x2
 #define IDR0_TTENDIAN_SHIFT21
 #define IDR0_TTENDIAN_MASK 0x3
 #define IDR0_TTENDIAN_LE   (2 << IDR0_TTENDIAN_SHIFT)
@@ -1051,12 +1053,14 @@ static void arm_smmu_write_strtab_ent(struct 
arm_smmu_device *smmu, u32 sid,
 STRTAB_STE_1_S1C_CACHE_WBRA
 << STRTAB_STE_1_S1COR_SHIFT |
 STRTAB_STE_1_S1C_SH_ISH << STRTAB_STE_1_S1CSH_SHIFT |
-STRTAB_STE_1_S1STALLD |
 #ifdef CONFIG_PCI_ATS
 STRTAB_STE_1_EATS_TRANS << STRTAB_STE_1_EATS_SHIFT |
 #endif
 STRTAB_STE_1_STRW_NSEL1 << STRTAB_STE_1_STRW_SHIFT);
 
+   if (smmu->features & ARM_SMMU_FEAT_STALLS)
+   dst[1] |= cpu_to_le64(STRTAB_STE_1_S1STALLD);
+
val |= (ste->s1_cfg->cdptr_dma & STRTAB_STE_0_S1CTXPTR_MASK
<< STRTAB_STE_0_S1CTXPTR_SHIFT) |
STRTAB_STE_0_CFG_S1_TRANS;
@@ -2483,8 +2487,14 @@ static int arm_smmu_device_probe(struct arm_smmu_device 
*smmu)
dev_warn(smmu->dev, "IDR0.COHACC overridden by dma-coherent 
property (%s)\n",
 coherent ? "true" : "false");
 
-   if (reg & IDR0_STALL_MODEL)
+   switch ((reg >> IDR0_STALL_SHIFT) & 0x3) {
+   case IDR0_STALL_MODEL_STALL:
+   case IDR0_STALL_MODEL_FORCE:
smmu->features |= ARM_SMMU_FEAT_STALLS;
+   break;
+   default:
+   break;
+   }
 
if (reg & IDR0_S1P)
smmu->features |= ARM_SMMU_FEAT_TRANS_S1;
-- 
2.6.0

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


Re: [PATCH 1/3] docs: iommu: Documentation for iommu in hi6220 SoC

2015-11-17 Thread Rob Herring
On Tue, Nov 17, 2015 at 5:57 AM, Chen Feng  wrote:
> Documentation for hi6220 iommu driver.

Please use get_maintainers.pl and re-send to correct lists
(devicet...@vger.kernel.org).

>
> Signed-off-by: Chen Feng 
> ---
>  .../bindings/iommu/hisi,hi6220-iommu.txt   | 32 
> ++
>  1 file changed, 32 insertions(+)
>  create mode 100644 
> Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
>
> diff --git a/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt 
> b/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
> new file mode 100644
> index 000..44f9101
> --- /dev/null
> +++ b/Documentation/devicetree/bindings/iommu/hisi,hi6220-iommu.txt
> @@ -0,0 +1,32 @@
> +Hi6220 SoC SMMU Device Driver devicetree document
> +The media system shared the same smmu IP to access DDR memory. And all
> +media IP used the same page table.
> +
> +Below binding describes the system mmu for media system in hi6220 platform
> +
> +Required properties:
> +- compatible: should contain "hisilicon,hi6220-smmu".
> +- reg: A tuple of base address and size of System MMU registers.
> +- clocks: a list of phandle + clock-specifier pairs, one for each entry
> +  in clock-names.
> +- clock-names: should contain:
> +  * "smmu"
> +  * "media-sc"
> +  * "smmu-peri"
> +- interrupts: An interrupt specifier for interrupt signal of System MMU.
> +- #iommu-cells: The iommu-cells should be 0. Because no additional 
> information
> +  needs to be encoded in the specifier.
> +
> +Examples:
> +   iommu@f421 {
> +   compatible = "hisilicon,hi6220-smmu";
> +   reg = <0x0 0xf421 0x0 0x1000>;
> +   interrupts = ;
> +   clocks = <&sys_ctrl HI6220_MMU_CLK>,
> +<&media_ctrl HI6220_MED_MMU>,
> +<&sys_ctrl HI6220_MEDIA_PLL_SRC>;
> +   clock-names = "smmu",
> + "media-sc",
> + "smmu-peri";
> +   #iommu-cells = <0>;
> +   };
> --
> 1.9.1
>
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: KVM PCI passthrough problems after kernel v4.2

2015-11-17 Thread Juhani Rautiainen
Hi!

Thanks a lot for the help. I switched to vfio and got NIC working
again. Now I just have to figure out what I have to change to get this
to persist through the host boots. To tell the truth I couldn't quite
parse from that commit message that my device would stop working:).
The error messages in this area are quite uninformative anyway. KVM
could for instance warn for using deprecated method (kernel does it in
many other places). When I did that configuration, I did it using KVM
PCI passthrough pages and the method there was this deprecated method
(and it still was when I switched to Centos7, because I lost my config
through stupid mistake and had to do it all over again). And I thought
that I've been following this area in LKML but somehow missed the
whole deprecation business:).

Thanks,
-Juhani

On Fri, Nov 13, 2015 at 12:00 AM, Alex Williamson
 wrote:
> On Thu, 2015-11-12 at 23:36 +0200, Juhani Rautiainen wrote:
>> Hi!
>>
>> I've been using KVM PCI passthrough with a dual-port NIC for over a
>> year. I just upgraded to v4.3 from v4.1.4 and PCI passthrough stopped
>> working. I checked with v4.1.9 and it still works there. Version 4.2
>> seems to point after which my system doesn't work. How can I help to
>> narrow down the cause of the problem? I checked the intel-iommu.c and
>> there seem to have been lots of changes between 4.1.9 and 4.2 in
>> drivers/iommu/intel-iommu.c. My motherboard is Asus P8C WS which has
>> Intel C216 chipset. CPU is Intel I5-3470. From v4.2 onwards
>> passthrough fails with:
>>
>> pci-stub :02:00.0: kvm assign device failed ret -22.
>
> This happens when kvm calls iommu_attach_device(), which was changed in
> v4.2 to fail with -EINVAL (-22) when the device is part of a
> non-singleton iommu group.  Legacy kvm device assignment is not iommu
> group aware and has been deprecated for some time.  Have you considered
> using vfio for device assignment instead?
>
> For reference, here's the comment that made this change:
>
> commit 426a273834eae65abcfc7132a21a85b3151e0bce
> Author: Joerg Roedel 
> Date:   Thu May 28 18:41:30 2015 +0200
>
> iommu: Limit iommu_attach/detach_device to devices with their own group
>
> This patch changes the behavior of the iommu_attach_device
> and iommu_detach_device functions. With this change these
> functions only work on devices that have their own group.
> For all other devices the iommu_group_attach/detach
> functions must be used.
>
> Signed-off-by: Joerg Roedel 
>
>



-- 
Juhani Rautiainen   jra...@iki.fi
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [PATCH v2] iommu/ipmmu-vmsa: Include SoC part number in DT binding docs

2015-11-17 Thread Rob Herring
On Tue, Nov 17, 2015 at 12:53:20PM +0900, Magnus Damm wrote:
> From: Magnus Damm 
> 
> Add part numbers for APE6 and current set of R-Car Gen2 SoCs to the
> IPMMU DT binding documentation. The example is also updated to show
> how the generic compatible string may be used as fallback.
> 
> Signed-off-by: Magnus Damm 

Acked-by: Rob Herring 

> ---
> 
>  Changes since V1:
>  - Updated compat string section to the following:
>"Must contain SoC-specific and generic entries from below."
> 
>  Thanks to Laurent for feedback!
> 
>  Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt |   12 
> --
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> --- 0001/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
> +++ work/Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt   
> 2015-11-17 12:45:26.080513000 +0900
> @@ -7,7 +7,15 @@ connected to the IPMMU through a port ca
>  
>  Required Properties:
>  
> -  - compatible: Must contain "renesas,ipmmu-vmsa".
> +  - compatible: Must contain SoC-specific and generic entries from below.
> +
> +- "renesas,ipmmu-r8a73a4" for the R8A73A4 (R-Mobile APE6) IPMMU.
> +- "renesas,ipmmu-r8a7790" for the R8A7790 (R-Car H2) IPMMU.
> +- "renesas,ipmmu-r8a7791" for the R8A7791 (R-Car M2-W) IPMMU.
> +- "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
> +- "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
> +- "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
> +
>- reg: Base address and size of the IPMMU registers.
>- interrupts: Specifiers for the MMU fault interrupts. For instances that
>  support secure mode two interrupts must be specified, for non-secure and
> @@ -27,7 +35,7 @@ node with the following property:
>  Example: R8A7791 IPMMU-MX and VSP1-D0 bus master
>  
>   ipmmu_mx: mmu@fe951000 {
> - compatible = "renasas,ipmmu-vmsa";
> + compatible = "renasas,ipmmu-r8a7791", "renasas,ipmmu-vmsa";
>   reg = <0 0xfe951000 0 0x1000>;
>   interrupts = <0 222 IRQ_TYPE_LEVEL_HIGH>,
><0 221 IRQ_TYPE_LEVEL_HIGH>;
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu


Re: [Patch v2 0/9] Fix AMD IOMMU faults in kdump kernel

2015-11-17 Thread Baoquan He
Hi Joerg,

Could you please help have a look and give some suggestions on this
issue?

Or any one else who is familiar with AMD IOMMU have any idea about
this?

Thanks
Baoquan
On 11/06/15 at 08:10pm, Baoquan He wrote:
> This is v2 draft patch set. It mainly functions as the following steps:
> 
> 1. Checking if it's in kdump kernel and previously enabled
> 2. If yes do below operatons:
> a. Do not disable amd iommu and do not touch dev tables before coping old 
> dev tables
> b. Copy dev table from old kernel and set the old domain id in 
> amd_iommu_pd_alloc_bitmap
> c. Copy irq tables from old kernel
> d. Copy command buffer and event buffer
> e. Don't call update_domain() to set domain->pt_root to dev entries 
> before device driver initialization.
> f. Reset the pre-enabled status in case IOMMU_DMA_OPS of state_next(). 
> 
> Existed problems:
> 
> 1. It always prints the following message whenever do a flush:
> 
>   "AMD-Vi: Completion-Wait loop timed out"
> 
> 2. Maybe there's someing wrong with the old irq remapping handling, the hard 
> disk can't be brought up
> successfully. You can check the attached kdump kernel boot log with this 
> patchset applied.
> 
> Baoquan He (9):
>   iommu/amd: Use standard bitmap operation to set bitmap
>   iommu/amd: Detect pre enabled translation
>   iommu/amd: make several functions global
>   iommu/amd: add copy_irq_table function
>   iommu/amd: Add function copy_dev_tables
>   iommu/amd: Add functions copy_command_buffer/copy_event_buffer
>   iommu/amd: copy old tables and do not update dev tables before driver
> init
>   iommu/amd: Do not update the information of domain to devtables before
> device driver init
>   iommu/amd: Clear the iommu pre enabled setting
> 
>  drivers/iommu/amd_iommu.c   |  27 +++---
>  drivers/iommu/amd_iommu_init.c  | 208 
> +---
>  drivers/iommu/amd_iommu_proto.h |   6 ++
>  drivers/iommu/amd_iommu_types.h |   4 +
>  4 files changed, 198 insertions(+), 47 deletions(-)
> 
> -- 
> 2.4.0
> 
___
iommu mailing list
iommu@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/iommu