aboutsummaryrefslogtreecommitdiff
path: root/patches
diff options
context:
space:
mode:
authorFelipe Franciosi <felipe@nutanix.com>2019-07-02 14:06:42 +0100
committerFelipe Franciosi <felipe@nutanix.com>2019-09-05 16:45:35 +0100
commitf8ef2771ca6c05dadd3188099eb678e6135e12e2 (patch)
tree1629283ee553622ce99477c63da4994d4c87bc0f /patches
downloadlibvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.zip
libvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.tar.gz
libvfio-user-f8ef2771ca6c05dadd3188099eb678e6135e12e2.tar.bz2
Initial commit
Diffstat (limited to 'patches')
-rw-r--r--patches/vfio.diff192
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)