Merge tag 'iommu-updates-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 Feb 2018 20:03:54 +0000 (12:03 -0800)
committerLinus Torvalds <torvalds@linux-foundation.org>
Thu, 8 Feb 2018 20:03:54 +0000 (12:03 -0800)
Pull IOMMU updates from Joerg Roedel:
 "This time there are not a lot of changes coming from the IOMMU side.

  That is partly because I returned from my parental leave late in the
  development process and probably partly because everyone was busy with
  Spectre and Meltdown mitigation work and didn't find the time for
  IOMMU work. So here are the few changes that queued up for this merge
  window:

   - 5-level page-table support for the Intel IOMMU.

   - error reporting improvements for the AMD IOMMU driver

   - additional DT bindings for ipmmu-vmsa (Renesas)

   - small fixes and cleanups"

* tag 'iommu-updates-v4.16' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu:
  iommu: Clean up of_iommu_init_fn
  iommu/ipmmu-vmsa: Remove redundant of_iommu_init_fn hook
  iommu/msm: Claim bus ops on probe
  iommu/vt-d: Enable 5-level paging mode in the PASID entry
  iommu/vt-d: Add a check for 5-level paging support
  iommu/vt-d: Add a check for 1GB page support
  iommu/vt-d: Enable upto 57 bits of domain address width
  iommu/vt-d: Use domain instead of cache fetching
  iommu/exynos: Don't unconditionally steal bus ops
  iommu/omap: Fix debugfs_create_*() usage
  iommu/vt-d: clean up pr_irq if request_threaded_irq fails
  iommu: Check the result of iommu_group_get() for NULL
  iommu/ipmmu-vmsa: Add r8a779(70|95) DT bindings
  iommu/ipmmu-vmsa: Add r8a7796 DT binding
  iommu/amd: Set the device table entry PPR bit for IOMMU V2 devices
  iommu/amd - Record more information about unknown events

16 files changed:
Documentation/devicetree/bindings/iommu/renesas,ipmmu-vmsa.txt
drivers/iommu/amd_iommu.c
drivers/iommu/amd_iommu_types.h
drivers/iommu/arm-smmu-v3.c
drivers/iommu/arm-smmu.c
drivers/iommu/exynos-iommu.c
drivers/iommu/intel-iommu.c
drivers/iommu/intel-svm.c
drivers/iommu/iommu.c
drivers/iommu/ipmmu-vmsa.c
drivers/iommu/msm_iommu.c
drivers/iommu/of_iommu.c
drivers/iommu/omap-iommu-debug.c
drivers/iommu/qcom_iommu.c
include/linux/intel-iommu.h
include/linux/of_iommu.h

index 857df929a6542157effed5df4944f6ba9f3da67c..1fd5d69647ca0dcc01e3cdd724dd4627e0d60e49 100644 (file)
@@ -16,6 +16,9 @@ Required Properties:
     - "renesas,ipmmu-r8a7793" for the R8A7793 (R-Car M2-N) IPMMU.
     - "renesas,ipmmu-r8a7794" for the R8A7794 (R-Car E2) IPMMU.
     - "renesas,ipmmu-r8a7795" for the R8A7795 (R-Car H3) IPMMU.
+    - "renesas,ipmmu-r8a7796" for the R8A7796 (R-Car M3-W) IPMMU.
+    - "renesas,ipmmu-r8a77970" for the R8A77970 (R-Car V3M) IPMMU.
+    - "renesas,ipmmu-r8a77995" for the R8A77995 (R-Car D3) IPMMU.
     - "renesas,ipmmu-vmsa" for generic R-Car Gen2 VMSA-compatible IPMMU.
 
   - reg: Base address and size of the IPMMU registers.
index fba4ec168bd5f1228cf72ef8019aecdc92689951..74788fdeb7734d014cb3a3dc5dc44319e0c76298 100644 (file)
@@ -617,7 +617,9 @@ retry:
                       address, flags);
                break;
        default:
-               printk(KERN_ERR "UNKNOWN type=0x%02x]\n", type);
+               printk(KERN_ERR "UNKNOWN type=0x%02x event[0]=0x%08x "
+                      "event[1]=0x%08x event[2]=0x%08x event[3]=0x%08x\n",
+                      type, event[0], event[1], event[2], event[3]);
        }
 
        memset(__evt, 0, 4 * sizeof(u32));
@@ -1816,7 +1818,8 @@ static bool dma_ops_domain(struct protection_domain *domain)
        return domain->flags & PD_DMA_OPS_MASK;
 }
 
-static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
+static void set_dte_entry(u16 devid, struct protection_domain *domain,
+                         bool ats, bool ppr)
 {
        u64 pte_root = 0;
        u64 flags = 0;
@@ -1833,6 +1836,13 @@ static void set_dte_entry(u16 devid, struct protection_domain *domain, bool ats)
        if (ats)
                flags |= DTE_FLAG_IOTLB;
 
+       if (ppr) {
+               struct amd_iommu *iommu = amd_iommu_rlookup_table[devid];
+
+               if (iommu_feature(iommu, FEATURE_EPHSUP))
+                       pte_root |= 1ULL << DEV_ENTRY_PPR;
+       }
+
        if (domain->flags & PD_IOMMUV2_MASK) {
                u64 gcr3 = iommu_virt_to_phys(domain->gcr3_tbl);
                u64 glx  = domain->glx;
@@ -1895,9 +1905,9 @@ static void do_attach(struct iommu_dev_data *dev_data,
        domain->dev_cnt                 += 1;
 
        /* Update device table */
-       set_dte_entry(dev_data->devid, domain, ats);
+       set_dte_entry(dev_data->devid, domain, ats, dev_data->iommu_v2);
        if (alias != dev_data->devid)
-               set_dte_entry(alias, domain, ats);
+               set_dte_entry(alias, domain, ats, dev_data->iommu_v2);
 
        device_flush_dte(dev_data);
 }
@@ -2276,13 +2286,15 @@ static void update_device_table(struct protection_domain *domain)
        struct iommu_dev_data *dev_data;
 
        list_for_each_entry(dev_data, &domain->dev_list, list) {
-               set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled);
+               set_dte_entry(dev_data->devid, domain, dev_data->ats.enabled,
+                             dev_data->iommu_v2);
 
                if (dev_data->devid == dev_data->alias)
                        continue;
 
                /* There is an alias, update device table entry for it */
-               set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled);
+               set_dte_entry(dev_data->alias, domain, dev_data->ats.enabled,
+                             dev_data->iommu_v2);
        }
 }
 
index f6b24c7d8b70e335d94992fe54ccd4d72b062be2..6a877ebd058b1e87a22c9fb2fe3c10035d6123ef 100644 (file)
@@ -98,6 +98,7 @@
 #define FEATURE_HE             (1ULL<<8)
 #define FEATURE_PC             (1ULL<<9)
 #define FEATURE_GAM_VAPIC      (1ULL<<21)
+#define FEATURE_EPHSUP         (1ULL<<50)
 
 #define FEATURE_PASID_SHIFT    32
 #define FEATURE_PASID_MASK     (0x1fULL << FEATURE_PASID_SHIFT)
 /* macros and definitions for device table entries */
 #define DEV_ENTRY_VALID         0x00
 #define DEV_ENTRY_TRANSLATION   0x01
+#define DEV_ENTRY_PPR           0x34
 #define DEV_ENTRY_IR            0x3d
 #define DEV_ENTRY_IW            0x3e
 #define DEV_ENTRY_NO_PAGE_FAULT        0x62
index 744592d330ca13f2734470c3992f5bb5b1b75088..3f2f1fc68b5240cea0b7d82bcbd46e1569d40665 100644 (file)
@@ -2971,7 +2971,7 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3", NULL);
+IOMMU_OF_DECLARE(arm_smmuv3, "arm,smmu-v3");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMUv3 implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
index 78d4c6b8f1bad57477f598a45430a7e519e7af39..69e7c60792a8e37130f75b447232d25369888cb8 100644 (file)
@@ -2211,12 +2211,12 @@ static struct platform_driver arm_smmu_driver = {
 };
 module_platform_driver(arm_smmu_driver);
 
-IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1", NULL);
-IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2", NULL);
-IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400", NULL);
-IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401", NULL);
-IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500", NULL);
-IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2", NULL);
+IOMMU_OF_DECLARE(arm_smmuv1, "arm,smmu-v1");
+IOMMU_OF_DECLARE(arm_smmuv2, "arm,smmu-v2");
+IOMMU_OF_DECLARE(arm_mmu400, "arm,mmu-400");
+IOMMU_OF_DECLARE(arm_mmu401, "arm,mmu-401");
+IOMMU_OF_DECLARE(arm_mmu500, "arm,mmu-500");
+IOMMU_OF_DECLARE(cavium_smmuv2, "cavium,smmu-v2");
 
 MODULE_DESCRIPTION("IOMMU API for ARM architected SMMU implementations");
 MODULE_AUTHOR("Will Deacon <will.deacon@arm.com>");
index 79c45650f8de6b2a20b0d1a79ca9dff5a17dec4c..2138102ef611de074ea16291770470feeaf2d4ee 100644 (file)
@@ -1353,8 +1353,15 @@ static const struct iommu_ops exynos_iommu_ops = {
 
 static int __init exynos_iommu_init(void)
 {
+       struct device_node *np;
        int ret;
 
+       np = of_find_matching_node(NULL, sysmmu_of_match);
+       if (!np)
+               return 0;
+
+       of_node_put(np);
+
        lv2table_kmem_cache = kmem_cache_create("exynos-iommu-lv2table",
                                LV2TABLE_SIZE, LV2TABLE_SIZE, 0, NULL);
        if (!lv2table_kmem_cache) {
@@ -1394,4 +1401,4 @@ err_reg_driver:
 }
 core_initcall(exynos_iommu_init);
 
-IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu", NULL);
+IOMMU_OF_DECLARE(exynos_iommu_of, "samsung,exynos-sysmmu");
index a1373cf343269455808f66ad18dc0a2fb7aa73f2..582fd01cb7d1b5ab9a0ece0d08e4bbdc0aac6188 100644 (file)
@@ -64,7 +64,7 @@
 #define IOAPIC_RANGE_END       (0xfeefffff)
 #define IOVA_START_ADDR                (0x1000)
 
-#define DEFAULT_DOMAIN_ADDRESS_WIDTH 48
+#define DEFAULT_DOMAIN_ADDRESS_WIDTH 57
 
 #define MAX_AGAW_WIDTH 64
 #define MAX_AGAW_PFN_WIDTH     (MAX_AGAW_WIDTH - VTD_PAGE_SHIFT)
@@ -1601,8 +1601,7 @@ static void iommu_flush_iotlb_psi(struct intel_iommu *iommu,
         * flush. However, device IOTLB doesn't need to be flushed in this case.
         */
        if (!cap_caching_mode(iommu->cap) || !map)
-               iommu_flush_dev_iotlb(get_iommu_domain(iommu, did),
-                                     addr, mask);
+               iommu_flush_dev_iotlb(domain, addr, mask);
 }
 
 static void iommu_flush_iova(struct iova_domain *iovad)
index 0a826eb7fe48659a84f01c4ff2d1b318006c6441..35a408d0ae4fae9e4ea33e184dfc60a6d0ddc0b4 100644 (file)
 #include <linux/interrupt.h>
 #include <asm/page.h>
 
+#define PASID_ENTRY_P          BIT_ULL(0)
+#define PASID_ENTRY_FLPM_5LP   BIT_ULL(9)
+#define PASID_ENTRY_SRE                BIT_ULL(11)
+
 static irqreturn_t prq_event_thread(int irq, void *d);
 
 struct pasid_entry {
@@ -41,6 +45,14 @@ int intel_svm_alloc_pasid_tables(struct intel_iommu *iommu)
        struct page *pages;
        int order;
 
+       if (cpu_feature_enabled(X86_FEATURE_GBPAGES) &&
+                       !cap_fl1gp_support(iommu->cap))
+               return -EINVAL;
+
+       if (cpu_feature_enabled(X86_FEATURE_LA57) &&
+                       !cap_5lp_support(iommu->cap))
+               return -EINVAL;
+
        /* Start at 2 because it's defined as 2^(1+PSS) */
        iommu->pasid_max = 2 << ecap_pss(iommu->ecap);
 
@@ -129,6 +141,7 @@ int intel_svm_enable_prq(struct intel_iommu *iommu)
                pr_err("IOMMU: %s: Failed to request IRQ for page request queue\n",
                       iommu->name);
                dmar_free_hwirq(irq);
+               iommu->pr_irq = 0;
                goto err;
        }
        dmar_writeq(iommu->reg + DMAR_PQH_REG, 0ULL);
@@ -144,9 +157,11 @@ int intel_svm_finish_prq(struct intel_iommu *iommu)
        dmar_writeq(iommu->reg + DMAR_PQT_REG, 0ULL);
        dmar_writeq(iommu->reg + DMAR_PQA_REG, 0ULL);
 
-       free_irq(iommu->pr_irq, iommu);
-       dmar_free_hwirq(iommu->pr_irq);
-       iommu->pr_irq = 0;
+       if (iommu->pr_irq) {
+               free_irq(iommu->pr_irq, iommu);
+               dmar_free_hwirq(iommu->pr_irq);
+               iommu->pr_irq = 0;
+       }
 
        free_pages((unsigned long)iommu->prq, PRQ_ORDER);
        iommu->prq = NULL;
@@ -290,6 +305,7 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
        struct intel_svm_dev *sdev;
        struct intel_svm *svm = NULL;
        struct mm_struct *mm = NULL;
+       u64 pasid_entry_val;
        int pasid_max;
        int ret;
 
@@ -396,9 +412,15 @@ int intel_svm_bind_mm(struct device *dev, int *pasid, int flags, struct svm_dev_
                                kfree(sdev);
                                goto out;
                        }
-                       iommu->pasid_table[svm->pasid].val = (u64)__pa(mm->pgd) | 1;
+                       pasid_entry_val = (u64)__pa(mm->pgd) | PASID_ENTRY_P;
                } else
-                       iommu->pasid_table[svm->pasid].val = (u64)__pa(init_mm.pgd) | 1 | (1ULL << 11);
+                       pasid_entry_val = (u64)__pa(init_mm.pgd) |
+                                         PASID_ENTRY_P | PASID_ENTRY_SRE;
+               if (cpu_feature_enabled(X86_FEATURE_LA57))
+                       pasid_entry_val |= PASID_ENTRY_FLPM_5LP;
+
+               iommu->pasid_table[svm->pasid].val = pasid_entry_val;
+
                wmb();
                /* In caching mode, we still have to flush with PASID 0 when
                 * a PASID table entry becomes present. Not entirely clear
index 3de5c0bcb5cc9f32b6fb615ce38f5729ae86d407..69fef991c651de26c60e5c3cb5f2e6be0c0d0fcb 100644 (file)
@@ -1303,6 +1303,9 @@ int iommu_attach_device(struct iommu_domain *domain, struct device *dev)
        int ret;
 
        group = iommu_group_get(dev);
+       if (!group)
+               return -ENODEV;
+
        /*
         * Lock the group to make sure the device-count doesn't
         * change while we are attaching
@@ -1341,6 +1344,8 @@ void iommu_detach_device(struct iommu_domain *domain, struct device *dev)
        struct iommu_group *group;
 
        group = iommu_group_get(dev);
+       if (!group)
+               return;
 
        mutex_lock(&group->mutex);
        if (iommu_group_device_count(group) != 1) {
index 8dce3a9de9d86e37b66dce131952aa19e0aadb2a..40ae6e87cb8802232b58d7b29f84d3f82930d7c2 100644 (file)
@@ -1108,18 +1108,8 @@ static void __exit ipmmu_exit(void)
 subsys_initcall(ipmmu_init);
 module_exit(ipmmu_exit);
 
-#ifdef CONFIG_IOMMU_DMA
-static int __init ipmmu_vmsa_iommu_of_setup(struct device_node *np)
-{
-       ipmmu_init();
-       return 0;
-}
-
-IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa",
-                ipmmu_vmsa_iommu_of_setup);
-IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795",
-                ipmmu_vmsa_iommu_of_setup);
-#endif
+IOMMU_OF_DECLARE(ipmmu_vmsa_iommu_of, "renesas,ipmmu-vmsa");
+IOMMU_OF_DECLARE(ipmmu_r8a7795_iommu_of, "renesas,ipmmu-r8a7795");
 
 MODULE_DESCRIPTION("IOMMU API for Renesas VMSA-compatible IPMMU");
 MODULE_AUTHOR("Laurent Pinchart <laurent.pinchart@ideasonboard.com>");
index 04f4d51ffacb1e50ae3f87f04fd3b23306f7b55b..0d3350463a3f48fe783e8fb6821e92ff1163f0b4 100644 (file)
@@ -823,6 +823,8 @@ static int msm_iommu_probe(struct platform_device *pdev)
                goto fail;
        }
 
+       bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
+
        pr_info("device mapped at %p, irq %d with %d ctx banks\n",
                iommu->base, iommu->irq, iommu->ncb);
 
@@ -875,19 +877,7 @@ static void __exit msm_iommu_driver_exit(void)
 subsys_initcall(msm_iommu_driver_init);
 module_exit(msm_iommu_driver_exit);
 
-static int __init msm_iommu_init(void)
-{
-       bus_set_iommu(&platform_bus_type, &msm_iommu_ops);
-       return 0;
-}
-
-static int __init msm_iommu_of_setup(struct device_node *np)
-{
-       msm_iommu_init();
-       return 0;
-}
-
-IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu", msm_iommu_of_setup);
+IOMMU_OF_DECLARE(msm_iommu_of, "qcom,apq8064-iommu");
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Stepan Moskovchenko <stepanm@codeaurora.org>");
index 50947ebb6d1700e3f81acb5806c1b1a8b183c145..5c36a8b7656ae2b4f298dfa9793807085e9e0708 100644 (file)
@@ -231,19 +231,3 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
 
        return ops;
 }
-
-static int __init of_iommu_init(void)
-{
-       struct device_node *np;
-       const struct of_device_id *match, *matches = &__iommu_of_table;
-
-       for_each_matching_node_and_match(np, matches, &match) {
-               const of_iommu_init_fn init_fn = match->data;
-
-               if (init_fn && init_fn(np))
-                       pr_err("Failed to initialise IOMMU %pOF\n", np);
-       }
-
-       return 0;
-}
-postcore_initcall_sync(of_iommu_init);
index 505548aafeff2276c82c64de4702aae37ddfe15b..50217548c3b8e7afbb906a57b28705d2c1df7cb7 100644 (file)
@@ -274,8 +274,8 @@ void omap_iommu_debugfs_add(struct omap_iommu *obj)
        if (!obj->debug_dir)
                return;
 
-       d = debugfs_create_u8("nr_tlb_entries", 0400, obj->debug_dir,
-                             (u8 *)&obj->nr_tlb_entries);
+       d = debugfs_create_u32("nr_tlb_entries", 0400, obj->debug_dir,
+                              &obj->nr_tlb_entries);
        if (!d)
                return;
 
index e07f02d00c688f0b604c71f6531d83dc43a94ee2..65b9c99707f84837aa0bb863ec211e08050ca005 100644 (file)
@@ -947,7 +947,7 @@ static void __exit qcom_iommu_exit(void)
 module_init(qcom_iommu_init);
 module_exit(qcom_iommu_exit);
 
-IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1", NULL);
+IOMMU_OF_DECLARE(qcom_iommu_dev, "qcom,msm-iommu-v1");
 
 MODULE_DESCRIPTION("IOMMU API for QCOM IOMMU v1 implementations");
 MODULE_LICENSE("GPL v2");
index f3274d9f46a252a9abc332dc0621ec3fc02ef4aa..8dad3dd26eaeddc60aea0ce70547a2964364befd 100644 (file)
@@ -83,7 +83,9 @@
 /*
  * Decoding Capability Register
  */
+#define cap_5lp_support(c)     (((c) >> 60) & 1)
 #define cap_pi_support(c)      (((c) >> 59) & 1)
+#define cap_fl1gp_support(c)   (((c) >> 56) & 1)
 #define cap_read_drain(c)      (((c) >> 55) & 1)
 #define cap_write_drain(c)     (((c) >> 54) & 1)
 #define cap_max_amask_val(c)   (((c) >> 48) & 0x3f)
index cddfaff4d0b70ff112e72bc9125d2c2b45dc5fd2..4fa654e4b5a92e1133cc532347711a64edd9eb93 100644 (file)
@@ -34,9 +34,6 @@ static inline const struct iommu_ops *of_iommu_configure(struct device *dev,
 
 extern struct of_device_id __iommu_of_table;
 
-typedef int (*of_iommu_init_fn)(struct device_node *);
-
-#define IOMMU_OF_DECLARE(name, compat, fn) \
-       _OF_DECLARE(iommu, name, compat, fn, of_iommu_init_fn)
+#define IOMMU_OF_DECLARE(name, compat) OF_DECLARE_1(iommu, name, compat, NULL)
 
 #endif /* __OF_IOMMU_H */