Commit d9a0cd51 authored by Alex Williamson's avatar Alex Williamson

Merge branch 'v5.16/vfio/hch-cleanup-vfio-iommu_group-creation-v6' into v5.16/vfio/next

parents 02d5e016 3f901389
...@@ -351,7 +351,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev) ...@@ -351,7 +351,7 @@ static int vfio_ap_mdev_probe(struct mdev_device *mdev)
list_add(&matrix_mdev->node, &matrix_dev->mdev_list); list_add(&matrix_mdev->node, &matrix_dev->mdev_list);
mutex_unlock(&matrix_dev->lock); mutex_unlock(&matrix_dev->lock);
ret = vfio_register_group_dev(&matrix_mdev->vdev); ret = vfio_register_emulated_iommu_dev(&matrix_mdev->vdev);
if (ret) if (ret)
goto err_list; goto err_list;
dev_set_drvdata(&mdev->dev, matrix_mdev); dev_set_drvdata(&mdev->dev, matrix_mdev);
......
...@@ -505,22 +505,13 @@ static void vfio_fsl_uninit_device(struct vfio_fsl_mc_device *vdev) ...@@ -505,22 +505,13 @@ static void vfio_fsl_uninit_device(struct vfio_fsl_mc_device *vdev)
static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
{ {
struct iommu_group *group;
struct vfio_fsl_mc_device *vdev; struct vfio_fsl_mc_device *vdev;
struct device *dev = &mc_dev->dev; struct device *dev = &mc_dev->dev;
int ret; int ret;
group = vfio_iommu_group_get(dev);
if (!group) {
dev_err(dev, "VFIO_FSL_MC: No IOMMU group\n");
return -EINVAL;
}
vdev = kzalloc(sizeof(*vdev), GFP_KERNEL); vdev = kzalloc(sizeof(*vdev), GFP_KERNEL);
if (!vdev) { if (!vdev)
ret = -ENOMEM; return -ENOMEM;
goto out_group_put;
}
vfio_init_group_dev(&vdev->vdev, dev, &vfio_fsl_mc_ops); vfio_init_group_dev(&vdev->vdev, dev, &vfio_fsl_mc_ops);
vdev->mc_dev = mc_dev; vdev->mc_dev = mc_dev;
...@@ -556,8 +547,6 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev) ...@@ -556,8 +547,6 @@ static int vfio_fsl_mc_probe(struct fsl_mc_device *mc_dev)
out_uninit: out_uninit:
vfio_uninit_group_dev(&vdev->vdev); vfio_uninit_group_dev(&vdev->vdev);
kfree(vdev); kfree(vdev);
out_group_put:
vfio_iommu_group_put(group, dev);
return ret; return ret;
} }
...@@ -574,8 +563,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev) ...@@ -574,8 +563,6 @@ static int vfio_fsl_mc_remove(struct fsl_mc_device *mc_dev)
vfio_uninit_group_dev(&vdev->vdev); vfio_uninit_group_dev(&vdev->vdev);
kfree(vdev); kfree(vdev);
vfio_iommu_group_put(mc_dev->dev.iommu_group, dev);
return 0; return 0;
} }
......
...@@ -13,60 +13,23 @@ ...@@ -13,60 +13,23 @@
#include "mdev_private.h" #include "mdev_private.h"
static int mdev_attach_iommu(struct mdev_device *mdev)
{
int ret;
struct iommu_group *group;
group = iommu_group_alloc();
if (IS_ERR(group))
return PTR_ERR(group);
ret = iommu_group_add_device(group, &mdev->dev);
if (!ret)
dev_info(&mdev->dev, "MDEV: group_id = %d\n",
iommu_group_id(group));
iommu_group_put(group);
return ret;
}
static void mdev_detach_iommu(struct mdev_device *mdev)
{
iommu_group_remove_device(&mdev->dev);
dev_info(&mdev->dev, "MDEV: detaching iommu\n");
}
static int mdev_probe(struct device *dev) static int mdev_probe(struct device *dev)
{ {
struct mdev_driver *drv = struct mdev_driver *drv =
container_of(dev->driver, struct mdev_driver, driver); container_of(dev->driver, struct mdev_driver, driver);
struct mdev_device *mdev = to_mdev_device(dev);
int ret;
ret = mdev_attach_iommu(mdev); if (!drv->probe)
if (ret) return 0;
return ret; return drv->probe(to_mdev_device(dev));
if (drv->probe) {
ret = drv->probe(mdev);
if (ret)
mdev_detach_iommu(mdev);
}
return ret;
} }
static void mdev_remove(struct device *dev) static void mdev_remove(struct device *dev)
{ {
struct mdev_driver *drv = struct mdev_driver *drv =
container_of(dev->driver, struct mdev_driver, driver); container_of(dev->driver, struct mdev_driver, driver);
struct mdev_device *mdev = to_mdev_device(dev);
if (drv->remove) if (drv->remove)
drv->remove(mdev); drv->remove(to_mdev_device(dev));
mdev_detach_iommu(mdev);
} }
static int mdev_match(struct device *dev, struct device_driver *drv) static int mdev_match(struct device *dev, struct device_driver *drv)
......
...@@ -119,7 +119,7 @@ static int vfio_mdev_probe(struct mdev_device *mdev) ...@@ -119,7 +119,7 @@ static int vfio_mdev_probe(struct mdev_device *mdev)
return -ENOMEM; return -ENOMEM;
vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops); vfio_init_group_dev(vdev, &mdev->dev, &vfio_mdev_dev_ops);
ret = vfio_register_group_dev(vdev); ret = vfio_register_emulated_iommu_dev(vdev);
if (ret) if (ret)
goto out_uninit; goto out_uninit;
......
...@@ -1806,7 +1806,6 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_uninit_device); ...@@ -1806,7 +1806,6 @@ EXPORT_SYMBOL_GPL(vfio_pci_core_uninit_device);
int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
{ {
struct pci_dev *pdev = vdev->pdev; struct pci_dev *pdev = vdev->pdev;
struct iommu_group *group;
int ret; int ret;
if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL) if (pdev->hdr_type != PCI_HEADER_TYPE_NORMAL)
...@@ -1825,10 +1824,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) ...@@ -1825,10 +1824,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
return -EBUSY; return -EBUSY;
} }
group = vfio_iommu_group_get(&pdev->dev);
if (!group)
return -EINVAL;
if (pci_is_root_bus(pdev->bus)) { if (pci_is_root_bus(pdev->bus)) {
ret = vfio_assign_device_set(&vdev->vdev, vdev); ret = vfio_assign_device_set(&vdev->vdev, vdev);
} else if (!pci_probe_reset_slot(pdev->slot)) { } else if (!pci_probe_reset_slot(pdev->slot)) {
...@@ -1842,10 +1837,10 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) ...@@ -1842,10 +1837,10 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
} }
if (ret) if (ret)
goto out_group_put; return ret;
ret = vfio_pci_vf_init(vdev); ret = vfio_pci_vf_init(vdev);
if (ret) if (ret)
goto out_group_put; return ret;
ret = vfio_pci_vga_init(vdev); ret = vfio_pci_vga_init(vdev);
if (ret) if (ret)
goto out_vf; goto out_vf;
...@@ -1876,8 +1871,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev) ...@@ -1876,8 +1871,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
vfio_pci_set_power_state(vdev, PCI_D0); vfio_pci_set_power_state(vdev, PCI_D0);
out_vf: out_vf:
vfio_pci_vf_uninit(vdev); vfio_pci_vf_uninit(vdev);
out_group_put:
vfio_iommu_group_put(group, &pdev->dev);
return ret; return ret;
} }
EXPORT_SYMBOL_GPL(vfio_pci_core_register_device); EXPORT_SYMBOL_GPL(vfio_pci_core_register_device);
...@@ -1893,8 +1886,6 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev) ...@@ -1893,8 +1886,6 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
vfio_pci_vf_uninit(vdev); vfio_pci_vf_uninit(vdev);
vfio_pci_vga_uninit(vdev); vfio_pci_vga_uninit(vdev);
vfio_iommu_group_put(pdev->dev.iommu_group, &pdev->dev);
if (!disable_idle_d3) if (!disable_idle_d3)
vfio_pci_set_power_state(vdev, PCI_D0); vfio_pci_set_power_state(vdev, PCI_D0);
} }
......
...@@ -642,7 +642,6 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev, ...@@ -642,7 +642,6 @@ static int vfio_platform_of_probe(struct vfio_platform_device *vdev,
int vfio_platform_probe_common(struct vfio_platform_device *vdev, int vfio_platform_probe_common(struct vfio_platform_device *vdev,
struct device *dev) struct device *dev)
{ {
struct iommu_group *group;
int ret; int ret;
vfio_init_group_dev(&vdev->vdev, dev, &vfio_platform_ops); vfio_init_group_dev(&vdev->vdev, dev, &vfio_platform_ops);
...@@ -663,24 +662,15 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev, ...@@ -663,24 +662,15 @@ int vfio_platform_probe_common(struct vfio_platform_device *vdev,
goto out_uninit; goto out_uninit;
} }
group = vfio_iommu_group_get(dev);
if (!group) {
dev_err(dev, "No IOMMU group for device %s\n", vdev->name);
ret = -EINVAL;
goto put_reset;
}
ret = vfio_register_group_dev(&vdev->vdev); ret = vfio_register_group_dev(&vdev->vdev);
if (ret) if (ret)
goto put_iommu; goto put_reset;
mutex_init(&vdev->igate); mutex_init(&vdev->igate);
pm_runtime_enable(dev); pm_runtime_enable(dev);
return 0; return 0;
put_iommu:
vfio_iommu_group_put(group, dev);
put_reset: put_reset:
vfio_platform_put_reset(vdev); vfio_platform_put_reset(vdev);
out_uninit: out_uninit:
...@@ -696,7 +686,6 @@ void vfio_platform_remove_common(struct vfio_platform_device *vdev) ...@@ -696,7 +686,6 @@ void vfio_platform_remove_common(struct vfio_platform_device *vdev)
pm_runtime_disable(vdev->device); pm_runtime_disable(vdev->device);
vfio_platform_put_reset(vdev); vfio_platform_put_reset(vdev);
vfio_uninit_group_dev(&vdev->vdev); vfio_uninit_group_dev(&vdev->vdev);
vfio_iommu_group_put(vdev->vdev.dev->iommu_group, vdev->vdev.dev);
} }
EXPORT_SYMBOL_GPL(vfio_platform_remove_common); EXPORT_SYMBOL_GPL(vfio_platform_remove_common);
......
This diff is collapsed.
/* SPDX-License-Identifier: GPL-2.0-only */
/*
* Copyright (C) 2012 Red Hat, Inc. All rights reserved.
* Author: Alex Williamson <alex.williamson@redhat.com>
*/
enum vfio_group_type {
/*
* Physical device with IOMMU backing.
*/
VFIO_IOMMU,
/*
* Virtual device without IOMMU backing. The VFIO core fakes up an
* iommu_group as the iommu_group sysfs interface is part of the
* userspace ABI. The user of these devices must not be able to
* directly trigger unmediated DMA.
*/
VFIO_EMULATED_IOMMU,
/*
* Physical device without IOMMU backing. The VFIO core fakes up an
* iommu_group as the iommu_group sysfs interface is part of the
* userspace ABI. Users can trigger unmediated DMA by the device,
* usage is highly dangerous, requires an explicit opt-in and will
* taint the kernel.
*/
VFIO_NO_IOMMU,
};
/* events for the backend driver notify callback */
enum vfio_iommu_notify_type {
VFIO_IOMMU_CONTAINER_CLOSE = 0,
};
/**
* struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
*/
struct vfio_iommu_driver_ops {
char *name;
struct module *owner;
void *(*open)(unsigned long arg);
void (*release)(void *iommu_data);
long (*ioctl)(void *iommu_data, unsigned int cmd,
unsigned long arg);
int (*attach_group)(void *iommu_data,
struct iommu_group *group,
enum vfio_group_type);
void (*detach_group)(void *iommu_data,
struct iommu_group *group);
int (*pin_pages)(void *iommu_data,
struct iommu_group *group,
unsigned long *user_pfn,
int npage, int prot,
unsigned long *phys_pfn);
int (*unpin_pages)(void *iommu_data,
unsigned long *user_pfn, int npage);
int (*register_notifier)(void *iommu_data,
unsigned long *events,
struct notifier_block *nb);
int (*unregister_notifier)(void *iommu_data,
struct notifier_block *nb);
int (*dma_rw)(void *iommu_data, dma_addr_t user_iova,
void *data, size_t count, bool write);
struct iommu_domain *(*group_iommu_domain)(void *iommu_data,
struct iommu_group *group);
void (*notify)(void *iommu_data,
enum vfio_iommu_notify_type event);
};
int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
void vfio_unregister_iommu_driver(const struct vfio_iommu_driver_ops *ops);
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
#include <linux/sched/mm.h> #include <linux/sched/mm.h>
#include <linux/sched/signal.h> #include <linux/sched/signal.h>
#include <linux/mm.h> #include <linux/mm.h>
#include "vfio.h"
#include <asm/iommu.h> #include <asm/iommu.h>
#include <asm/tce.h> #include <asm/tce.h>
...@@ -1238,13 +1239,16 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container, ...@@ -1238,13 +1239,16 @@ static long tce_iommu_take_ownership_ddw(struct tce_container *container,
} }
static int tce_iommu_attach_group(void *iommu_data, static int tce_iommu_attach_group(void *iommu_data,
struct iommu_group *iommu_group) struct iommu_group *iommu_group, enum vfio_group_type type)
{ {
int ret = 0; int ret = 0;
struct tce_container *container = iommu_data; struct tce_container *container = iommu_data;
struct iommu_table_group *table_group; struct iommu_table_group *table_group;
struct tce_iommu_group *tcegrp = NULL; struct tce_iommu_group *tcegrp = NULL;
if (type == VFIO_EMULATED_IOMMU)
return -EINVAL;
mutex_lock(&container->lock); mutex_lock(&container->lock);
/* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n", /* pr_debug("tce_vfio: Attaching group #%u to iommu %p\n",
......
This diff is collapsed.
...@@ -18,7 +18,6 @@ struct mdev_device { ...@@ -18,7 +18,6 @@ struct mdev_device {
void *driver_data; void *driver_data;
struct list_head next; struct list_head next;
struct mdev_type *type; struct mdev_type *type;
struct device *iommu_device;
bool active; bool active;
}; };
...@@ -27,25 +26,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev) ...@@ -27,25 +26,6 @@ static inline struct mdev_device *to_mdev_device(struct device *dev)
return container_of(dev, struct mdev_device, dev); return container_of(dev, struct mdev_device, dev);
} }
/*
* Called by the parent device driver to set the device which represents
* this mdev in iommu protection scope. By default, the iommu device is
* NULL, that indicates using vendor defined isolation.
*
* @dev: the mediated device that iommu will isolate.
* @iommu_device: a pci device which represents the iommu for @dev.
*/
static inline void mdev_set_iommu_device(struct mdev_device *mdev,
struct device *iommu_device)
{
mdev->iommu_device = iommu_device;
}
static inline struct device *mdev_get_iommu_device(struct mdev_device *mdev)
{
return mdev->iommu_device;
}
unsigned int mdev_get_type_group_id(struct mdev_device *mdev); unsigned int mdev_get_type_group_id(struct mdev_device *mdev);
unsigned int mtype_get_type_group_id(struct mdev_type *mtype); unsigned int mtype_get_type_group_id(struct mdev_type *mtype);
struct device *mtype_get_parent_dev(struct mdev_type *mtype); struct device *mtype_get_parent_dev(struct mdev_type *mtype);
......
...@@ -71,68 +71,17 @@ struct vfio_device_ops { ...@@ -71,68 +71,17 @@ struct vfio_device_ops {
int (*match)(struct vfio_device *vdev, char *buf); int (*match)(struct vfio_device *vdev, char *buf);
}; };
extern struct iommu_group *vfio_iommu_group_get(struct device *dev);
extern void vfio_iommu_group_put(struct iommu_group *group, struct device *dev);
void vfio_init_group_dev(struct vfio_device *device, struct device *dev, void vfio_init_group_dev(struct vfio_device *device, struct device *dev,
const struct vfio_device_ops *ops); const struct vfio_device_ops *ops);
void vfio_uninit_group_dev(struct vfio_device *device); void vfio_uninit_group_dev(struct vfio_device *device);
int vfio_register_group_dev(struct vfio_device *device); int vfio_register_group_dev(struct vfio_device *device);
int vfio_register_emulated_iommu_dev(struct vfio_device *device);
void vfio_unregister_group_dev(struct vfio_device *device); void vfio_unregister_group_dev(struct vfio_device *device);
extern struct vfio_device *vfio_device_get_from_dev(struct device *dev); extern struct vfio_device *vfio_device_get_from_dev(struct device *dev);
extern void vfio_device_put(struct vfio_device *device); extern void vfio_device_put(struct vfio_device *device);
int vfio_assign_device_set(struct vfio_device *device, void *set_id); int vfio_assign_device_set(struct vfio_device *device, void *set_id);
/* events for the backend driver notify callback */
enum vfio_iommu_notify_type {
VFIO_IOMMU_CONTAINER_CLOSE = 0,
};
/**
* struct vfio_iommu_driver_ops - VFIO IOMMU driver callbacks
*/
struct vfio_iommu_driver_ops {
char *name;
struct module *owner;
void *(*open)(unsigned long arg);
void (*release)(void *iommu_data);
ssize_t (*read)(void *iommu_data, char __user *buf,
size_t count, loff_t *ppos);
ssize_t (*write)(void *iommu_data, const char __user *buf,
size_t count, loff_t *size);
long (*ioctl)(void *iommu_data, unsigned int cmd,
unsigned long arg);
int (*mmap)(void *iommu_data, struct vm_area_struct *vma);
int (*attach_group)(void *iommu_data,
struct iommu_group *group);
void (*detach_group)(void *iommu_data,
struct iommu_group *group);
int (*pin_pages)(void *iommu_data,
struct iommu_group *group,
unsigned long *user_pfn,
int npage, int prot,
unsigned long *phys_pfn);
int (*unpin_pages)(void *iommu_data,
unsigned long *user_pfn, int npage);
int (*register_notifier)(void *iommu_data,
unsigned long *events,
struct notifier_block *nb);
int (*unregister_notifier)(void *iommu_data,
struct notifier_block *nb);
int (*dma_rw)(void *iommu_data, dma_addr_t user_iova,
void *data, size_t count, bool write);
struct iommu_domain *(*group_iommu_domain)(void *iommu_data,
struct iommu_group *group);
void (*notify)(void *iommu_data,
enum vfio_iommu_notify_type event);
};
extern int vfio_register_iommu_driver(const struct vfio_iommu_driver_ops *ops);
extern void vfio_unregister_iommu_driver(
const struct vfio_iommu_driver_ops *ops);
/* /*
* External user API * External user API
*/ */
......
...@@ -553,7 +553,7 @@ static int mbochs_probe(struct mdev_device *mdev) ...@@ -553,7 +553,7 @@ static int mbochs_probe(struct mdev_device *mdev)
mbochs_create_config_space(mdev_state); mbochs_create_config_space(mdev_state);
mbochs_reset(mdev_state); mbochs_reset(mdev_state);
ret = vfio_register_group_dev(&mdev_state->vdev); ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev);
if (ret) if (ret)
goto err_mem; goto err_mem;
dev_set_drvdata(&mdev->dev, mdev_state); dev_set_drvdata(&mdev->dev, mdev_state);
......
...@@ -258,7 +258,7 @@ static int mdpy_probe(struct mdev_device *mdev) ...@@ -258,7 +258,7 @@ static int mdpy_probe(struct mdev_device *mdev)
mdpy_count++; mdpy_count++;
ret = vfio_register_group_dev(&mdev_state->vdev); ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev);
if (ret) if (ret)
goto err_mem; goto err_mem;
dev_set_drvdata(&mdev->dev, mdev_state); dev_set_drvdata(&mdev->dev, mdev_state);
......
...@@ -741,7 +741,7 @@ static int mtty_probe(struct mdev_device *mdev) ...@@ -741,7 +741,7 @@ static int mtty_probe(struct mdev_device *mdev)
mtty_create_config_space(mdev_state); mtty_create_config_space(mdev_state);
ret = vfio_register_group_dev(&mdev_state->vdev); ret = vfio_register_emulated_iommu_dev(&mdev_state->vdev);
if (ret) if (ret)
goto err_vconfig; goto err_vconfig;
dev_set_drvdata(&mdev->dev, mdev_state); dev_set_drvdata(&mdev->dev, mdev_state);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment