[PATCH] kernel/dma: export dma_alloc_from_contiguous to modules

2019-07-10 Thread miles.chen
From: Miles Chen 

This change exports dma_alloc_from_contiguous and
dma_release_from_contiguous to modules.

Currently, we can add a reserve a memory node in dts files, make
it a CMA memory by setting compatible = "shared-dma-pool",
and setup the dev->cma_area by using of_reserved_mem_device_init_by_idx().

Export dma_alloc_from_contiguous and dma_release_from_contiguous, so we
can allocate/free from/to dev->cma_area in kernel modules.

Signed-off-by: Miles Chen 
---
 kernel/dma/contiguous.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/kernel/dma/contiguous.c b/kernel/dma/contiguous.c
index b2a87905846d..d5920bdedc77 100644
--- a/kernel/dma/contiguous.c
+++ b/kernel/dma/contiguous.c
@@ -197,6 +197,7 @@ struct page *dma_alloc_from_contiguous(struct device *dev, 
size_t count,
 
return cma_alloc(dev_get_cma_area(dev), count, align, no_warn);
 }
+EXPORT_SYMBOL_GPL(dma_alloc_from_contiguous);
 
 /**
  * dma_release_from_contiguous() - release allocated pages
@@ -213,6 +214,7 @@ bool dma_release_from_contiguous(struct device *dev, struct 
page *pages,
 {
return cma_release(dev_get_cma_area(dev), pages, count);
 }
+EXPORT_SYMBOL_GPL(dma_release_from_contiguous);
 
 /*
  * Support for reserved memory regions defined in device tree
-- 
2.18.0



[RFC PATCH] iommu: io-pgtable: Drop WARN for empty PTEs on unmap

2019-07-10 Thread Rob Herring
If a region has been mapped sparsely (such as on page faults), the user
has to keep track of what was mapped or not in order to avoid warnings
when unmapping the entire region. Remove the WARN on empty PTEs to allow
unmapping sparsely mapped regions.

Cc: Will Deacon 
Cc: Robin Murphy 
Cc: Joerg Roedel 
Cc: linux-arm-ker...@lists.infradead.org
Cc: iommu@lists.linux-foundation.org
Signed-off-by: Rob Herring 
---
This is needed for large (up to 1GB AIUI) scratch buffers on panfrost 
which are mapped on demand on GPU page faults and can be unmapped on 
memory pressure. Alternatively, I'd need to have a bitmap of mapped 
pages to track what is mapped or not. Dropping the WARN seems like a 
much simpler solution.

This will need to go thru the DRM tree once I've gotten the panfrost 
side finished, but wanted some early feedback.

Rob

 drivers/iommu/io-pgtable-arm.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 4e21efbc4459..43971638a5aa 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -611,7 +611,7 @@ static size_t __arm_lpae_unmap(struct arm_lpae_io_pgtable 
*data,
 
ptep += ARM_LPAE_LVL_IDX(iova, lvl, data);
pte = READ_ONCE(*ptep);
-   if (WARN_ON(!pte))
+   if (!pte)
return 0;
 
/* If the size matches this level, we're in the right place */
-- 
2.20.1

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


[PATCH] iommu/amd: fix a crash in iova_magazine_free_pfns

2019-07-10 Thread Qian Cai
When a system is under heavy memory pressure, the allocation in
alloc_iova_fast() could still fail even flush_rcache=true, and then
causes dma_ops_alloc_iova() return 0.

pqi_scsi_queue_command
  pqi_raid_submit_scsi_cmd_with_io_request
scsi_dma_map
  map_sg
dma_ops_alloc_iova
 alloc_iova_fast

Later, map_sg()->iommu_map_page() would probably fail due to the invalid
PFN 0, and call free_iova_fast()->iova_rcache_insert() to insert it to
the rcache. Finally, it will trigger the BUG_ON(!iova) here.

kernel BUG at drivers/iommu/iova.c:801!
Workqueue: kblockd blk_mq_run_work_fn
RIP: 0010:iova_magazine_free_pfns+0x7d/0xc0
Call Trace:
 free_cpu_cached_iovas+0xbd/0x150
 alloc_iova_fast+0x8c/0xba
 dma_ops_alloc_iova.isra.6+0x65/0xa0
 map_sg+0x8c/0x2a0
 scsi_dma_map+0xc6/0x160
 pqi_aio_submit_io+0x1f6/0x440 [smartpqi]
 pqi_scsi_queue_command+0x90c/0xdd0 [smartpqi]
 scsi_queue_rq+0x79c/0x1200
 blk_mq_dispatch_rq_list+0x4dc/0xb70
 blk_mq_sched_dispatch_requests+0x249/0x310
 __blk_mq_run_hw_queue+0x128/0x200
 blk_mq_run_work_fn+0x27/0x30
 process_one_work+0x522/0xa10
 worker_thread+0x63/0x5b0
 kthread+0x1d2/0x1f0
 ret_from_fork+0x22/0x40

