[PATCH 10/11] vfio-pci: introduce vfio_pci_core subsystem driver

From: Max Gurtovoy
Date: Thu Jun 03 2021 - 12:09:17 EST


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