Now that vfio_pci has been split into two source modules, one focusing on the "struct pci_driver" (vfio_pci.c) and a toolbox library of code (vfio_pci_core.c), complete the split and move them into two different modules. As before vfio_pci.ko continues to present the same interface under sysfs and this change will have no functional impact. Below is an example for adding new driver that will use vfio pci subsystem: +---------------------------------------------------+ | | | VFIO | | | +---------------------------------------------------+ +---------------------------------------------------+ | | | VFIO_PCI_CORE | | | +---------------------------------------------------+ +----------+ +---------------+ +--------------------+ | | | | | | | VFIO_PCI | | MLX5_VFIO_PCI | | HISILICON_VFIO_PCI | | | | | | | +----------+ +---------------+ +--------------------+ Splitting into another module and adding exports allows creating new HW specific vfio_pci drivers that can implement device specific functionality, such as VFIO migration interfaces or specialized device requirements. Signed-off-by: Max Gurtovoy <mgurtovoy@xxxxxxxxxx> --- drivers/vfio/pci/Kconfig | 18 ++++++--- drivers/vfio/pci/Makefile | 11 +++-- drivers/vfio/pci/vfio_pci.c | 14 ++----- drivers/vfio/pci/vfio_pci_config.c | 2 +- drivers/vfio/pci/vfio_pci_core.c | 40 ++++++++++++++++--- drivers/vfio/pci/vfio_pci_igd.c | 2 +- drivers/vfio/pci/vfio_pci_intrs.c | 2 +- drivers/vfio/pci/vfio_pci_rdwr.c | 2 +- drivers/vfio/pci/vfio_pci_zdev.c | 2 +- .../pci => include/linux}/vfio_pci_core.h | 10 ++--- 10 files changed, 66 insertions(+), 37 deletions(-) rename {drivers/vfio/pci => include/linux}/vfio_pci_core.h (96%) diff --git a/drivers/vfio/pci/Kconfig b/drivers/vfio/pci/Kconfig index 5e2e1b9a9fd3..384d06661f30 100644 --- a/drivers/vfio/pci/Kconfig +++ b/drivers/vfio/pci/Kconfig @@ -1,6 +1,6 @@ # SPDX-License-Identifier: GPL-2.0-only -config VFIO_PCI - tristate "VFIO support for PCI devices" +config VFIO_PCI_CORE + tristate "VFIO core support for PCI devices" depends on VFIO && PCI && EVENTFD depends on MMU select VFIO_VIRQFD @@ -11,9 +11,17 @@ config VFIO_PCI If you don't know what to do here, say N. +config VFIO_PCI + tristate "VFIO support for PCI devices" + depends on VFIO_PCI_CORE + help + This provides a generic PCI support using the VFIO framework. + + If you don't know what to do here, say N. + config VFIO_PCI_VGA bool "VFIO PCI support for VGA devices" - depends on VFIO_PCI && X86 && VGA_ARB + depends on VFIO_PCI_CORE && X86 && VGA_ARB help Support for VGA extension to VFIO PCI. This exposes an additional region on VGA devices for accessing legacy VGA addresses used by @@ -22,11 +30,11 @@ config VFIO_PCI_VGA If you don't know what to do here, say N. config VFIO_PCI_MMAP - depends on VFIO_PCI + depends on VFIO_PCI_CORE def_bool y if !S390 config VFIO_PCI_INTX - depends on VFIO_PCI + depends on VFIO_PCI_CORE def_bool y if !S390 config VFIO_PCI_IGD diff --git a/drivers/vfio/pci/Makefile b/drivers/vfio/pci/Makefile index 8aa517b4b671..ddba4759cde7 100644 --- a/drivers/vfio/pci/Makefile +++ b/drivers/vfio/pci/Makefile @@ -1,7 +1,10 @@ # SPDX-License-Identifier: GPL-2.0-only -vfio-pci-y := vfio_pci.o vfio_pci_core.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o -vfio-pci-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.o -vfio-pci-$(CONFIG_S390) += vfio_pci_zdev.o - +obj-$(CONFIG_VFIO_PCI_CORE) += vfio-pci-core.o obj-$(CONFIG_VFIO_PCI) += vfio-pci.o + +vfio-pci-core-y := vfio_pci_core.o vfio_pci_intrs.o vfio_pci_rdwr.o vfio_pci_config.o +vfio-pci-core-$(CONFIG_S390) += vfio_pci_zdev.o + +vfio-pci-y := vfio_pci.o +vfio-pci-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.o diff --git a/drivers/vfio/pci/vfio_pci.c b/drivers/vfio/pci/vfio_pci.c index 9beb4b841945..56870a6540d7 100644 --- a/drivers/vfio/pci/vfio_pci.c +++ b/drivers/vfio/pci/vfio_pci.c @@ -25,7 +25,7 @@ #include <linux/types.h> #include <linux/uaccess.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> #define DRIVER_VERSION "0.2" #define DRIVER_AUTHOR "Alex Williamson <alex.williamson@xxxxxxxxxx>" @@ -141,6 +141,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) if (ret) goto out_free; + dev_set_drvdata(&pdev->dev, vdev); return 0; out_free: @@ -185,7 +186,6 @@ static struct pci_driver vfio_pci_driver = { static void __exit vfio_pci_cleanup(void) { pci_unregister_driver(&vfio_pci_driver); - vfio_pci_core_cleanup(); } static void __init vfio_pci_fill_ids(void) @@ -233,14 +233,10 @@ static int __init vfio_pci_init(void) { int ret; - ret = vfio_pci_core_init(); - if (ret) - return ret; - /* Register and scan for devices */ ret = pci_register_driver(&vfio_pci_driver); if (ret) - goto out; + return ret; vfio_pci_fill_ids(); @@ -248,10 +244,6 @@ static int __init vfio_pci_init(void) pr_warn("device denylist disabled.\n"); return 0; - -out: - vfio_pci_core_cleanup(); - return ret; } module_init(vfio_pci_init); diff --git a/drivers/vfio/pci/vfio_pci_config.c b/drivers/vfio/pci/vfio_pci_config.c index 1f034f768a27..6e58b4bf7a60 100644 --- a/drivers/vfio/pci/vfio_pci_config.c +++ b/drivers/vfio/pci/vfio_pci_config.c @@ -26,7 +26,7 @@ #include <linux/vfio.h> #include <linux/slab.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> /* Fake capability ID for standard config space */ #define PCI_CAP_ID_BASIC 0 diff --git a/drivers/vfio/pci/vfio_pci_core.c b/drivers/vfio/pci/vfio_pci_core.c index 39a3f18bbc08..a1ce79160f6f 100644 --- a/drivers/vfio/pci/vfio_pci_core.c +++ b/drivers/vfio/pci/vfio_pci_core.c @@ -8,6 +8,8 @@ * Author: Tom Lyon, pugs@xxxxxxxxx */ +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + #include <linux/device.h> #include <linux/eventfd.h> #include <linux/file.h> @@ -25,7 +27,11 @@ #include <linux/nospec.h> #include <linux/sched/mm.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> + +#define DRIVER_VERSION "0.2" +#define DRIVER_AUTHOR "Alex Williamson <alex.williamson@xxxxxxxxxx>" +#define DRIVER_DESC "core driver for VFIO based PCI devices" static bool nointxmask; module_param_named(nointxmask, nointxmask, bool, S_IRUGO | S_IWUSR); @@ -316,6 +322,7 @@ int vfio_pci_core_enable(struct vfio_pci_core_device *vdev) return 0; } +EXPORT_SYMBOL_GPL(vfio_pci_core_enable); void vfio_pci_core_disable(struct vfio_pci_core_device *vdev) { @@ -415,6 +422,7 @@ void vfio_pci_core_disable(struct vfio_pci_core_device *vdev) if (!disable_idle_d3) vfio_pci_set_power_state(vdev, PCI_D3hot); } +EXPORT_SYMBOL_GPL(vfio_pci_core_disable); static struct vfio_pci_core_device *get_pf_vdev(struct vfio_pci_core_device *vdev) { @@ -473,6 +481,7 @@ void vfio_pci_core_release(struct vfio_device *core_vdev) } mutex_unlock(&vdev->igate); } +EXPORT_SYMBOL_GPL(vfio_pci_core_release); void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev) { @@ -480,6 +489,7 @@ void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev) vfio_spapr_pci_eeh_open(vdev->pdev); vfio_pci_vf_token_user_add(vdev, 1); } +EXPORT_SYMBOL_GPL(vfio_pci_core_finish_enable); int vfio_pci_core_open(struct vfio_device *core_vdev) { @@ -497,6 +507,7 @@ int vfio_pci_core_open(struct vfio_device *core_vdev) return 0; } +EXPORT_SYMBOL_GPL(vfio_pci_core_open); static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type) { @@ -681,6 +692,7 @@ int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev, return 0; } +EXPORT_SYMBOL_GPL(vfio_pci_register_dev_region); struct vfio_devices { struct vfio_pci_core_device **devices; @@ -1287,6 +1299,7 @@ long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd, return -ENOTTY; } +EXPORT_SYMBOL_GPL(vfio_pci_core_ioctl); static ssize_t vfio_pci_rw(struct vfio_pci_core_device *vdev, char __user *buf, size_t count, loff_t *ppos, bool iswrite) @@ -1330,6 +1343,7 @@ ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf, return vfio_pci_rw(vdev, buf, count, ppos, false); } +EXPORT_SYMBOL_GPL(vfio_pci_core_read); ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf, size_t count, loff_t *ppos) @@ -1342,6 +1356,7 @@ ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *bu return vfio_pci_rw(vdev, (char __user *)buf, count, ppos, true); } +EXPORT_SYMBOL_GPL(vfio_pci_core_write); /* Return 1 on zap and vma_lock acquired, 0 on contention (only with @try) */ static int vfio_pci_zap_and_vma_lock(struct vfio_pci_core_device *vdev, bool try) @@ -1607,6 +1622,7 @@ int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma return 0; } +EXPORT_SYMBOL_GPL(vfio_pci_core_mmap); void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count) { @@ -1629,6 +1645,7 @@ void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count) mutex_unlock(&vdev->igate); } +EXPORT_SYMBOL_GPL(vfio_pci_core_request); static int vfio_pci_validate_vf_token(struct vfio_pci_core_device *vdev, bool vf_token, uuid_t *uuid) @@ -1773,6 +1790,7 @@ int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf) return 1; /* Match */ } +EXPORT_SYMBOL_GPL(vfio_pci_core_match); static int vfio_pci_reflck_find(struct pci_dev *pdev, void *data) { @@ -1814,6 +1832,7 @@ int vfio_pci_core_reflck_attach(struct vfio_device *core_vdev) return PTR_ERR_OR_ZERO(core_vdev->reflck); } +EXPORT_SYMBOL_GPL(vfio_pci_core_reflck_attach); static int vfio_pci_bus_notifier(struct notifier_block *nb, unsigned long action, void *data) @@ -1972,7 +1991,6 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev, ret = vfio_register_group_dev(&vdev->vdev); if (ret) goto out_power; - dev_set_drvdata(&pdev->dev, vdev); return 0; out_power: @@ -1987,6 +2005,7 @@ int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev, vfio_iommu_group_put(group, &pdev->dev); return ret; } +EXPORT_SYMBOL_GPL(vfio_pci_core_register_device); void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev) { @@ -2009,6 +2028,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev) kfree(vdev->region); kfree(vdev->pm_save); } +EXPORT_SYMBOL_GPL(vfio_pci_core_unregister_device); static pci_ers_result_t vfio_pci_aer_err_detected(struct pci_dev *pdev, pci_channel_state_t state) @@ -2054,10 +2074,12 @@ int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn) return ret < 0 ? ret : nr_virtfn; } +EXPORT_SYMBOL_GPL(vfio_pci_core_sriov_configure); const struct pci_error_handlers vfio_pci_core_err_handlers = { .error_detected = vfio_pci_aer_err_detected, }; +EXPORT_SYMBOL_GPL(vfio_pci_core_err_handlers); static int vfio_pci_get_unused_devs(struct pci_dev *pdev, void *data) { @@ -2197,15 +2219,21 @@ static void vfio_pci_try_bus_reset(struct vfio_pci_core_device *vdev) kfree(devs.devices); } -/* This will become the __exit function of vfio_pci_core.ko */ -void vfio_pci_core_cleanup(void) +static void vfio_pci_core_cleanup(void) { vfio_pci_uninit_perm_bits(); } -/* This will become the __init function of vfio_pci_core.ko */ -int __init vfio_pci_core_init(void) +static int __init vfio_pci_core_init(void) { /* Allocate shared config space permission data used by all devices */ return vfio_pci_init_perm_bits(); } + +module_init(vfio_pci_core_init); +module_exit(vfio_pci_core_cleanup); + +MODULE_VERSION(DRIVER_VERSION); +MODULE_LICENSE("GPL v2"); +MODULE_AUTHOR(DRIVER_AUTHOR); +MODULE_DESCRIPTION(DRIVER_DESC); diff --git a/drivers/vfio/pci/vfio_pci_igd.c b/drivers/vfio/pci/vfio_pci_igd.c index 2295eaac4bc9..f04774cd3a7f 100644 --- a/drivers/vfio/pci/vfio_pci_igd.c +++ b/drivers/vfio/pci/vfio_pci_igd.c @@ -15,7 +15,7 @@ #include <linux/uaccess.h> #include <linux/vfio.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> #define OPREGION_SIGNATURE "IntelGraphicsMem" #define OPREGION_SIZE (8 * 1024) diff --git a/drivers/vfio/pci/vfio_pci_intrs.c b/drivers/vfio/pci/vfio_pci_intrs.c index 945ddbdf4d11..6069a11fb51a 100644 --- a/drivers/vfio/pci/vfio_pci_intrs.c +++ b/drivers/vfio/pci/vfio_pci_intrs.c @@ -20,7 +20,7 @@ #include <linux/wait.h> #include <linux/slab.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> /* * INTx diff --git a/drivers/vfio/pci/vfio_pci_rdwr.c b/drivers/vfio/pci/vfio_pci_rdwr.c index 8fff4689dd44..57d3b2cbbd8e 100644 --- a/drivers/vfio/pci/vfio_pci_rdwr.c +++ b/drivers/vfio/pci/vfio_pci_rdwr.c @@ -17,7 +17,7 @@ #include <linux/vfio.h> #include <linux/vgaarb.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> #ifdef __LITTLE_ENDIAN #define vfio_ioread64 ioread64 diff --git a/drivers/vfio/pci/vfio_pci_zdev.c b/drivers/vfio/pci/vfio_pci_zdev.c index 2ffbdc11f089..fe4def9ffffb 100644 --- a/drivers/vfio/pci/vfio_pci_zdev.c +++ b/drivers/vfio/pci/vfio_pci_zdev.c @@ -19,7 +19,7 @@ #include <asm/pci_clp.h> #include <asm/pci_io.h> -#include "vfio_pci_core.h" +#include <linux/vfio_pci_core.h> /* * Add the Base PCI Function information to the device info region. diff --git a/drivers/vfio/pci/vfio_pci_core.h b/include/linux/vfio_pci_core.h similarity index 96% rename from drivers/vfio/pci/vfio_pci_core.h rename to include/linux/vfio_pci_core.h index 406e934e23b2..5a48c3c552b1 100644 --- a/drivers/vfio/pci/vfio_pci_core.h +++ b/include/linux/vfio_pci_core.h @@ -171,10 +171,10 @@ extern void vfio_pci_uninit_perm_bits(void); extern int vfio_config_init(struct vfio_pci_core_device *vdev); extern void vfio_config_free(struct vfio_pci_core_device *vdev); -extern int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev, - unsigned int type, unsigned int subtype, - const struct vfio_pci_regops *ops, - size_t size, u32 flags, void *data); +int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev, + unsigned int type, unsigned int subtype, + const struct vfio_pci_regops *ops, + size_t size, u32 flags, void *data); extern int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev, pci_power_t state); @@ -207,8 +207,6 @@ static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev, #endif /* Will be exported for vfio pci drivers usage */ -void vfio_pci_core_cleanup(void); -int vfio_pci_core_init(void); void vfio_pci_core_release(struct vfio_device *core_vdev); int vfio_pci_core_open(struct vfio_device *core_vdev); int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev, -- 2.21.0