From 5fc63a7c446e998d01a68b108fe007be675aced7 Mon Sep 17 00:00:00 2001 From: Antonios Motakis Date: Fri, 18 Oct 2013 16:08:29 +0100 Subject: [PATCH 1/4] iommu/arm-smmu: add devices attached to the SMMU to an IOMMU group IOMMU groups are expected by certain users of the IOMMU API, e.g. VFIO. Add new devices found by the SMMU driver to an IOMMU group to satisfy those users. Acked-by: Alex Williamson Signed-off-by: Antonios Motakis Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index e46a88700b68..879da20617fb 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -1494,6 +1494,13 @@ static int arm_smmu_add_device(struct device *dev) { struct arm_smmu_device *child, *parent, *smmu; struct arm_smmu_master *master = NULL; + struct iommu_group *group; + int ret; + + if (dev->archdata.iommu) { + dev_warn(dev, "IOMMU driver already assigned to device\n"); + return -EINVAL; + } spin_lock(&arm_smmu_devices_lock); list_for_each_entry(parent, &arm_smmu_devices, list) { @@ -1526,13 +1533,23 @@ static int arm_smmu_add_device(struct device *dev) if (!master) return -ENODEV; + group = iommu_group_alloc(); + if (IS_ERR(group)) { + dev_err(dev, "Failed to allocate IOMMU group\n"); + return PTR_ERR(group); + } + + ret = iommu_group_add_device(group, dev); + iommu_group_put(group); dev->archdata.iommu = smmu; - return 0; + + return ret; } static void arm_smmu_remove_device(struct device *dev) { dev->archdata.iommu = NULL; + iommu_group_remove_device(dev); } static struct iommu_ops arm_smmu_ops = { From 06f983dd571f564bdd3eb2ac4c33002034ea7810 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 5 Nov 2013 15:55:04 +0000 Subject: [PATCH 2/4] iommu/arm-smmu: use VA_BITS to determine arm64 virtual address space With the introduction of the VA_BITS definition for arm64, make use of it in the driver, allowing up to 42-bits of VA space when configured with 64k pages. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 879da20617fb..fa3371adea4f 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -24,7 +24,7 @@ * - v7/v8 long-descriptor format * - Non-secure access to the SMMU * - 4k and 64k pages, with contiguous pte hints. - * - Up to 39-bit addressing + * - Up to 42-bit addressing (dependent on VA_BITS) * - Context fault reporting */ @@ -1747,7 +1747,6 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) * allocation (PTRS_PER_PGD). */ #ifdef CONFIG_64BIT - /* Current maximum output size of 39 bits */ smmu->s1_output_size = min(39UL, size); #else smmu->s1_output_size = min(32UL, size); @@ -1762,7 +1761,7 @@ static int arm_smmu_device_cfg_probe(struct arm_smmu_device *smmu) } else { #ifdef CONFIG_64BIT size = (id >> ID2_UBS_SHIFT) & ID2_UBS_MASK; - size = min(39, arm_smmu_id_size_to_bits(size)); + size = min(VA_BITS, arm_smmu_id_size_to_bits(size)); #else size = 32; #endif From ca13bb3d4e54f5c30089e55d5b8f4bb80c8f05e2 Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 5 Nov 2013 15:59:53 +0000 Subject: [PATCH 3/4] iommu: add IOMMU_EXEC flag for safely allowing XN mappings Whilst most IOMMU mappings should probably be non-executable, there may be cases (HSA?) where executable mappings are required. This patch introduces a new mapping flag, IOMMU_EXEC, to indicate that the mapping should be mapped as executable. Signed-off-by: Will Deacon --- include/linux/iommu.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/include/linux/iommu.h b/include/linux/iommu.h index a444c790fa72..709a697c4e02 100644 --- a/include/linux/iommu.h +++ b/include/linux/iommu.h @@ -24,9 +24,10 @@ #include #include -#define IOMMU_READ (1) -#define IOMMU_WRITE (2) -#define IOMMU_CACHE (4) /* DMA cache coherency */ +#define IOMMU_READ (1 << 0) +#define IOMMU_WRITE (1 << 1) +#define IOMMU_CACHE (1 << 2) /* DMA cache coherency */ +#define IOMMU_EXEC (1 << 3) struct iommu_ops; struct iommu_group; From cf2d45b19ddb361241f36d8c9f3d0b234a18459b Mon Sep 17 00:00:00 2001 From: Will Deacon Date: Tue, 5 Nov 2013 16:32:00 +0000 Subject: [PATCH 4/4] iommu/arm-smmu: add support for IOMMU_EXEC Previously, all of our mappings were marked as executable, which isn't usually required. Now that we have the IOMMU_EXEC flag, use that to determine whether or not a mapping should be marked as executable. Signed-off-by: Will Deacon --- drivers/iommu/arm-smmu.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index fa3371adea4f..8911850c9444 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -61,12 +61,13 @@ #define ARM_SMMU_GR1(smmu) ((smmu)->base + (smmu)->pagesize) /* Page table bits */ -#define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) +#define ARM_SMMU_PTE_XN (((pteval_t)3) << 53) #define ARM_SMMU_PTE_CONT (((pteval_t)1) << 52) #define ARM_SMMU_PTE_AF (((pteval_t)1) << 10) #define ARM_SMMU_PTE_SH_NS (((pteval_t)0) << 8) #define ARM_SMMU_PTE_SH_OS (((pteval_t)2) << 8) #define ARM_SMMU_PTE_SH_IS (((pteval_t)3) << 8) +#define ARM_SMMU_PTE_PAGE (((pteval_t)3) << 0) #if PAGE_SIZE == SZ_4K #define ARM_SMMU_PTE_CONT_ENTRIES 16 @@ -1205,7 +1206,7 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, unsigned long pfn, int flags, int stage) { pte_t *pte, *start; - pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF; + pteval_t pteval = ARM_SMMU_PTE_PAGE | ARM_SMMU_PTE_AF | ARM_SMMU_PTE_XN; if (pmd_none(*pmd)) { /* Allocate a new set of tables */ @@ -1244,7 +1245,9 @@ static int arm_smmu_alloc_init_pte(struct arm_smmu_device *smmu, pmd_t *pmd, } /* If no access, create a faulting entry to avoid TLB fills */ - if (!(flags & (IOMMU_READ | IOMMU_WRITE))) + if (flags & IOMMU_EXEC) + pteval &= ~ARM_SMMU_PTE_XN; + else if (!(flags & (IOMMU_READ | IOMMU_WRITE))) pteval &= ~ARM_SMMU_PTE_PAGE; pteval |= ARM_SMMU_PTE_SH_IS;