diff options
author | Felipe Franciosi <felipe@nutanix.com> | 2019-07-02 14:06:42 +0100 |
---|---|---|
committer | Felipe Franciosi <felipe@nutanix.com> | 2019-09-05 16:45:35 +0100 |
commit | f8ef2771ca6c05dadd3188099eb678e6135e12e2 (patch) | |
tree | 1629283ee553622ce99477c63da4994d4c87bc0f /patches | |
download | libvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.zip libvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.tar.gz libvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.tar.bz2 |
Initial commit
Diffstat (limited to 'patches')
-rw-r--r-- | patches/vfio.diff | 192 |
1 files changed, 192 insertions, 0 deletions
diff --git a/patches/vfio.diff b/patches/vfio.diff new file mode 100644 index 0000000..d19da2e --- /dev/null +++ b/patches/vfio.diff @@ -0,0 +1,192 @@ +diff --git a/drivers/vfio/vfio.c b/drivers/vfio/vfio.c +index a3030cd..ab1b82c 100644 +--- a/drivers/vfio/vfio.c ++++ b/drivers/vfio/vfio.c +@@ -2019,15 +2019,24 @@ static int vfio_register_iommu_notifier(struct vfio_group *group, + int ret; + + ret = vfio_group_add_container_user(group); +- if (ret) ++ if (ret) { ++ pr_info("vfio_group_add_container_user failed with %d\n", ret); + return -EINVAL; ++ } + + container = group->container; + driver = container->iommu_driver; +- if (likely(driver && driver->ops->register_notifier)) ++ if (likely(driver && driver->ops->register_notifier)) { + ret = driver->ops->register_notifier(container->iommu_data, +- events, nb); +- else ++ events, nb); ++ if (unlikely(!ret) && driver->ops->retro_notify) { ++ ret = driver->ops->retro_notify(container->iommu_data); ++ if (unlikely((ret & NOTIFY_BAD) == NOTIFY_BAD)) ++ ret = -ENOTTY; ++ else ++ ret = 0; ++ } ++ } else + ret = -ENOTTY; + + vfio_group_try_dissolve_container(group); +@@ -2140,6 +2149,7 @@ int vfio_register_notifier(struct device *dev, enum vfio_notify_type type, + ret = vfio_register_group_notifier(group, events, nb); + break; + default: ++ pr_info("bad notification type %d\n", type); + ret = -EINVAL; + } + +diff --git a/drivers/vfio/vfio_iommu_type1.c b/drivers/vfio/vfio_iommu_type1.c +index d0f731c..b47b8f96 100644 +--- a/drivers/vfio/vfio_iommu_type1.c ++++ b/drivers/vfio/vfio_iommu_type1.c +@@ -558,8 +558,10 @@ static int vfio_iommu_type1_pin_pages(void *iommu_data, + return -EINVAL; + + /* Supported for v2 version only */ +- if (!iommu->v2) ++ if (!iommu->v2) { ++ pr_debug("non v2 IOMMU\n"); + return -EACCES; ++ } + + mutex_lock(&iommu->lock); + +@@ -1050,6 +1052,30 @@ static int vfio_pin_map_dma(struct vfio_iommu *iommu, struct vfio_dma *dma, + return ret; + } + ++static int vfio_dma_map_trigger_notifiers(struct vfio_iommu * const iommu, ++ struct vfio_dma const * const dma) ++ ++{ ++ struct vfio_iommu_type1_dma_map nb_map = {0}; ++ ++ BUG_ON(!iommu); ++ BUG_ON(!dma); ++ ++ nb_map.flags = dma->prot; ++ ++ if ((dma->prot & IOMMU_READ) == IOMMU_READ) ++ nb_map.flags |= VFIO_DMA_MAP_FLAG_READ; ++ if ((dma->prot & IOMMU_WRITE) == IOMMU_WRITE) ++ nb_map.flags |= VFIO_DMA_MAP_FLAG_WRITE; ++ nb_map.vaddr = dma->vaddr; ++ nb_map.iova = dma->iova; ++ nb_map.size = dma->size; ++ ++ return blocking_notifier_call_chain(&iommu->notifier, ++ VFIO_IOMMU_NOTIFY_DMA_MAP, ++ &nb_map); ++} ++ + static int vfio_dma_do_map(struct vfio_iommu *iommu, + struct vfio_iommu_type1_dma_map *map) + { +@@ -1139,13 +1165,25 @@ static int vfio_dma_do_map(struct vfio_iommu *iommu, + vfio_link_dma(iommu, dma); + + /* Don't pin and map if container doesn't contain IOMMU capable domain*/ +- if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) ++ if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu)) { + dma->size = size; +- else ++ ret = 0; ++ } else + ret = vfio_pin_map_dma(iommu, dma, size); + + out_unlock: + mutex_unlock(&iommu->lock); ++ /* FIXME is the following safe without having acquired the mutex? */ ++ if (!IS_IOMMU_CAP_DOMAIN_IN_CONTAINER(iommu) && !ret) { ++ ret = vfio_dma_map_trigger_notifiers(iommu, dma); ++ /* FIXME proceed or clean up and fail? */ ++ if ((ret & NOTIFY_BAD) == NOTIFY_BAD) { ++ pr_debug("failed to trigger notifier(s): %d\n", ret); ++ ret = -EINVAL; ++ } else ++ ret = 0; ++ } ++ + return ret; + } + +@@ -1504,8 +1542,11 @@ static void vfio_sanity_check_pfn_list(struct vfio_iommu *iommu) + + dma = rb_entry(n, struct vfio_dma, node); + +- if (WARN_ON(!RB_EMPTY_ROOT(&dma->pfn_list))) ++ if (WARN_ON(!RB_EMPTY_ROOT(&dma->pfn_list))) { ++ pr_debug("DMA region %llx-%llx still pinned\n", ++ dma->iova, dma->iova + dma->size); + break; ++ } + } + /* mdev vendor driver must unregister notifier */ + WARN_ON(iommu->notifier.head); +@@ -1740,7 +1781,7 @@ static int vfio_iommu_type1_register_notifier(void *iommu_data, + struct vfio_iommu *iommu = iommu_data; + + /* clear known events */ +- *events &= ~VFIO_IOMMU_NOTIFY_DMA_UNMAP; ++ *events &= ~(VFIO_IOMMU_NOTIFY_DMA_MAP | VFIO_IOMMU_NOTIFY_DMA_UNMAP); + + /* refuse to register if still events remaining */ + if (*events) +@@ -1749,6 +1790,25 @@ static int vfio_iommu_type1_register_notifier(void *iommu_data, + return blocking_notifier_chain_register(&iommu->notifier, nb); + } + ++static int vfio_iommu_type1_retro_notify(void *iommu_data) ++{ ++ int err = NOTIFY_OK; ++ struct vfio_iommu *iommu; ++ struct vfio_dma *pos, *n; ++ ++ BUG_ON(!iommu_data); ++ ++ iommu = (struct vfio_iommu*)iommu_data; ++ ++ rbtree_postorder_for_each_entry_safe(pos, n, &iommu->dma_list, node) { ++ err = vfio_dma_map_trigger_notifiers(iommu, pos); ++ if ((err & NOTIFY_BAD) == NOTIFY_BAD) ++ break; ++ } ++ ++ return err; ++} ++ + static int vfio_iommu_type1_unregister_notifier(void *iommu_data, + struct notifier_block *nb) + { +@@ -1769,6 +1829,7 @@ static const struct vfio_iommu_driver_ops vfio_iommu_driver_ops_type1 = { + .unpin_pages = vfio_iommu_type1_unpin_pages, + .register_notifier = vfio_iommu_type1_register_notifier, + .unregister_notifier = vfio_iommu_type1_unregister_notifier, ++ .retro_notify = vfio_iommu_type1_retro_notify, + }; + + static int __init vfio_iommu_type1_init(void) +diff --git a/include/linux/vfio.h b/include/linux/vfio.h +index 66741ab0..10ee80b 100644 +--- a/include/linux/vfio.h ++++ b/include/linux/vfio.h +@@ -85,6 +85,7 @@ struct vfio_iommu_driver_ops { + struct notifier_block *nb); + int (*unregister_notifier)(void *iommu_data, + struct notifier_block *nb); ++ int (*retro_notify)(void *iommu_data); + }; + + extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops); +@@ -118,6 +119,7 @@ enum vfio_notify_type { + + /* events for VFIO_IOMMU_NOTIFY */ + #define VFIO_IOMMU_NOTIFY_DMA_UNMAP BIT(0) ++#define VFIO_IOMMU_NOTIFY_DMA_MAP BIT(1) + + /* events for VFIO_GROUP_NOTIFY */ + #define VFIO_GROUP_NOTIFY_SET_KVM BIT(0) |