Merge tag 'iommu-updates-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git...
authorLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Oct 2014 05:23:49 +0000 (07:23 +0200)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 15 Oct 2014 05:23:49 +0000 (07:23 +0200)
Pull IOMMU updates from Joerg Roedel:
 "This pull-request includes:

   - change in the IOMMU-API to convert the former iommu_domain_capable
     function to just iommu_capable

   - various fixes in handling RMRR ranges for the VT-d driver (one fix
     requires a device driver core change which was acked by Greg KH)

   - the AMD IOMMU driver now assigns and deassigns complete alias
     groups to fix issues with devices using the wrong PCI request-id

   - MMU-401 support for the ARM SMMU driver

   - multi-master IOMMU group support for the ARM SMMU driver

   - various other small fixes all over the place"

* tag 'iommu-updates-v3.18' of git://git.kernel.org/pub/scm/linux/kernel/git/joro/iommu: (41 commits)
  iommu/vt-d: Work around broken RMRR firmware entries
  iommu/vt-d: Store bus information in RMRR PCI device path
  iommu/vt-d: Only remove domain when device is removed
  driver core: Add BUS_NOTIFY_REMOVED_DEVICE event
  iommu/amd: Fix devid mapping for ivrs_ioapic override
  iommu/irq_remapping: Fix the regression of hpet irq remapping
  iommu: Fix bus notifier breakage
  iommu/amd: Split init_iommu_group() from iommu_init_device()
  iommu: Rework iommu_group_get_for_pci_dev()
  iommu: Make of_device_id array const
  amd_iommu: do not dereference a NULL pointer address.
  iommu/omap: Remove omap_iommu unused owner field
  iommu: Remove iommu_domain_has_cap() API function
  IB/usnic: Convert to use new iommu_capable() API function
  vfio: Convert to use new iommu_capable() API function
  kvm: iommu: Convert to use new iommu_capable() API function
  iommu/tegra: Convert to iommu_capable() API function
  iommu/msm: Convert to iommu_capable() API function
  iommu/vt-d: Convert to iommu_capable() API function
  iommu/fsl: Convert to iommu_capable() API function
  ...

1  2 
drivers/base/core.c
drivers/vfio/vfio_iommu_type1.c
include/linux/device.h
include/linux/iommu.h
virt/kvm/iommu.c