Fix it by validating the return from the 2nd alloc_iova_fast() in
dma_ops_alloc_iova(), so map_sg() could handle the error condition
immediately.

Signed-off-by: Qian Cai 
---
 drivers/iommu/amd_iommu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/drivers/iommu/amd_iommu.c b/drivers/iommu/amd_iommu.c
index 73740b969e62..f24c689b4e01 100644
--- a/drivers/iommu/amd_iommu.c
+++ b/drivers/iommu/amd_iommu.c
@@ -1697,6 +1697,8 @@ static unsigned long dma_ops_alloc_iova(struct device 
*dev,
if (!pfn)
pfn = alloc_iova_fast(_dom->iovad, pages,
  IOVA_PFN(dma_mask), true);
+   if (!pfn)
+   return DMA_MAPPING_ERROR;
 
return (pfn << PAGE_SHIFT);
 }
-- 
1.8.3.1

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


[PATCH] dma-direct: Force unencrypted DMA under SME for certain DMA masks

2019-07-10 Thread Lendacky, Thomas
From: Tom Lendacky 

If a device doesn't support DMA to a physical address that includes the
encryption bit (currently bit 47, so 48-bit DMA), then the DMA must
occur to unencrypted memory. SWIOTLB is used to satisfy that requirement
if an IOMMU is not active (enabled or configured in passthrough mode).

