Merge branches 'iommu/fixes', 'arm/tegra', 'arm/smmu', 'virtio', 'x86/vt-d', 'x86...
authorJoerg Roedel <jroedel@suse.de>
Fri, 27 Oct 2023 07:13:40 +0000 (09:13 +0200)
committerJoerg Roedel <jroedel@suse.de>
Fri, 27 Oct 2023 07:13:40 +0000 (09:13 +0200)
1  2  3  4  5  6  7  8 
drivers/iommu/amd/iommu.c
drivers/iommu/apple-dart.c
drivers/iommu/intel/iommu.c
drivers/iommu/intel/iommu.h
drivers/iommu/iommu.c
drivers/iommu/mtk_iommu.c
drivers/iommu/tegra-smmu.c
include/linux/iommu.h

index 95bd7c25ba6f366b5db2582e8cb5318491cbb523,95bd7c25ba6f366b5db2582e8cb5318491cbb523,95bd7c25ba6f366b5db2582e8cb5318491cbb523,95bd7c25ba6f366b5db2582e8cb5318491cbb523,95bd7c25ba6f366b5db2582e8cb5318491cbb523,a284768cb542be9ce3834a44a18bb5e7f9bef65e,95bd7c25ba6f366b5db2582e8cb5318491cbb523,74229b1607a172e2a7d445af7bfffb6d20bdb990..089886485895bcef70b69141560bc558dfa84eda
@@@@@@@@@ -2092,31 -2092,31 -2092,31 -2092,31 -2092,31 -2129,41 -2092,31 -2092,31 +2129,41 @@@@@@@@@ static struct protection_domain *protec
                struct io_pgtable_ops *pgtbl_ops;
                struct protection_domain *domain;
                int pgtable;
----- --        int mode = DEFAULT_PGTABLE_LEVEL;
                int ret;
        