diff --combined drivers/base/core.c
index 28b808c73e8ed14344472188794b94a14efea72f,7b270a2e6ed57dcf3028ee8a91425cfc4705c995..14d162952c3bc21bdadf3966ccef0c7b2c43df91
@@@ -1211,6 -1211,9 +1211,9 @@@ void device_del(struct device *dev
         */
        if (platform_notify_remove)
                platform_notify_remove(dev);
+       if (dev->bus)
+               blocking_notifier_call_chain(&dev->bus->p->bus_notifier,
+                                            BUS_NOTIFY_REMOVED_DEVICE, dev);
        kobject_uevent(&dev->kobj, KOBJ_REMOVE);
        cleanup_device_parent(dev);
        kobject_del(&dev->kobj);
@@@ -2007,8 -2010,6 +2010,8 @@@ create_syslog_header(const struct devic
                return 0;
  
        pos += snprintf(hdr + pos, hdrlen - pos, "SUBSYSTEM=%s", subsys);
 +      if (pos >= hdrlen)
 +              goto overflow;
  
        /*
         * Add device identifier DEVICE=:
                                "DEVICE=+%s:%s", subsys, dev_name(dev));
        }
  
 +      if (pos >= hdrlen)
 +              goto overflow;
 +
        return pos;
 +
 +overflow:
 +      dev_WARN(dev, "device/subsystem name too long");
 +      return 0;
  }
  
  int dev_vprintk_emit(int level, const struct device *dev,
index 583ccdb2c58f110fc45e7a7abdc56f81af8d3b4a,562f686b4cba558fe0e9af060890f0561adc1432..4a9d666f1e9186ed07071c0d909ba167e814998a
@@@ -57,8 -57,7 +57,8 @@@ struct vfio_iommu 
        struct list_head        domain_list;
        struct mutex            lock;
        struct rb_root          dma_list;
 -      bool v2;
 +      bool                    v2;
 +      bool                    nesting;
  };
  
  struct vfio_domain {
@@@ -706,15 -705,6 +706,15 @@@ static int vfio_iommu_type1_attach_grou
                goto out_free;
        }
  
 +      if (iommu->nesting) {
 +              int attr = 1;
 +
 +              ret = iommu_domain_set_attr(domain->domain, DOMAIN_ATTR_NESTING,
 +                                          &attr);
 +              if (ret)
 +                      goto out_domain;
 +      }
 +
        ret = iommu_attach_group(domain->domain, iommu_group);
        if (ret)
                goto out_domain;
        list_add(&group->next, &domain->group_list);
  
        if (!allow_unsafe_interrupts &&
-           !iommu_domain_has_cap(domain->domain, IOMMU_CAP_INTR_REMAP)) {
+           !iommu_capable(bus, IOMMU_CAP_INTR_REMAP)) {
                pr_warn("%s: No interrupt remapping support.  Use the module param \"allow_unsafe_interrupts\" to enable VFIO IOMMU support on this platform\n",
                       __func__);
                ret = -EPERM;
                goto out_detach;
        }
  
-       if (iommu_domain_has_cap(domain->domain, IOMMU_CAP_CACHE_COHERENCY))
+       if (iommu_capable(bus, IOMMU_CAP_CACHE_COHERENCY))
                domain->prot |= IOMMU_CACHE;
  
        /*
@@@ -829,26 -819,17 +829,26 @@@ static void *vfio_iommu_type1_open(unsi
  {
        struct vfio_iommu *iommu;
  
 -      if (arg != VFIO_TYPE1_IOMMU && arg != VFIO_TYPE1v2_IOMMU)
 -              return ERR_PTR(-EINVAL);
 -
        iommu = kzalloc(sizeof(*iommu), GFP_KERNEL);
        if (!iommu)
                return ERR_PTR(-ENOMEM);
  
 +      switch (arg) {
 +      case VFIO_TYPE1_IOMMU:
 +              break;
 +      case VFIO_TYPE1_NESTING_IOMMU:
 +              iommu->nesting = true;
 +      case VFIO_TYPE1v2_IOMMU:
 +              iommu->v2 = true;
 +              break;
 +      default:
 +              kfree(iommu);
 +              return ERR_PTR(-EINVAL);
 +      }
 +
        INIT_LIST_HEAD(&iommu->domain_list);
        iommu->dma_list = RB_ROOT;
        mutex_init(&iommu->lock);
 -      iommu->v2 = (arg == VFIO_TYPE1v2_IOMMU);
  
        return iommu;
  }
@@@ -904,7 -885,6 +904,7 @@@ static long vfio_iommu_type1_ioctl(voi
                switch (arg) {
                case VFIO_TYPE1_IOMMU:
                case VFIO_TYPE1v2_IOMMU:
 +              case VFIO_TYPE1_NESTING_IOMMU:
                        return 1;
                case VFIO_DMA_CC_IOMMU:
                        if (!iommu)
diff --combined include/linux/device.h
index a608e237f0a854c6312bb70f1fcd46c4c57da44c,d0d5c5db509dbf67d693b76510bf0cd7249b46bd..ce1f21608b168f9b1f1759f5f4eefd4c4d4beae5
@@@ -181,13 -181,14 +181,14 @@@ extern int bus_unregister_notifier(stru
   * with the device lock held in the core, so be careful.
   */
  #define BUS_NOTIFY_ADD_DEVICE         0x00000001 /* device added */
- #define BUS_NOTIFY_DEL_DEVICE         0x00000002 /* device removed */
- #define BUS_NOTIFY_BIND_DRIVER                0x00000003 /* driver about to be
+ #define BUS_NOTIFY_DEL_DEVICE         0x00000002 /* device to be removed */
+ #define BUS_NOTIFY_REMOVED_DEVICE     0x00000003 /* device removed */
+ #define BUS_NOTIFY_BIND_DRIVER                0x00000004 /* driver about to be
                                                      bound */
- #define BUS_NOTIFY_BOUND_DRIVER               0x00000004 /* driver bound to device */
- #define BUS_NOTIFY_UNBIND_DRIVER      0x00000005 /* driver about to be
+ #define BUS_NOTIFY_BOUND_DRIVER               0x00000005 /* driver bound to device */
+ #define BUS_NOTIFY_UNBIND_DRIVER      0x00000006 /* driver about to be
                                                      unbound */
- #define BUS_NOTIFY_UNBOUND_DRIVER     0x00000006 /* driver is unbound
+ #define BUS_NOTIFY_UNBOUND_DRIVER     0x00000007 /* driver is unbound
                                                      from the device */
  
  extern struct kset *bus_get_kset(struct bus_type *bus);
@@@ -607,8 -608,8 +608,8 @@@ extern int devres_release_group(struct 
  extern void *devm_kmalloc(struct device *dev, size_t size, gfp_t gfp);
  extern char *devm_kvasprintf(struct device *dev, gfp_t gfp, const char *fmt,
                             va_list ap);
 -extern char *devm_kasprintf(struct device *dev, gfp_t gfp,
 -                          const char *fmt, ...);
 +extern __printf(3, 4)
 +char *devm_kasprintf(struct device *dev, gfp_t gfp, const char *fmt, ...);
  static inline void *devm_kzalloc(struct device *dev, size_t size, gfp_t gfp)
  {
        return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
diff --combined include/linux/iommu.h
index 7b02bcc85b9ead2ced4308c6ff8a120006c1c793,379a6179fd96e80219c504c8e9a0378ce0d4fd5d..e6a7c9ff72f2a717ba643d4a2a7786f93a33497e
@@@ -57,8 -57,11 +57,11 @@@ struct iommu_domain 
        struct iommu_domain_geometry geometry;
  };
  
- #define IOMMU_CAP_CACHE_COHERENCY     0x1
- #define IOMMU_CAP_INTR_REMAP          0x2     /* isolates device intrs */
+ enum iommu_cap {
+       IOMMU_CAP_CACHE_COHERENCY,      /* IOMMU can enforce cache coherent DMA
+                                          transactions */
+       IOMMU_CAP_INTR_REMAP,           /* IOMMU supports interrupt isolation */
+ };
  
  /*
   * Following constraints are specifc to FSL_PAMUV1:
@@@ -80,7 -83,6 +83,7 @@@ enum iommu_attr 
        DOMAIN_ATTR_FSL_PAMU_STASH,
        DOMAIN_ATTR_FSL_PAMU_ENABLE,
        DOMAIN_ATTR_FSL_PAMUV1,
 +      DOMAIN_ATTR_NESTING,    /* two stages of translation */
        DOMAIN_ATTR_MAX,
  };
  
@@@ -95,7 -97,6 +98,6 @@@
   * @map: map a physically contiguous memory region to an iommu domain
   * @unmap: unmap a physically contiguous memory region from an iommu domain
   * @iova_to_phys: translate iova to physical address
-  * @domain_has_cap: domain capabilities query
   * @add_device: add device to iommu grouping
   * @remove_device: remove device from iommu grouping
   * @domain_get_attr: Query domain attributes
   * @pgsize_bitmap: bitmap of supported page sizes
   */
  struct iommu_ops {
+       bool (*capable)(enum iommu_cap);
        int (*domain_init)(struct iommu_domain *domain);
        void (*domain_destroy)(struct iommu_domain *domain);
        int (*attach_dev)(struct iommu_domain *domain, struct device *dev);
        size_t (*unmap)(struct iommu_domain *domain, unsigned long iova,
                     size_t size);
        phys_addr_t (*iova_to_phys)(struct iommu_domain *domain, dma_addr_t iova);
-       int (*domain_has_cap)(struct iommu_domain *domain,
-                             unsigned long cap);
        int (*add_device)(struct device *dev);
        void (*remove_device)(struct device *dev);
        int (*device_group)(struct device *dev, unsigned int *groupid);
  
  extern int bus_set_iommu(struct bus_type *bus, const struct iommu_ops *ops);
  extern bool iommu_present(struct bus_type *bus);
+ extern bool iommu_capable(struct bus_type *bus, enum iommu_cap cap);
  extern struct iommu_domain *iommu_domain_alloc(struct bus_type *bus);
  extern struct iommu_group *iommu_group_get_by_id(int id);
  extern void iommu_domain_free(struct iommu_domain *domain);
@@@ -155,8 -156,6 +157,6 @@@ extern int iommu_map(struct iommu_domai
  extern size_t iommu_unmap(struct iommu_domain *domain, unsigned long iova,
                       size_t size);
  extern phys_addr_t iommu_iova_to_phys(struct iommu_domain *domain, dma_addr_t iova);
- extern int iommu_domain_has_cap(struct iommu_domain *domain,
-                               unsigned long cap);
  extern void iommu_set_fault_handler(struct iommu_domain *domain,
                        iommu_fault_handler_t handler, void *token);
  
@@@ -251,6 -250,11 +251,11 @@@ static inline bool iommu_present(struc
        return false;
  }
  
+ static inline bool iommu_capable(struct bus_type *bus, enum iommu_cap cap)
+ {
+       return false;
+ }
  static inline struct iommu_domain *iommu_domain_alloc(struct bus_type *bus)
  {
        return NULL;
@@@ -305,12 -309,6 +310,6 @@@ static inline phys_addr_t iommu_iova_to
        return 0;
  }
  
- static inline int iommu_domain_has_cap(struct iommu_domain *domain,
-                                      unsigned long cap)
- {
-       return 0;
- }
  static inline void iommu_set_fault_handler(struct iommu_domain *domain,
                                iommu_fault_handler_t handler, void *token)
  {
diff --combined virt/kvm/iommu.c
index e723bb91aa346a3bbc0805e064a3823838d2a7c1,45ee080573f454e62fb5deb1cb4f6dd9d1077f38..e51d9f9b995f1864faa6921a41cc0809ce69fb8a
@@@ -191,8 -191,7 +191,7 @@@ int kvm_assign_device(struct kvm *kvm
                return r;
        }
  
-       noncoherent = !iommu_domain_has_cap(kvm->arch.iommu_domain,
-                                           IOMMU_CAP_CACHE_COHERENCY);
+       noncoherent = !iommu_capable(&pci_bus_type, IOMMU_CAP_CACHE_COHERENCY);
  
        /* Check if need to update IOMMU page table for guest memory */
        if (noncoherent != kvm->arch.iommu_noncoherent) {
                        goto out_unmap;
        }
  
 -      pdev->dev_flags |= PCI_DEV_FLAGS_ASSIGNED;
 +      pci_set_dev_assigned(pdev);
  
        dev_info(&pdev->dev, "kvm assign device\n");
  
@@@ -229,7 -228,7 +228,7 @@@ int kvm_deassign_device(struct kvm *kvm
  
        iommu_detach_device(domain, &pdev->dev);
  
 -      pdev->dev_flags &= ~PCI_DEV_FLAGS_ASSIGNED;
 +      pci_clear_dev_assigned(pdev);
  
        dev_info(&pdev->dev, "kvm deassign device\n");
  
@@@ -254,8 -253,7 +253,7 @@@ int kvm_iommu_map_guest(struct kvm *kvm
        }
  
        if (!allow_unsafe_assigned_interrupts &&
-           !iommu_domain_has_cap(kvm->arch.iommu_domain,
-                                 IOMMU_CAP_INTR_REMAP)) {
+           !iommu_capable(&pci_bus_type, IOMMU_CAP_INTR_REMAP)) {
                printk(KERN_WARNING "%s: No interrupt remapping support,"
                       " disallowing device assignment."
                       " Re-enble with \"allow_unsafe_assigned_interrupts=1\""