However, commit fafadcd16595 ("swiotlb: don't dip into swiotlb pool for
coherent allocations") modified the coherent allocation support in SWIOTLB
to use the DMA direct coherent allocation support. When an IOMMU is not
active, this resulted in dma_alloc_coherent() failing for devices that
didn't support DMA addresses that included the encryption bit.

Addressing this requires changes to the force_dma_unencrypted() function
in kernel/dma/direct.c. Since the function is now non-trivial and SME/SEV
specific, update the DMA direct support to add an arch override for the
force_dma_unencrypted() function. The arch override is selected when
CONFIG_AMD_MEM_ENCRYPT is set. The arch override function resides in the
arch/x86/mm/mem_encrypt.c file and forces unencrypted DMA when either SEV
is active or SME is active and the device does not support DMA to physical
addresses that include the encryption bit.

Fixes: fafadcd16595 ("swiotlb: don't dip into swiotlb pool for coherent 
allocations")
Suggested-by: Christoph Hellwig 
Signed-off-by: Tom Lendacky 
---

Based on tree git://git.infradead.org/users/hch/dma-mapping.git for-next

 arch/x86/Kconfig  |  1 +
 arch/x86/mm/mem_encrypt.c | 30 ++
 kernel/dma/Kconfig|  3 +++
 kernel/dma/direct.c   | 19 ++-
 4 files changed, 44 insertions(+), 9 deletions(-)

diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig
index 2bbbd4d1ba31..12e02a8f9de7 100644
--- a/arch/x86/Kconfig
+++ b/arch/x86/Kconfig
@@ -1508,6 +1508,7 @@ config AMD_MEM_ENCRYPT
depends on X86_64 && CPU_SUP_AMD
select DYNAMIC_PHYSICAL_MASK
select ARCH_USE_MEMREMAP_PROT
+   select ARCH_HAS_FORCE_DMA_UNENCRYPTED
---help---
  Say yes to enable support for the encryption of system memory.
  This requires an AMD processor that supports Secure Memory
diff --git a/arch/x86/mm/mem_encrypt.c b/arch/x86/mm/mem_encrypt.c
index 51f50a7a07ef..c7a88b837c43 100644
--- a/arch/x86/mm/mem_encrypt.c
+++ b/arch/x86/mm/mem_encrypt.c
@@ -18,6 +18,10 @@
 #include 
 #include 
 #include 
+#include 
+#include 
+#include 
+#include 
 
 #include 
 #include 
@@ -351,6 +355,32 @@ bool sev_active(void)
 }
 EXPORT_SYMBOL(sev_active);
 
+/* Override for DMA direct allocation check - ARCH_HAS_FORCE_DMA_UNENCRYPTED */
+bool force_dma_unencrypted(struct device *dev)
+{
+   /*
+* For SEV, all DMA must be to unencrypted addresses.
+*/
+   if (sev_active())
+   return true;
+
+   /*
+* For SME, all DMA must be to unencrypted addresses if the
+* device does not support DMA to addresses that include the
+* encryption mask.
+*/
+   if (sme_active()) {
+   u64 dma_enc_mask = DMA_BIT_MASK(__ffs64(sme_me_mask));
+   u64 dma_dev_mask = min_not_zero(dev->coherent_dma_mask,
+   dev->bus_dma_mask);
+
+   if (dma_dev_mask <= dma_enc_mask)
+   return true;
+   }
+
+   return false;
+}
+
 /* Architecture __weak replacement functions */
 void __init mem_encrypt_free_decrypted_mem(void)
 {
diff --git a/kernel/dma/Kconfig b/kernel/dma/Kconfig
index 70f8f8d9200e..9decbba255fc 100644
--- a/kernel/dma/Kconfig
+++ b/kernel/dma/Kconfig
@@ -48,6 +48,9 @@ config ARCH_HAS_DMA_COHERENT_TO_PFN
 config ARCH_HAS_DMA_MMAP_PGPROT
bool
 
+config ARCH_HAS_FORCE_DMA_UNENCRYPTED
+   bool
+
 config DMA_NONCOHERENT_CACHE_SYNC
bool
 
diff --git a/kernel/dma/direct.c b/kernel/dma/direct.c
index b90e1aede743..fb37374dae75 100644
--- a/kernel/dma/direct.c
+++ b/kernel/dma/direct.c
@@ -23,13 +23,14 @@
 #define ARCH_ZONE_DMA_BITS 24
 #endif
 
-/*
- * For AMD SEV all DMA must be to unencrypted addresses.
- */
-static inline bool force_dma_unencrypted(void)
+#ifdef CONFIG_ARCH_HAS_FORCE_DMA_UNENCRYPTED
+bool force_dma_unencrypted(struct device *dev);
+#else
+static inline bool force_dma_unencrypted(struct device *dev)
 {
-   return sev_active();
+   return false;
 }
+#endif
 
 static void report_addr(struct device *dev, dma_addr_t dma_addr, size_t size)
 {
@@ -46,7 +47,7 @@ static void report_addr(struct device *dev, dma_addr_t 
dma_addr, size_t size)
 static inline dma_addr_t phys_to_dma_direct(struct device *dev,
phys_addr_t phys)
 {
-   if (force_dma_unencrypted())
+   if (force_dma_unencrypted(dev))
return __phys_to_dma(dev, phys);
return phys_to_dma(dev, phys);
 }
@@ -67,7 +68,7 @@ static gfp_t __dma_direct_optimal_gfp_mask(struct device 
*dev, u64 dma_mask,
if (dev->bus_dma_mask && dev->bus_dma_mask < dma_mask)

[PATCH v2] iommu: add support for drivers that manage iommu explicitly

2019-07-10 Thread Rob Clark
From: Rob Clark 

Avoid attaching any non-driver managed domain if the driver indicates
that it manages the iommu directly.

This avoids a problem on devices where the bootloader takes the SMMU out
of bypass and enables scanout, such as is the case on snapdragon aarch64
laptops and newer snapdragon android devices.  Attaching an IDENTITY or
DMA domain before the driver has a chance to intervene will break efifb
scanout and start triggering iommu faults.

If the driver manages the iommu directly (as does drm/msm), it can
shut down scanout when it is ready to take over the display, before
attaching an UNMANAGED domain.

Signed-off-by: Rob Clark 
---
v2. Move the check into arm_smmu_attach_dev() (as I *think* this is
what Robin preferred; update commit msg to focus on the display
related issue that this solves.

We also need Bjorn's patch set to inherit SMR and CB config during
init:

https://www.spinics.net/lists/arm-kernel/msg732246.html

 drivers/iommu/arm-smmu.c | 11 +++
 include/linux/device.h   |  3 ++-
 2 files changed, 13 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 1a5efa7c8767..4a80710124db 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -1411,6 +1411,17 @@ static int arm_smmu_attach_dev(struct iommu_domain 
*domain, struct device *dev)
return -ENXIO;
}
 
+   /*
+* If driver is going to manage iommu directly, then avoid
+* attaching any non driver managed domain.  There could
+* be already active dma underway (ie. scanout in case of
+* bootloader enabled display), and interfering with that
+* will make things go *boom*
+*/
+   if ((domain->type != IOMMU_DOMAIN_UNMANAGED) &&
+   dev->driver && dev->driver->driver_manages_iommu)
+   return 0;
+
/*
 * FIXME: The arch/arm DMA API code tries to attach devices to its own
 * domains between of_xlate() and add_device() - we have no way to cope
diff --git a/include/linux/device.h b/include/linux/device.h
index e138baabe01e..d98aa4d3c8c3 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -282,7 +282,8 @@ struct device_driver {
struct module   *owner;
const char  *mod_name;  /* used for built-in modules */
 
-   bool suppress_bind_attrs;   /* disables bind/unbind via sysfs */
+   bool suppress_bind_attrs:1; /* disables bind/unbind via sysfs */
+   bool driver_manages_iommu:1;/* driver manages IOMMU explicitly */
enum probe_type probe_type;
 
const struct of_device_id   *of_match_table;
-- 
2.20.1



Re: [RESEND PATCH v2 2/3] iommu/io-pgtable-arm: Add support for AARCH64 split pagetables

2019-07-10 Thread Jordan Crouse
On Wed, Jul 10, 2019 at 05:45:37PM +0100, Robin Murphy wrote:
> Hi Jordan,
> 
> On 08/07/2019 20:00, Jordan Crouse wrote:
> >Add a new sub-format ARM_64_LPAE_SPLIT_S1 to create and set up split
> >pagetables (TTBR0 and TTBR1). The initialization function sets up the
> >correct va_size and sign extension bits and programs the TCR registers.
> >Split pagetable formats use their own own map/unmap wrappers to ensure
> >that the correct pagetable is selected based on the incoming iova but
> >most of the heavy lifting is common to the other formats.
> 
> I'm somewhat concerned that this implementation is very closely tied to the
> current Adreno use-case, and won't easily generalise in future to other
> potential TTBR1 uses which have been tossed around, like
> SMMUv3-without-substream-ID.

I haven't heard about these use-cases. I figured v3 would be all PASID all the
time. If you have details, I can see if I can avoid painting v3 into a corner.

> Furthermore, even for the Adreno pretend-PASID case it appears to be a bit
> too fragile for comfort - given that a DOMAIN_ATTR_SPLIT_TABLES domain
> doesn't look any different from a regular one from the users' point of view,
> what's to stop them making "without PASID" mappings in the lower half of the
> address space, and thus unwittingly pulling the rug out from under their own
> feet upon attaching an aux domain? In fact allocating a TTBR0 table at all
> for the main domain seems like little more than a waste of memory.

That makes sense. Would it work better if we made a type ARM_64_LPAE_TTBR1_S1
that only allocated memory for TTBR1 and set TBR.EDP0 to trigger faults for
TTBR0?

Then we could get rid of most of the extra stuff in io-pgtable-arm.c and I think
that would meet most of your concerns. 

Jordan

> >
> >Signed-off-by: Jordan Crouse 
> >---
> >
> >  drivers/iommu/io-pgtable-arm.c | 261 
> > +
> >  drivers/iommu/io-pgtable.c |   1 +
> >  include/linux/io-pgtable.h |   2 +
> >  3 files changed, 240 insertions(+), 24 deletions(-)
> >
> >diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
> >index 161a7d56..aec35e5 100644
> >--- a/drivers/iommu/io-pgtable-arm.c
> >+++ b/drivers/iommu/io-pgtable-arm.c
> >@@ -118,7 +118,12 @@
> >  #define ARM_LPAE_TCR_TG0_64K   (1 << 14)
> >  #define ARM_LPAE_TCR_TG0_16K   (2 << 14)
> >+#define ARM_LPAE_TCR_TG1_4K (0 << 30)
> >+#define ARM_LPAE_TCR_TG1_64K(1 << 30)
> >+#define ARM_LPAE_TCR_TG1_16K(2 << 30)
> >+
> >  #define ARM_LPAE_TCR_SH0_SHIFT 12
> >+#define ARM_LPAE_TCR_SH1_SHIFT  28
> >  #define ARM_LPAE_TCR_SH0_MASK  0x3
> >  #define ARM_LPAE_TCR_SH_NS 0
> >  #define ARM_LPAE_TCR_SH_OS 2
> >@@ -126,6 +131,8 @@
> >  #define ARM_LPAE_TCR_ORGN0_SHIFT   10
> >  #define ARM_LPAE_TCR_IRGN0_SHIFT   8
> >+#define ARM_LPAE_TCR_ORGN1_SHIFT26
> >+#define ARM_LPAE_TCR_IRGN1_SHIFT24
> >  #define ARM_LPAE_TCR_RGN_MASK  0x3
> >  #define ARM_LPAE_TCR_RGN_NC0
> >  #define ARM_LPAE_TCR_RGN_WBWA  1
> >@@ -136,6 +143,7 @@
> >  #define ARM_LPAE_TCR_SL0_MASK  0x3
> >  #define ARM_LPAE_TCR_T0SZ_SHIFT0
> >+#define ARM_LPAE_TCR_T1SZ_SHIFT 16
> >  #define ARM_LPAE_TCR_SZ_MASK   0xf
> >  #define ARM_LPAE_TCR_PS_SHIFT  16
> >@@ -152,6 +160,14 @@
> >  #define ARM_LPAE_TCR_PS_48_BIT 0x5ULL
> >  #define ARM_LPAE_TCR_PS_52_BIT 0x6ULL
> >+#define ARM_LPAE_TCR_SEP_SHIFT  47
> >+#define ARM_LPAE_TCR_SEP_31 (0x0ULL << ARM_LPAE_TCR_SEP_SHIFT)
> >+#define ARM_LPAE_TCR_SEP_35 (0x1ULL << ARM_LPAE_TCR_SEP_SHIFT)
> >+#define ARM_LPAE_TCR_SEP_39 (0x2ULL << ARM_LPAE_TCR_SEP_SHIFT)
> >+#define ARM_LPAE_TCR_SEP_41 (0x3ULL << ARM_LPAE_TCR_SEP_SHIFT)
> >+#define ARM_LPAE_TCR_SEP_43 (0x4ULL << ARM_LPAE_TCR_SEP_SHIFT)
> >+#define ARM_LPAE_TCR_SEP_UPSTREAM   (0x7ULL << ARM_LPAE_TCR_SEP_SHIFT)
> 
> This is a specific detail of SMMUv2, and nothing to do with the LPAE/AArch64
> VMSA formats.
> 
> >+
> >  #define ARM_LPAE_MAIR_ATTR_SHIFT(n)((n) << 3)
> >  #define ARM_LPAE_MAIR_ATTR_MASK0xff
> >  #define ARM_LPAE_MAIR_ATTR_DEVICE  0x04
> >@@ -179,11 +195,12 @@ struct arm_lpae_io_pgtable {
> > struct io_pgtable   iop;
> > int levels;
> >+u32 sep;
> > size_t  pgd_size;
> > unsigned long   pg_shift;
> > unsigned long   bits_per_level;
> >-void*pgd;
> >+void*pgd[2];
> >  };
> >  typedef u64 arm_lpae_iopte;
> >@@ -426,7 +443,8 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
> >arm_lpae_io_pgtable *data,
> > arm_lpae_iopte pte;
> > if (data->iop.fmt == ARM_64_LPAE_S1 ||
> >-data->iop.fmt == ARM_32_LPAE_S1) {
> >+

Re: [RESEND PATCH v2 2/3] iommu/io-pgtable-arm: Add support for AARCH64 split pagetables

2019-07-10 Thread Robin Murphy

Hi Jordan,

On 08/07/2019 20:00, Jordan Crouse wrote:

Add a new sub-format ARM_64_LPAE_SPLIT_S1 to create and set up split
pagetables (TTBR0 and TTBR1). The initialization function sets up the
correct va_size and sign extension bits and programs the TCR registers.
Split pagetable formats use their own own map/unmap wrappers to ensure
that the correct pagetable is selected based on the incoming iova but
most of the heavy lifting is common to the other formats.


I'm somewhat concerned that this implementation is very closely tied to 
the current Adreno use-case, and won't easily generalise in future to 
other potential TTBR1 uses which have been tossed around, like 
SMMUv3-without-substream-ID.


Furthermore, even for the Adreno pretend-PASID case it appears to be a 
bit too fragile for comfort - given that a DOMAIN_ATTR_SPLIT_TABLES 
domain doesn't look any different from a regular one from the users' 
point of view, what's to stop them making "without PASID" mappings in 
the lower half of the address space, and thus unwittingly pulling the 
rug out from under their own feet upon attaching an aux domain? In fact 
allocating a TTBR0 table at all for the main domain seems like little 
more than a waste of memory.




Signed-off-by: Jordan Crouse 
---

  drivers/iommu/io-pgtable-arm.c | 261 +
  drivers/iommu/io-pgtable.c |   1 +
  include/linux/io-pgtable.h |   2 +
  3 files changed, 240 insertions(+), 24 deletions(-)

diff --git a/drivers/iommu/io-pgtable-arm.c b/drivers/iommu/io-pgtable-arm.c
index 161a7d56..aec35e5 100644
--- a/drivers/iommu/io-pgtable-arm.c
+++ b/drivers/iommu/io-pgtable-arm.c
@@ -118,7 +118,12 @@
  #define ARM_LPAE_TCR_TG0_64K  (1 << 14)
  #define ARM_LPAE_TCR_TG0_16K  (2 << 14)
  
+#define ARM_LPAE_TCR_TG1_4K		(0 << 30)

+#define ARM_LPAE_TCR_TG1_64K   (1 << 30)
+#define ARM_LPAE_TCR_TG1_16K   (2 << 30)
+
  #define ARM_LPAE_TCR_SH0_SHIFT12
+#define ARM_LPAE_TCR_SH1_SHIFT 28
  #define ARM_LPAE_TCR_SH0_MASK 0x3
  #define ARM_LPAE_TCR_SH_NS0
  #define ARM_LPAE_TCR_SH_OS2
@@ -126,6 +131,8 @@
  
  #define ARM_LPAE_TCR_ORGN0_SHIFT	10

  #define ARM_LPAE_TCR_IRGN0_SHIFT  8
+#define ARM_LPAE_TCR_ORGN1_SHIFT   26
+#define ARM_LPAE_TCR_IRGN1_SHIFT   24
  #define ARM_LPAE_TCR_RGN_MASK 0x3
  #define ARM_LPAE_TCR_RGN_NC   0
  #define ARM_LPAE_TCR_RGN_WBWA 1
@@ -136,6 +143,7 @@
  #define ARM_LPAE_TCR_SL0_MASK 0x3
  
  #define ARM_LPAE_TCR_T0SZ_SHIFT		0

+#define ARM_LPAE_TCR_T1SZ_SHIFT16
  #define ARM_LPAE_TCR_SZ_MASK  0xf
  
  #define ARM_LPAE_TCR_PS_SHIFT		16

@@ -152,6 +160,14 @@
  #define ARM_LPAE_TCR_PS_48_BIT0x5ULL
  #define ARM_LPAE_TCR_PS_52_BIT0x6ULL
  
+#define ARM_LPAE_TCR_SEP_SHIFT		47

+#define ARM_LPAE_TCR_SEP_31(0x0ULL << ARM_LPAE_TCR_SEP_SHIFT)
+#define ARM_LPAE_TCR_SEP_35(0x1ULL << ARM_LPAE_TCR_SEP_SHIFT)
+#define ARM_LPAE_TCR_SEP_39(0x2ULL << ARM_LPAE_TCR_SEP_SHIFT)
+#define ARM_LPAE_TCR_SEP_41(0x3ULL << ARM_LPAE_TCR_SEP_SHIFT)
+#define ARM_LPAE_TCR_SEP_43(0x4ULL << ARM_LPAE_TCR_SEP_SHIFT)
+#define ARM_LPAE_TCR_SEP_UPSTREAM  (0x7ULL << ARM_LPAE_TCR_SEP_SHIFT)


This is a specific detail of SMMUv2, and nothing to do with the 
LPAE/AArch64 VMSA formats.



+
  #define ARM_LPAE_MAIR_ATTR_SHIFT(n)   ((n) << 3)
  #define ARM_LPAE_MAIR_ATTR_MASK   0xff
  #define ARM_LPAE_MAIR_ATTR_DEVICE 0x04
@@ -179,11 +195,12 @@ struct arm_lpae_io_pgtable {
struct io_pgtable   iop;
  
  	int			levels;

+   u32 sep;
size_t  pgd_size;
unsigned long   pg_shift;
unsigned long   bits_per_level;
  
-	void			*pgd;

+   void*pgd[2];
  };
  
  typedef u64 arm_lpae_iopte;

@@ -426,7 +443,8 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
arm_lpae_iopte pte;
  
  	if (data->iop.fmt == ARM_64_LPAE_S1 ||

-   data->iop.fmt == ARM_32_LPAE_S1) {
+   data->iop.fmt == ARM_32_LPAE_S1 ||
+   data->iop.fmt == ARM_64_LPAE_SPLIT_S1) {
pte = ARM_LPAE_PTE_nG;
if (!(prot & IOMMU_WRITE) && (prot & IOMMU_READ))
pte |= ARM_LPAE_PTE_AP_RDONLY;
@@ -470,11 +488,10 @@ static arm_lpae_iopte arm_lpae_prot_to_pte(struct 
arm_lpae_io_pgtable *data,
return pte;
  }
  
-static int arm_lpae_map(struct io_pgtable_ops *ops, unsigned long iova,

-   phys_addr_t paddr, size_t size, int iommu_prot)
+static int _arm_lpae_map(struct arm_lpae_io_pgtable *data, unsigned long iova,
+   phys_addr_t paddr, size_t size, int iommu_prot,
+   arm_lpae_iopte *ptep)
  {
-   struct arm_lpae_io_pgtable *data = io_pgtable_ops_to_data(ops);
-   

Re: [RESEND PATCH v2 3/3] iommu/arm-smmu: Add support for DOMAIN_ATTR_SPLIT_TABLES

2019-07-10 Thread Robin Murphy

On 08/07/2019 20:00, Jordan Crouse wrote:

When DOMAIN_ATTR_SPLIT_TABLES is specified for pass ARM_64_LPAE_SPLIT_S1
to io_pgtable_ops to allocate and initialize TTBR0 and TTBR1 pagetables.

v3: Moved all the pagetable specific work into io-pgtable-arm
in a previous patch.

Signed-off-by: Jordan Crouse 
---

  drivers/iommu/arm-smmu.c | 16 +++-
  1 file changed, 15 insertions(+), 1 deletion(-)

diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c
index 653b6b3..7a6b4bb 100644
--- a/drivers/iommu/arm-smmu.c
+++ b/drivers/iommu/arm-smmu.c
@@ -257,6 +257,7 @@ struct arm_smmu_domain {
boolnon_strict;
struct mutexinit_mutex; /* Protects smmu pointer */
spinlock_t  cb_lock; /* Serialises ATS1* ops and 
TLB syncs */
+   u32 attributes;
struct iommu_domain domain;
  };
  
@@ -832,7 +833,11 @@ static int arm_smmu_init_domain_context(struct iommu_domain *domain,

ias = smmu->va_size;
oas = smmu->ipa_size;
if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH64) {
-   fmt = ARM_64_LPAE_S1;
+   if (smmu_domain->attributes &
+   (1 << DOMAIN_ATTR_SPLIT_TABLES))
+   fmt = ARM_64_LPAE_SPLIT_S1;
+   else
+   fmt = ARM_64_LPAE_S1;
} else if (cfg->fmt == ARM_SMMU_CTX_FMT_AARCH32_L) {
fmt = ARM_32_LPAE_S1;
ias = min(ias, 32UL);
@@ -1582,6 +1587,10 @@ static int arm_smmu_domain_get_attr(struct iommu_domain 
*domain,
case DOMAIN_ATTR_NESTING:
*(int *)data = (smmu_domain->stage == 
ARM_SMMU_DOMAIN_NESTED);
return 0;
+   case DOMAIN_ATTR_SPLIT_TABLES:
+   *(int *)data = !!(smmu_domain->attributes &
+   (1 << DOMAIN_ATTR_SPLIT_TABLES));


I'm not really a fan of always claiming to support this but silently 
ignoring it depending on hardware/kernel configuration - it seems 
somewhat tricky to make callers properly robust against making false 
assumptions (e.g. consider if the system is booted with 
"arm-smmu.force_stage=2").


Robin.


+   return 0;
default:
return -ENODEV;
}
@@ -1622,6 +1631,11 @@ static int arm_smmu_domain_set_attr(struct iommu_domain 
*domain,
else
smmu_domain->stage = ARM_SMMU_DOMAIN_S1;
break;
+   case DOMAIN_ATTR_SPLIT_TABLES:
+   if (*((int *)data))
+   smmu_domain->attributes |=
+   (1 << DOMAIN_ATTR_SPLIT_TABLES);
+   break;
default:
ret = -ENODEV;
}


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


Re: [PATCH v8 07/21] iommu/io-pgtable-arm-v7s: Extend MediaTek 4GB Mode

2019-07-10 Thread Will Deacon
On Sat, Jun 29, 2019 at 10:09:13AM +0800, Yong Wu wrote:
> MediaTek extend the arm v7s descriptor to support the dram over 4GB.
> 
> In the mt2712 and mt8173, it's called "4GB mode", the physical address
> is from 0x4000_ to 0x1_3fff_, but from EMI point of view, it
> is remapped to high address from 0x1__ to 0x1__, the
> bit32 is always enabled. thus, in the M4U, we always enable the bit9
> for all PTEs which means to enable bit32 of physical address.
> 
> but in mt8183, M4U support the dram from 0x4000_ to 0x3__
> which isn't remaped. We extend the PTEs: the bit9 represent bit32 of
> PA and the bit4 represent bit33 of PA. Meanwhile the iova still is
> 32bits.

What happens if bit4 is set in the pte for mt2712 or mt8173? Perhaps the
io-pgtable backend should be allowing oas > 32 when
IO_PGTABLE_QUIRK_ARM_MTK_4GB is set, and then enforcing that itself.

> In order to unify code, in the "4GB mode", we add the bit32 for the
> physical address manually in our driver.
> 
> Correspondingly, Adding bit32 and bit33 for the PA in the iova_to_phys
> has to been moved into v7s.
> 
> Regarding whether the pagetable address could be over 4GB, the mt8183
> support it while the previous mt8173 don't. thus keep it as is.
> 
> Signed-off-by: Yong Wu 
> Reviewed-by: Robin Murphy 
> Reviewed-by: Evan Green 
> ---
> Comparing with the previous one:
> 1). Add a new patch "iommu/mediatek: Fix iova_to_phys PA start for 4GB
> mode" before this one. Thus rebase it.
> A little difference: in the 4gb mode, we add bit32 for PA. and the PA got
> from iova_to_phys always have bit32 here, thus we should adjust it to locate
> the valid pa.
> 2). Add this code suggested from Evan.
>  if (!data->plat_data->has_4gb_mode)
>  data->enable_4GB = false;
> ---
>  drivers/iommu/io-pgtable-arm-v7s.c | 31 ---
>  drivers/iommu/mtk_iommu.c  | 29 ++---
>  drivers/iommu/mtk_iommu.h  |  1 +
>  3 files changed, 43 insertions(+), 18 deletions(-)
> 
> diff --git a/drivers/iommu/io-pgtable-arm-v7s.c 
> b/drivers/iommu/io-pgtable-arm-v7s.c
> index 94c38db..4077822 100644
> --- a/drivers/iommu/io-pgtable-arm-v7s.c
> +++ b/drivers/iommu/io-pgtable-arm-v7s.c
> @@ -123,7 +123,9 @@
>  #define ARM_V7S_TEX_MASK 0x7
>  #define ARM_V7S_ATTR_TEX(val)(((val) & ARM_V7S_TEX_MASK) << 
> ARM_V7S_TEX_SHIFT)
>  
> -#define ARM_V7S_ATTR_MTK_4GB BIT(9) /* MTK extend it for 4GB mode */
> +/* MediaTek extend the two bits below for over 4GB mode */
> +#define ARM_V7S_ATTR_MTK_PA_BIT32BIT(9)
> +#define ARM_V7S_ATTR_MTK_PA_BIT33BIT(4)
>  
>  /* *well, except for TEX on level 2 large pages, of course :( */
>  #define ARM_V7S_CONT_PAGE_TEX_SHIFT  6
> @@ -190,13 +192,22 @@ static dma_addr_t __arm_v7s_dma_addr(void *pages)
>  static arm_v7s_iopte paddr_to_iopte(phys_addr_t paddr, int lvl,
>   struct io_pgtable_cfg *cfg)
>  {
> - return paddr & ARM_V7S_LVL_MASK(lvl);
> + arm_v7s_iopte pte = paddr & ARM_V7S_LVL_MASK(lvl);
> +
> + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
> + if (paddr & BIT_ULL(32))
> + pte |= ARM_V7S_ATTR_MTK_PA_BIT32;
> + if (paddr & BIT_ULL(33))
> + pte |= ARM_V7S_ATTR_MTK_PA_BIT33;
> + }
> + return pte;
>  }
>  
>  static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int lvl,
> struct io_pgtable_cfg *cfg)
>  {
>   arm_v7s_iopte mask;
> + phys_addr_t paddr;
>  
>   if (ARM_V7S_PTE_IS_TABLE(pte, lvl))
>   mask = ARM_V7S_TABLE_MASK;
> @@ -205,7 +216,14 @@ static phys_addr_t iopte_to_paddr(arm_v7s_iopte pte, int 
> lvl,
>   else
>   mask = ARM_V7S_LVL_MASK(lvl);
>  
> - return pte & mask;
> + paddr = pte & mask;
> + if (cfg->quirks & IO_PGTABLE_QUIRK_ARM_MTK_4GB) {
> + if (pte & ARM_V7S_ATTR_MTK_PA_BIT32)
> + paddr |= BIT_ULL(32);
> + if (pte & ARM_V7S_ATTR_MTK_PA_BIT33)
> + paddr |= BIT_ULL(33);
> + }
> + return paddr;

I think this relies on CONFIG_PHYS_ADDR_T_64BIT, which isn't always set on
32-bit ARM.

Will


VFIO/IOMMU/PCI Linux Plumbers 2019 MC - Call for Topics

2019-07-10 Thread Lorenzo Pieralisi
Hi,

following the official LPC19 VFIO/IOMMU/PCI microconference acceptance
notification:

https://www.linuxplumbersconf.org/blog/2019/vfio-iommu-pci-microconference-accepted-into-2019-linux-plumbers-conference/

I am sending out a call for sessions proposals open to all developers
interested/involved in Linux kernel VFIO/IOMMU/PCI development.

The LPC19 blog page provides a list of topics that we put forward for
the microconference submission:

https://www.linuxplumbersconf.org/blog/2019/vfio-iommu-pci-microconference-accepted-into-2019-linux-plumbers-conference/

The blog page is there to provide a list of topics that we considered key
and it should not be considered final, actually it is a starting point to
define a possible schedule structure.

Session proposals for the LPC19 VFIO/IOMMU/PCI microconference are warmly
encouraged and can be submitted here through the common Call for Proposals
LPC19 web page (please choose VFIO/IOMMU/PCI MC topic in the "Track" submenu):

https://www.linuxplumbersconf.org/event/4/abstracts/

Anyone involved in VFIO/IOMMU/PCI kernel development, if you wish to add
sessions and attend the microconference consider yourself welcome, for any
questions just reply to this thread or drop me a line.

Looking forward to meeting you all in Lisbon for this interesting track !

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