*/
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);
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,
struct list_head domain_list;
struct mutex lock;
struct rb_root dma_list;
- bool v2;
+ bool v2;
+ bool nesting;
};
struct vfio_domain {
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;
/*
{
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;
}
switch (arg) {
case VFIO_TYPE1_IOMMU:
case VFIO_TYPE1v2_IOMMU:
+ case VFIO_TYPE1_NESTING_IOMMU:
return 1;
case VFIO_DMA_CC_IOMMU:
if (!iommu)
* 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);
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);
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:
DOMAIN_ATTR_FSL_PAMU_STASH,
DOMAIN_ATTR_FSL_PAMU_ENABLE,
DOMAIN_ATTR_FSL_PAMUV1,
+ DOMAIN_ATTR_NESTING, /* two stages of translation */
DOMAIN_ATTR_MAX,
};
* @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);
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);
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;
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)
{
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");
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");
}
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\""