+++++ ++        domain = kzalloc(sizeof(*domain), GFP_KERNEL);
+++++ ++        if (!domain)
+++++ ++                return NULL;
+++++ ++
+++++ ++        domain->id = domain_id_alloc();
+++++ ++        if (!domain->id)
+++++ ++                goto out_err;
+++++ ++
+++++ ++        spin_lock_init(&domain->lock);
+++++ ++        INIT_LIST_HEAD(&domain->dev_list);
+++++ ++        domain->nid = NUMA_NO_NODE;
+++++ ++
+++++ ++        switch (type) {
+++++ ++        /* No need to allocate io pgtable ops in passthrough mode */
+++++ ++        case IOMMU_DOMAIN_IDENTITY:
+++++ ++                return domain;
+++++ ++        case IOMMU_DOMAIN_DMA:
+++++ ++                pgtable = amd_iommu_pgtable;
+++++ ++                break;
                /*
----- --         * Force IOMMU v1 page table when iommu=pt and
----- --         * when allocating domain for pass-through devices.
+++++ ++         * Force IOMMU v1 page table when allocating
+++++ ++         * domain for pass-through devices.
                 */
----- --        if (type == IOMMU_DOMAIN_IDENTITY) {
----- -                 pgtable = AMD_IOMMU_V1;
----- -                 mode = PAGE_MODE_NONE;
----- -         } else if (type == IOMMU_DOMAIN_UNMANAGED) {
+++++ ++        case IOMMU_DOMAIN_UNMANAGED:
                        pgtable = AMD_IOMMU_V1;
       -                mode = PAGE_MODE_NONE;
       -        } else if (type == IOMMU_DOMAIN_UNMANAGED) {
       -                pgtable = AMD_IOMMU_V1;
----- --        } else if (type == IOMMU_DOMAIN_DMA || type == IOMMU_DOMAIN_DMA_FQ) {
----- --                pgtable = amd_iommu_pgtable;
----- --        } else {
----- --                return NULL;
+++++ ++                break;
+++++ ++        default:
+++++ ++                goto out_err;
                }
        
----- --        domain = kzalloc(sizeof(*domain), GFP_KERNEL);
----- --        if (!domain)
----- --                return NULL;
----- --
                switch (pgtable) {
                case AMD_IOMMU_V1:
----- --                ret = protection_domain_init_v1(domain, mode);
+++++ ++                ret = protection_domain_init_v1(domain, DEFAULT_PGTABLE_LEVEL);
                        break;
                case AMD_IOMMU_V2:
                        ret = protection_domain_init_v2(domain);
index 0b89275084274659fb91f8dbd2567693bdf963dd,2082081402d324abe99dc4c02b43866367ca4fa0,2082081402d324abe99dc4c02b43866367ca4fa0,2082081402d324abe99dc4c02b43866367ca4fa0,2082081402d324abe99dc4c02b43866367ca4fa0,2082081402d324abe99dc4c02b43866367ca4fa0,821b4a3465dfb9600c064d2020763576a62b6834,22880a42ccaa645b5cc1be8c479f25bb3ea3c2aa..ee05f4824bfad1d6515fd506e9c1c2fd6760e18f
@@@@@@@@@ -670,28 -670,29 -670,29 -670,29 -670,29 -670,29 -668,56 -671,29 +669,56 @@@@@@@@@ static int apple_dart_attach_dev_paging
                if (ret)
                        return ret;
        
------ -        switch (domain->type) {
-               default:
 ----- -        case IOMMU_DOMAIN_DMA:
 ----- -        case IOMMU_DOMAIN_UNMANAGED:
------ -                ret = apple_dart_domain_add_streams(dart_domain, cfg);
------ -                if (ret)
------ -                        return ret;
++++++ +        for_each_stream_map(i, cfg, stream_map)
++++++ +                apple_dart_setup_translation(dart_domain, stream_map);
++++++ +        return 0;
++++++ +}
        
------ -                for_each_stream_map(i, cfg, stream_map)
------ -                        apple_dart_setup_translation(dart_domain, stream_map);
------ -                break;
------ -        case IOMMU_DOMAIN_BLOCKED:
------ -                for_each_stream_map(i, cfg, stream_map)
------ -                        apple_dart_hw_disable_dma(stream_map);
------ -                break;
------ -        case IOMMU_DOMAIN_IDENTITY:
------ -                for_each_stream_map(i, cfg, stream_map)
------ -                        apple_dart_hw_enable_bypass(stream_map);
------ -                break;
------ -        }
++++++ +static int apple_dart_attach_dev_identity(struct iommu_domain *domain,
++++++ +                                          struct device *dev)
++++++ +{
++++++ +        struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
++++++ +        struct apple_dart_stream_map *stream_map;
++++++ +        int i;
        
------ -        return ret;
++++++ +        if (!cfg->stream_maps[0].dart->supports_bypass)
++++++ +                return -EINVAL;
++++++ +
++++++ +        for_each_stream_map(i, cfg, stream_map)
++++++ +                apple_dart_hw_enable_bypass(stream_map);
++++++ +        return 0;
        }
        
++++++ +static const struct iommu_domain_ops apple_dart_identity_ops = {
++++++ +        .attach_dev = apple_dart_attach_dev_identity,
++++++ +};
++++++ +
++++++ +static struct iommu_domain apple_dart_identity_domain = {
++++++ +        .type = IOMMU_DOMAIN_IDENTITY,
++++++ +        .ops = &apple_dart_identity_ops,
++++++ +};
++++++ +
++++++ +static int apple_dart_attach_dev_blocked(struct iommu_domain *domain,
++++++ +                                         struct device *dev)
++++++ +{
++++++ +        struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
++++++ +        struct apple_dart_stream_map *stream_map;
++++++ +        int i;
++++++ +
++++++ +        for_each_stream_map(i, cfg, stream_map)
++++++ +                apple_dart_hw_disable_dma(stream_map);
++++++ +        return 0;
++++++ +}
++++++ +
++++++ +static const struct iommu_domain_ops apple_dart_blocked_ops = {
++++++ +        .attach_dev = apple_dart_attach_dev_blocked,
++++++ +};
++++++ +
++++++ +static struct iommu_domain apple_dart_blocked_domain = {
++++++ +        .type = IOMMU_DOMAIN_BLOCKED,
++++++ +        .ops = &apple_dart_blocked_ops,
++++++ +};
++++++ +
        static struct iommu_device *apple_dart_probe_device(struct device *dev)
        {
                struct apple_dart_master_cfg *cfg = dev_iommu_priv_get(dev);
Simple merge
Simple merge
index c146378c7d032c3805f46e6db24a6a9e47e4a264,3bfc56df4f781cbb15f6cad090681f8327b8dde4,3bfc56df4f781cbb15f6cad090681f8327b8dde4,3bfc56df4f781cbb15f6cad090681f8327b8dde4,3bfc56df4f781cbb15f6cad090681f8327b8dde4,360f1042e55508ebba66aa5794a5247ed4344941,79a0fdb334046fc51074be9abbe120a8a97178f1,1cc9d139c860cf6223586fd22cf01763bdca62d3..f17a1113f3d6a35daf9cff1def8f4f5158416ea2
@@@@@@@@@ -1753,11 -1752,11 -1752,11 -1752,11 -1752,11 -1752,11 -1780,22 -1780,22 +1781,22 @@@@@@@@@ iommu_group_alloc_default_domain(struc
        
                lockdep_assert_held(&group->mutex);
        
       -                        return ERR_PTR(-EINVAL);
++++++          /*
++++++           * Allow legacy drivers to specify the domain that will be the default
++++++           * domain. This should always be either an IDENTITY/BLOCKED/PLATFORM
++++++           * domain. Do not use in new drivers.
++++++           */
++++++          if (ops->default_domain) {
++++++                  if (req_type)
++++++ +                        return NULL;
++++++                  return ops->default_domain;
++++++          }
++++++  
                if (req_type)
------                  return __iommu_group_alloc_default_domain(bus, group, req_type);
++++++                  return __iommu_group_alloc_default_domain(group, req_type);
        
                /* The driver gave no guidance on what type to use, try the default */
------          dom = __iommu_group_alloc_default_domain(bus, group, iommu_def_domain_type);
++++++          dom = __iommu_group_alloc_default_domain(group, iommu_def_domain_type);
                if (dom)
                        return dom;
        
@@@@@@@@@ -1818,30 -1817,30 -1817,30 -1817,30 -1817,30 -1817,30 -1893,62 -1893,50 +1894,62 @@@@@@@@@ static int iommu_get_default_domain_typ
        
                lockdep_assert_held(&group->mutex);
        
++++++          /*
++++++           * ARM32 drivers supporting CONFIG_ARM_DMA_USE_IOMMU can declare an
++++++           * identity_domain and it will automatically become their default
++++++           * domain. Later on ARM_DMA_USE_IOMMU will install its UNMANAGED domain.
++++++           * Override the selection to IDENTITY.
++++++           */
++++++          if (IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)) {
++++++                  static_assert(!(IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU) &&
++++++                                  IS_ENABLED(CONFIG_IOMMU_DMA)));
++++++                  driver_type = IOMMU_DOMAIN_IDENTITY;
++++++          }
++++++  
                for_each_group_device(group, gdev) {
------                  unsigned int type = iommu_get_def_domain_type(gdev->dev);
------  
------                  if (best_type && type && best_type != type) {
------                          if (target_type) {
------                                  dev_err_ratelimited(
------                                          gdev->dev,
------                                          "Device cannot be in %s domain\n",
------                                          iommu_domain_type_str(target_type));
++++++                  driver_type = iommu_get_def_domain_type(group, gdev->dev,
++++++                                                          driver_type);
++++++  
++++++                  if (dev_is_pci(gdev->dev) && to_pci_dev(gdev->dev)->untrusted) {
++++++                          /*
++++++                           * No ARM32 using systems will set untrusted, it cannot
++++++                           * work.
++++++                           */
++++++                          if (WARN_ON(IS_ENABLED(CONFIG_ARM_DMA_USE_IOMMU)))
                                        return -1;
------                          }
++++++                          untrusted = gdev->dev;
++++++                  }
++++++          }
        
------                          dev_warn(
------                                  gdev->dev,
------                                  "Device needs domain type %s, but device %s in the same iommu group requires type %s - using default\n",
------                                  iommu_domain_type_str(type), dev_name(last_dev),
------                                  iommu_domain_type_str(best_type));
------                          return 0;
++++++ +        /*
++++++ +         * If the common dma ops are not selected in kconfig then we cannot use
++++++ +         * IOMMU_DOMAIN_DMA at all. Force IDENTITY if nothing else has been
++++++ +         * selected.
++++++ +         */
++++++ +        if (!IS_ENABLED(CONFIG_IOMMU_DMA)) {
++++++ +                if (WARN_ON(driver_type == IOMMU_DOMAIN_DMA))
++++++ +                        return -1;
++++++ +                if (!driver_type)
++++++ +                        driver_type = IOMMU_DOMAIN_IDENTITY;
++++++ +        }
++++++ +
++++++          if (untrusted) {
++++++                  if (driver_type && driver_type != IOMMU_DOMAIN_DMA) {
++++++                          dev_err_ratelimited(
++++++                                  untrusted,
++++++                                  "Device is not trusted, but driver is overriding group %u to %s, refusing to probe.\n",
++++++                                  group->id, iommu_domain_type_str(driver_type));
++++++                          return -1;
                        }
------                  if (!best_type)
------                          best_type = type;
------                  last_dev = gdev->dev;
++++++                  driver_type = IOMMU_DOMAIN_DMA;
                }
------          return best_type;
++++++  
++++++          if (target_type) {
++++++                  if (driver_type && target_type != driver_type)
++++++                          return -1;
++++++                  return target_type;
++++++          }
++++++          return driver_type;
        }
        
        static void iommu_group_do_probe_finalize(struct device *dev)
@@@@@@@@@ -1976,10 -1975,10 -1975,10 -1975,10 -1975,10 -1975,10 -2084,17 -2072,15 +2085,17 @@@@@@@@@ static struct iommu_domain *__iommu_dom
                struct iommu_domain *domain;
                unsigned int alloc_type = type & IOMMU_DOMAIN_ALLOC_FLAGS;
        
------          if (bus == NULL || bus->iommu_ops == NULL)
++++++          if (alloc_type == IOMMU_DOMAIN_IDENTITY && ops->identity_domain)
++++++                  return ops->identity_domain;
++++++ +        else if (alloc_type == IOMMU_DOMAIN_BLOCKED && ops->blocked_domain)
++++++ +                return ops->blocked_domain;
++++++          else if (type & __IOMMU_DOMAIN_PAGING && ops->domain_alloc_paging)
++++++                  domain = ops->domain_alloc_paging(dev);
++++++          else if (ops->domain_alloc)
++++++                  domain = ops->domain_alloc(alloc_type);
++++++          else
                        return NULL;
        
------          domain = bus->iommu_ops->domain_alloc(alloc_type);
                if (!domain)
                        return NULL;
        
@@@@@@@@@ -2516,25 -2515,25 -2515,25 -2515,25 -2515,25 -2515,25 -2599,12 -2585,21 +2600,21 @@@@@@@@@ int iommu_map(struct iommu_domain *doma
                        return -EINVAL;
        
                ret = __iommu_map(domain, iova, paddr, size, prot, gfp);
-------         if (ret == 0 && ops->iotlb_sync_map)
-------                 ops->iotlb_sync_map(domain, iova, size);
+++++++         if (ret == 0 && ops->iotlb_sync_map) {
+++++++                 ret = ops->iotlb_sync_map(domain, iova, size);
+++++++                 if (ret)
+++++++                         goto out_err;
+++++++         }
      + 
      +         return ret;
------  }
------  EXPORT_SYMBOL_GPL(iommu_map);
      + 
------  static size_t __iommu_unmap_pages(struct iommu_domain *domain,
------                                    unsigned long iova, size_t size,
------                                    struct iommu_iotlb_gather *iotlb_gather)
------  {
------          const struct iommu_domain_ops *ops = domain->ops;
------          size_t pgsize, count;
+++++++ out_err:
+++++++         /* undo mappings already done */
+++++++         iommu_unmap(domain, iova, size);
        
------          pgsize = iommu_pgsize(domain, iova, iova, size, &count);
------          return ops->unmap_pages ?
------                 ops->unmap_pages(domain, iova, pgsize, count, iotlb_gather) :
------                 ops->unmap(domain, iova, pgsize, iotlb_gather);
++++++          return ret;
        }
++++++  EXPORT_SYMBOL_GPL(iommu_map);
        
        static size_t __iommu_unmap(struct iommu_domain *domain,
                                    unsigned long iova, size_t size,
Simple merge
Simple merge
index c50a769d569a60f2922a40ad7b813de4b29513d0,c50a769d569a60f2922a40ad7b813de4b29513d0,c50a769d569a60f2922a40ad7b813de4b29513d0,c50a769d569a60f2922a40ad7b813de4b29513d0,c50a769d569a60f2922a40ad7b813de4b29513d0,c50a769d569a60f2922a40ad7b813de4b29513d0,73daa4fb168bc4553f45eb62bde8b7e0dcc1beec,0c4d8ae985ac62c536fcac25ebdf97fd057f11d1..ddc25d2391063b6f154810a3666a5692afa6e178
@@@@@@@@@ -260,6 -260,6 -260,6 -260,6 -260,6 -260,6 -263,13 -263,11 +263,13 @@@@@@@@@ struct iommu_iotlb_gather 
         *                    will be blocked by the hardware.
         * @pgsize_bitmap: bitmap of all possible supported page sizes
         * @owner: Driver module providing these ops
++++++   * @identity_domain: An always available, always attachable identity
++++++   *                   translation.
++++++ + * @blocked_domain: An always available, always attachable blocking
++++++ + *                  translation.
++++++   * @default_domain: If not NULL this will always be set as the default domain.
++++++   *                  This should be an IDENTITY/BLOCKED/PLATFORM domain.
++++++   *                  Do not use in new drivers.
         */
        struct iommu_ops {
                bool (*capable)(struct device *dev, enum iommu_cap);
                const struct iommu_domain_ops *default_domain_ops;
                unsigned long pgsize_bitmap;
                struct module *owner;
++++++          struct iommu_domain *identity_domain;
++++++ +        struct iommu_domain *blocked_domain;
++++++          struct iommu_domain *default_domain;
        };
        
        /**