vfio/pci: Introduce vfio_pci_core.ko
authorMax Gurtovoy <mgurtovoy@nvidia.com>
Thu, 26 Aug 2021 10:39:12 +0000 (13:39 +0300)
committerAlex Williamson <alex.williamson@redhat.com>
Thu, 26 Aug 2021 16:36:51 +0000 (10:36 -0600)
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
kernel modules.

As before vfio_pci.ko continues to present the same interface under sysfs
and this change will have no functional impact.

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@nvidia.com>
Signed-off-by: Jason Gunthorpe <jgg@nvidia.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Signed-off-by: Yishai Hadas <yishaih@nvidia.com>
Link: https://lore.kernel.org/r/20210826103912.128972-14-yishaih@nvidia.com
Signed-off-by: Alex Williamson <alex.williamson@redhat.com>
12 files changed:
MAINTAINERS
drivers/vfio/pci/Kconfig
drivers/vfio/pci/Makefile
drivers/vfio/pci/vfio_pci.c
drivers/vfio/pci/vfio_pci_config.c
drivers/vfio/pci/vfio_pci_core.c
drivers/vfio/pci/vfio_pci_core.h [deleted file]
drivers/vfio/pci/vfio_pci_igd.c
drivers/vfio/pci/vfio_pci_intrs.c
drivers/vfio/pci/vfio_pci_rdwr.c
drivers/vfio/pci/vfio_pci_zdev.c
include/linux/vfio_pci_core.h [new file with mode: 0644]

index c9467d2839f5e894adc11c06949a842a0a9bd39f..7f0fcaa8ee677fbea740c7bc11e968f449f6153f 100644 (file)
@@ -19466,6 +19466,7 @@ T:      git git://github.com/awilliam/linux-vfio.git
 F:     Documentation/driver-api/vfio.rst
 F:     drivers/vfio/
 F:     include/linux/vfio.h
+F:     include/linux/vfio_pci_core.h
 F:     include/uapi/linux/vfio.h
 
 VFIO FSL-MC DRIVER
index afdab7d71e98cc1e16606b0a4fcdec987b10cab2..860424ccda1bf11f1662a4629b068c353db42964 100644 (file)
@@ -1,19 +1,28 @@
 # SPDX-License-Identifier: GPL-2.0-only
-config VFIO_PCI
-       tristate "VFIO support for PCI devices"
-       depends on PCI
-       depends on MMU
+if PCI && MMU
+config VFIO_PCI_CORE
+       tristate
        select VFIO_VIRQFD
        select IRQ_BYPASS_MANAGER
+
+config VFIO_PCI_MMAP
+       def_bool y if !S390
+
+config VFIO_PCI_INTX
+       def_bool y if !S390
+
+config VFIO_PCI
+       tristate "Generic VFIO support for any PCI device"
+       select VFIO_PCI_CORE
        help
-         Support for the PCI VFIO bus driver.  This is required to make
-         use of PCI drivers using the VFIO framework.
+         Support for the generic PCI VFIO bus driver which can connect any
+         PCI device to the VFIO framework.
 
          If you don't know what to do here, say N.
 
 if VFIO_PCI
 config VFIO_PCI_VGA
-       bool "VFIO PCI support for VGA devices"
+       bool "Generic VFIO PCI support for VGA devices"
        depends on X86 && VGA_ARB
        help
          Support for VGA extension to VFIO PCI.  This exposes an additional
@@ -22,14 +31,8 @@ config VFIO_PCI_VGA
 
          If you don't know what to do here, say N.
 
-config VFIO_PCI_MMAP
-       def_bool y if !S390
-
-config VFIO_PCI_INTX
-       def_bool y if !S390
-
 config VFIO_PCI_IGD
-       bool "VFIO PCI extensions for Intel graphics (GVT-d)"
+       bool "Generic VFIO PCI extensions for Intel graphics (GVT-d)"
        depends on X86
        default y
        help
@@ -39,5 +42,5 @@ config VFIO_PCI_IGD
          and LPC bridge config space.
 
          To enable Intel IGD assignment through vfio-pci, say Y.
-
+endif
 endif
index 8aa517b4b67171bb4a907394c4ac5d7a15ef9c2f..349d68d242b4253c5dae31efc9a8c6343c4ca434 100644 (file)
@@ -1,7 +1,9 @@
 # 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
+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
+obj-$(CONFIG_VFIO_PCI_CORE) += vfio-pci-core.o
 
+vfio-pci-y := vfio_pci.o
+vfio-pci-$(CONFIG_VFIO_PCI_IGD) += vfio_pci_igd.o
 obj-$(CONFIG_VFIO_PCI) += vfio-pci.o
index 85fd638a59553b08b472b487935ff63be1945993..a5ce92beb6557d45f03851b42779a684f03c0580 100644 (file)
@@ -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_AUTHOR   "Alex Williamson <alex.williamson@redhat.com>"
 #define DRIVER_DESC     "VFIO PCI - User Level meta-driver"
@@ -153,6 +153,7 @@ static int vfio_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        ret = vfio_pci_core_register_device(vdev);
        if (ret)
                goto out_free;
+       dev_set_drvdata(&pdev->dev, vdev);
        return 0;
 
 out_free:
@@ -246,14 +247,10 @@ static int __init vfio_pci_init(void)
 
        vfio_pci_core_set_params(nointxmask, is_disable_vga, disable_idle_d3);
 
-       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();
 
@@ -261,17 +258,12 @@ 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);
 
 static void __exit vfio_pci_cleanup(void)
 {
        pci_unregister_driver(&vfio_pci_driver);
-       vfio_pci_core_cleanup();
 }
 module_exit(vfio_pci_cleanup);
 
index 1f034f768a27094ad1da8f385662296091e2201b..6e58b4bf7a60139dfd716c6ba2d6d8f31dbd72fb 100644 (file)
@@ -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
index 65eafaafb2e05cb79eec413426ff8839ccdd5815..675616e08897195663bf4f49fe1c6ef11cbbe0a7 100644 (file)
@@ -8,6 +8,8 @@
  * Author: Tom Lyon, pugs@cisco.com
  */
 
+#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+
 #include <linux/device.h>
 #include <linux/eventfd.h>
 #include <linux/file.h>
 #include <linux/nospec.h>
 #include <linux/sched/mm.h>
 
-#include "vfio_pci_core.h"
+#include <linux/vfio_pci_core.h>
+
+#define DRIVER_AUTHOR   "Alex Williamson <alex.williamson@redhat.com>"
+#define DRIVER_DESC "core driver for VFIO based PCI devices"
 
 static bool nointxmask;
 static bool disable_vga;
@@ -306,6 +311,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)
 {
@@ -403,6 +409,7 @@ out:
        if (!vfio_pci_dev_set_try_reset(vdev->vdev.dev_set) && !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)
 {
@@ -459,6 +466,7 @@ void vfio_pci_core_close_device(struct vfio_device *core_vdev)
        }
        mutex_unlock(&vdev->igate);
 }
+EXPORT_SYMBOL_GPL(vfio_pci_core_close_device);
 
 void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev)
 {
@@ -466,6 +474,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);
 
 static int vfio_pci_get_irq_count(struct vfio_pci_core_device *vdev, int irq_type)
 {
@@ -624,6 +633,7 @@ int vfio_pci_register_dev_region(struct vfio_pci_core_device *vdev,
 
        return 0;
 }
+EXPORT_SYMBOL_GPL(vfio_pci_register_dev_region);
 
 long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
                unsigned long arg)
@@ -1168,6 +1178,7 @@ hot_reset_release:
 
        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)
@@ -1211,6 +1222,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)
@@ -1223,6 +1235,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)
@@ -1501,6 +1514,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)
 {
@@ -1523,6 +1537,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)
@@ -1667,6 +1682,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_bus_notifier(struct notifier_block *nb,
                                 unsigned long action, void *data)
@@ -1775,6 +1791,7 @@ void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
        INIT_LIST_HEAD(&vdev->vma_list);
        init_rwsem(&vdev->memory_lock);
 }
+EXPORT_SYMBOL_GPL(vfio_pci_core_init_device);
 
 void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev)
 {
@@ -1785,6 +1802,7 @@ void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev)
        kfree(vdev->region);
        kfree(vdev->pm_save);
 }
+EXPORT_SYMBOL_GPL(vfio_pci_core_uninit_device);
 
 int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev)
 {
@@ -1852,7 +1870,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:
@@ -1864,6 +1881,7 @@ out_group_put:
        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)
 {
@@ -1881,6 +1899,7 @@ void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev)
        if (!disable_idle_d3)
                vfio_pci_set_power_state(vdev, PCI_D0);
 }
+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)
@@ -1924,10 +1943,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 bool vfio_dev_in_groups(struct vfio_pci_core_device *vdev,
                               struct vfio_pci_group_info *groups)
@@ -2116,16 +2137,22 @@ void vfio_pci_core_set_params(bool is_nointxmask, bool is_disable_vga,
        disable_vga = is_disable_vga;
        disable_idle_d3 = is_disable_idle_d3;
 }
+EXPORT_SYMBOL_GPL(vfio_pci_core_set_params);
 
-/* 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_LICENSE("GPL v2");
+MODULE_AUTHOR(DRIVER_AUTHOR);
+MODULE_DESCRIPTION(DRIVER_DESC);
diff --git a/drivers/vfio/pci/vfio_pci_core.h b/drivers/vfio/pci/vfio_pci_core.h
deleted file mode 100644 (file)
index 7a2da1e..0000000
+++ /dev/null
@@ -1,241 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-only */
-/*
- * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
- *     Author: Alex Williamson <alex.williamson@redhat.com>
- *
- * Derived from original vfio:
- * Copyright 2010 Cisco Systems, Inc.  All rights reserved.
- * Author: Tom Lyon, pugs@cisco.com
- */
-
-#include <linux/mutex.h>
-#include <linux/pci.h>
-#include <linux/vfio.h>
-#include <linux/irqbypass.h>
-#include <linux/types.h>
-#include <linux/uuid.h>
-#include <linux/notifier.h>
-
-#ifndef VFIO_PCI_CORE_H
-#define VFIO_PCI_CORE_H
-
-#define VFIO_PCI_OFFSET_SHIFT   40
-
-#define VFIO_PCI_OFFSET_TO_INDEX(off)  (off >> VFIO_PCI_OFFSET_SHIFT)
-#define VFIO_PCI_INDEX_TO_OFFSET(index)        ((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
-#define VFIO_PCI_OFFSET_MASK   (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
-
-/* Special capability IDs predefined access */
-#define PCI_CAP_ID_INVALID             0xFF    /* default raw access */
-#define PCI_CAP_ID_INVALID_VIRT                0xFE    /* default virt access */
-
-/* Cap maximum number of ioeventfds per device (arbitrary) */
-#define VFIO_PCI_IOEVENTFD_MAX         1000
-
-struct vfio_pci_ioeventfd {
-       struct list_head        next;
-       struct vfio_pci_core_device     *vdev;
-       struct virqfd           *virqfd;
-       void __iomem            *addr;
-       uint64_t                data;
-       loff_t                  pos;
-       int                     bar;
-       int                     count;
-       bool                    test_mem;
-};
-
-struct vfio_pci_irq_ctx {
-       struct eventfd_ctx      *trigger;
-       struct virqfd           *unmask;
-       struct virqfd           *mask;
-       char                    *name;
-       bool                    masked;
-       struct irq_bypass_producer      producer;
-};
-
-struct vfio_pci_core_device;
-struct vfio_pci_region;
-
-struct vfio_pci_regops {
-       ssize_t (*rw)(struct vfio_pci_core_device *vdev, char __user *buf,
-                     size_t count, loff_t *ppos, bool iswrite);
-       void    (*release)(struct vfio_pci_core_device *vdev,
-                          struct vfio_pci_region *region);
-       int     (*mmap)(struct vfio_pci_core_device *vdev,
-                       struct vfio_pci_region *region,
-                       struct vm_area_struct *vma);
-       int     (*add_capability)(struct vfio_pci_core_device *vdev,
-                                 struct vfio_pci_region *region,
-                                 struct vfio_info_cap *caps);
-};
-
-struct vfio_pci_region {
-       u32                             type;
-       u32                             subtype;
-       const struct vfio_pci_regops    *ops;
-       void                            *data;
-       size_t                          size;
-       u32                             flags;
-};
-
-struct vfio_pci_dummy_resource {
-       struct resource         resource;
-       int                     index;
-       struct list_head        res_next;
-};
-
-struct vfio_pci_vf_token {
-       struct mutex            lock;
-       uuid_t                  uuid;
-       int                     users;
-};
-
-struct vfio_pci_mmap_vma {
-       struct vm_area_struct   *vma;
-       struct list_head        vma_next;
-};
-
-struct vfio_pci_core_device {
-       struct vfio_device      vdev;
-       struct pci_dev          *pdev;
-       void __iomem            *barmap[PCI_STD_NUM_BARS];
-       bool                    bar_mmap_supported[PCI_STD_NUM_BARS];
-       u8                      *pci_config_map;
-       u8                      *vconfig;
-       struct perm_bits        *msi_perm;
-       spinlock_t              irqlock;
-       struct mutex            igate;
-       struct vfio_pci_irq_ctx *ctx;
-       int                     num_ctx;
-       int                     irq_type;
-       int                     num_regions;
-       struct vfio_pci_region  *region;
-       u8                      msi_qmax;
-       u8                      msix_bar;
-       u16                     msix_size;
-       u32                     msix_offset;
-       u32                     rbar[7];
-       bool                    pci_2_3;
-       bool                    virq_disabled;
-       bool                    reset_works;
-       bool                    extended_caps;
-       bool                    bardirty;
-       bool                    has_vga;
-       bool                    needs_reset;
-       bool                    nointx;
-       bool                    needs_pm_restore;
-       struct pci_saved_state  *pci_saved_state;
-       struct pci_saved_state  *pm_save;
-       int                     ioeventfds_nr;
-       struct eventfd_ctx      *err_trigger;
-       struct eventfd_ctx      *req_trigger;
-       struct list_head        dummy_resources_list;
-       struct mutex            ioeventfds_lock;
-       struct list_head        ioeventfds_list;
-       struct vfio_pci_vf_token        *vf_token;
-       struct notifier_block   nb;
-       struct mutex            vma_lock;
-       struct list_head        vma_list;
-       struct rw_semaphore     memory_lock;
-};
-
-#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
-#define is_msi(vdev) (vdev->irq_type == VFIO_PCI_MSI_IRQ_INDEX)
-#define is_msix(vdev) (vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX)
-#define is_irq_none(vdev) (!(is_intx(vdev) || is_msi(vdev) || is_msix(vdev)))
-#define irq_is(vdev, type) (vdev->irq_type == type)
-
-extern void vfio_pci_intx_mask(struct vfio_pci_core_device *vdev);
-extern void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev);
-
-extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_core_device *vdev,
-                                  uint32_t flags, unsigned index,
-                                  unsigned start, unsigned count, void *data);
-
-extern ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
-                                 char __user *buf, size_t count,
-                                 loff_t *ppos, bool iswrite);
-
-extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
-                              size_t count, loff_t *ppos, bool iswrite);
-
-extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
-                              size_t count, loff_t *ppos, bool iswrite);
-
-extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
-                              uint64_t data, int count, int fd);
-
-extern int vfio_pci_init_perm_bits(void);
-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);
-
-extern int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
-                                   pci_power_t state);
-
-extern bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev);
-extern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device
-                                                   *vdev);
-extern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev);
-extern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev,
-                                              u16 cmd);
-
-#ifdef CONFIG_VFIO_PCI_IGD
-extern int vfio_pci_igd_init(struct vfio_pci_core_device *vdev);
-#else
-static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
-{
-       return -ENODEV;
-}
-#endif
-
-#ifdef CONFIG_S390
-extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
-                                      struct vfio_info_cap *caps);
-#else
-static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
-                                             struct vfio_info_cap *caps)
-{
-       return -ENODEV;
-}
-#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_set_params(bool nointxmask, bool is_disable_vga,
-                             bool is_disable_idle_d3);
-void vfio_pci_core_close_device(struct vfio_device *core_vdev);
-void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
-                              struct pci_dev *pdev,
-                              const struct vfio_device_ops *vfio_pci_ops);
-int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev);
-void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev);
-void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev);
-int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn);
-extern const struct pci_error_handlers vfio_pci_core_err_handlers;
-long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
-               unsigned long arg);
-ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
-               size_t count, loff_t *ppos);
-ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
-               size_t count, loff_t *ppos);
-int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma);
-void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count);
-int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf);
-int vfio_pci_core_enable(struct vfio_pci_core_device *vdev);
-void vfio_pci_core_disable(struct vfio_pci_core_device *vdev);
-void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev);
-
-static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
-{
-       return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
-}
-
-#endif /* VFIO_PCI_CORE_H */
index a324ca7e6b5a2907ca40458c713dd0c615f6c093..7ca4109bba48281f5fcc850b01300e91c64eb792 100644 (file)
@@ -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)
index 945ddbdf4d11bbb6ff20f19f377998799bf59f5b..6069a11fb51acf418bc89a787fb96e81325fbedb 100644 (file)
@@ -20,7 +20,7 @@
 #include <linux/wait.h>
 #include <linux/slab.h>
 
-#include "vfio_pci_core.h"
+#include <linux/vfio_pci_core.h>
 
 /*
  * INTx
index 8fff4689dd44db328b6033a3e5a3db30f7732228..57d3b2cbbd8e5aa08d3ba2a270a4d1fa6ec31ab2 100644 (file)
@@ -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
index 2ffbdc11f08942815e157fa27ea431b0d13e5e83..fe4def9ffffb7518ca8132d8776ec8a7a7b2f4df 100644 (file)
@@ -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/include/linux/vfio_pci_core.h b/include/linux/vfio_pci_core.h
new file mode 100644 (file)
index 0000000..ef9a44b
--- /dev/null
@@ -0,0 +1,239 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/*
+ * Copyright (C) 2012 Red Hat, Inc.  All rights reserved.
+ *     Author: Alex Williamson <alex.williamson@redhat.com>
+ *
+ * Derived from original vfio:
+ * Copyright 2010 Cisco Systems, Inc.  All rights reserved.
+ * Author: Tom Lyon, pugs@cisco.com
+ */
+
+#include <linux/mutex.h>
+#include <linux/pci.h>
+#include <linux/vfio.h>
+#include <linux/irqbypass.h>
+#include <linux/types.h>
+#include <linux/uuid.h>
+#include <linux/notifier.h>
+
+#ifndef VFIO_PCI_CORE_H
+#define VFIO_PCI_CORE_H
+
+#define VFIO_PCI_OFFSET_SHIFT   40
+
+#define VFIO_PCI_OFFSET_TO_INDEX(off)  (off >> VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_INDEX_TO_OFFSET(index)        ((u64)(index) << VFIO_PCI_OFFSET_SHIFT)
+#define VFIO_PCI_OFFSET_MASK   (((u64)(1) << VFIO_PCI_OFFSET_SHIFT) - 1)
+
+/* Special capability IDs predefined access */
+#define PCI_CAP_ID_INVALID             0xFF    /* default raw access */
+#define PCI_CAP_ID_INVALID_VIRT                0xFE    /* default virt access */
+
+/* Cap maximum number of ioeventfds per device (arbitrary) */
+#define VFIO_PCI_IOEVENTFD_MAX         1000
+
+struct vfio_pci_ioeventfd {
+       struct list_head        next;
+       struct vfio_pci_core_device     *vdev;
+       struct virqfd           *virqfd;
+       void __iomem            *addr;
+       uint64_t                data;
+       loff_t                  pos;
+       int                     bar;
+       int                     count;
+       bool                    test_mem;
+};
+
+struct vfio_pci_irq_ctx {
+       struct eventfd_ctx      *trigger;
+       struct virqfd           *unmask;
+       struct virqfd           *mask;
+       char                    *name;
+       bool                    masked;
+       struct irq_bypass_producer      producer;
+};
+
+struct vfio_pci_core_device;
+struct vfio_pci_region;
+
+struct vfio_pci_regops {
+       ssize_t (*rw)(struct vfio_pci_core_device *vdev, char __user *buf,
+                     size_t count, loff_t *ppos, bool iswrite);
+       void    (*release)(struct vfio_pci_core_device *vdev,
+                          struct vfio_pci_region *region);
+       int     (*mmap)(struct vfio_pci_core_device *vdev,
+                       struct vfio_pci_region *region,
+                       struct vm_area_struct *vma);
+       int     (*add_capability)(struct vfio_pci_core_device *vdev,
+                                 struct vfio_pci_region *region,
+                                 struct vfio_info_cap *caps);
+};
+
+struct vfio_pci_region {
+       u32                             type;
+       u32                             subtype;
+       const struct vfio_pci_regops    *ops;
+       void                            *data;
+       size_t                          size;
+       u32                             flags;
+};
+
+struct vfio_pci_dummy_resource {
+       struct resource         resource;
+       int                     index;
+       struct list_head        res_next;
+};
+
+struct vfio_pci_vf_token {
+       struct mutex            lock;
+       uuid_t                  uuid;
+       int                     users;
+};
+
+struct vfio_pci_mmap_vma {
+       struct vm_area_struct   *vma;
+       struct list_head        vma_next;
+};
+
+struct vfio_pci_core_device {
+       struct vfio_device      vdev;
+       struct pci_dev          *pdev;
+       void __iomem            *barmap[PCI_STD_NUM_BARS];
+       bool                    bar_mmap_supported[PCI_STD_NUM_BARS];
+       u8                      *pci_config_map;
+       u8                      *vconfig;
+       struct perm_bits        *msi_perm;
+       spinlock_t              irqlock;
+       struct mutex            igate;
+       struct vfio_pci_irq_ctx *ctx;
+       int                     num_ctx;
+       int                     irq_type;
+       int                     num_regions;
+       struct vfio_pci_region  *region;
+       u8                      msi_qmax;
+       u8                      msix_bar;
+       u16                     msix_size;
+       u32                     msix_offset;
+       u32                     rbar[7];
+       bool                    pci_2_3;
+       bool                    virq_disabled;
+       bool                    reset_works;
+       bool                    extended_caps;
+       bool                    bardirty;
+       bool                    has_vga;
+       bool                    needs_reset;
+       bool                    nointx;
+       bool                    needs_pm_restore;
+       struct pci_saved_state  *pci_saved_state;
+       struct pci_saved_state  *pm_save;
+       int                     ioeventfds_nr;
+       struct eventfd_ctx      *err_trigger;
+       struct eventfd_ctx      *req_trigger;
+       struct list_head        dummy_resources_list;
+       struct mutex            ioeventfds_lock;
+       struct list_head        ioeventfds_list;
+       struct vfio_pci_vf_token        *vf_token;
+       struct notifier_block   nb;
+       struct mutex            vma_lock;
+       struct list_head        vma_list;
+       struct rw_semaphore     memory_lock;
+};
+
+#define is_intx(vdev) (vdev->irq_type == VFIO_PCI_INTX_IRQ_INDEX)
+#define is_msi(vdev) (vdev->irq_type == VFIO_PCI_MSI_IRQ_INDEX)
+#define is_msix(vdev) (vdev->irq_type == VFIO_PCI_MSIX_IRQ_INDEX)
+#define is_irq_none(vdev) (!(is_intx(vdev) || is_msi(vdev) || is_msix(vdev)))
+#define irq_is(vdev, type) (vdev->irq_type == type)
+
+extern void vfio_pci_intx_mask(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_intx_unmask(struct vfio_pci_core_device *vdev);
+
+extern int vfio_pci_set_irqs_ioctl(struct vfio_pci_core_device *vdev,
+                                  uint32_t flags, unsigned index,
+                                  unsigned start, unsigned count, void *data);
+
+extern ssize_t vfio_pci_config_rw(struct vfio_pci_core_device *vdev,
+                                 char __user *buf, size_t count,
+                                 loff_t *ppos, bool iswrite);
+
+extern ssize_t vfio_pci_bar_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+                              size_t count, loff_t *ppos, bool iswrite);
+
+extern ssize_t vfio_pci_vga_rw(struct vfio_pci_core_device *vdev, char __user *buf,
+                              size_t count, loff_t *ppos, bool iswrite);
+
+extern long vfio_pci_ioeventfd(struct vfio_pci_core_device *vdev, loff_t offset,
+                              uint64_t data, int count, int fd);
+
+extern int vfio_pci_init_perm_bits(void);
+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);
+
+extern int vfio_pci_set_power_state(struct vfio_pci_core_device *vdev,
+                                   pci_power_t state);
+
+extern bool __vfio_pci_memory_enabled(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_zap_and_down_write_memory_lock(struct vfio_pci_core_device
+                                                   *vdev);
+extern u16 vfio_pci_memory_lock_and_enable(struct vfio_pci_core_device *vdev);
+extern void vfio_pci_memory_unlock_and_restore(struct vfio_pci_core_device *vdev,
+                                              u16 cmd);
+
+#ifdef CONFIG_VFIO_PCI_IGD
+extern int vfio_pci_igd_init(struct vfio_pci_core_device *vdev);
+#else
+static inline int vfio_pci_igd_init(struct vfio_pci_core_device *vdev)
+{
+       return -ENODEV;
+}
+#endif
+
+#ifdef CONFIG_S390
+extern int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
+                                      struct vfio_info_cap *caps);
+#else
+static inline int vfio_pci_info_zdev_add_caps(struct vfio_pci_core_device *vdev,
+                                             struct vfio_info_cap *caps)
+{
+       return -ENODEV;
+}
+#endif
+
+/* Will be exported for vfio pci drivers usage */
+void vfio_pci_core_set_params(bool nointxmask, bool is_disable_vga,
+                             bool is_disable_idle_d3);
+void vfio_pci_core_close_device(struct vfio_device *core_vdev);
+void vfio_pci_core_init_device(struct vfio_pci_core_device *vdev,
+                              struct pci_dev *pdev,
+                              const struct vfio_device_ops *vfio_pci_ops);
+int vfio_pci_core_register_device(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_uninit_device(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_unregister_device(struct vfio_pci_core_device *vdev);
+int vfio_pci_core_sriov_configure(struct pci_dev *pdev, int nr_virtfn);
+extern const struct pci_error_handlers vfio_pci_core_err_handlers;
+long vfio_pci_core_ioctl(struct vfio_device *core_vdev, unsigned int cmd,
+               unsigned long arg);
+ssize_t vfio_pci_core_read(struct vfio_device *core_vdev, char __user *buf,
+               size_t count, loff_t *ppos);
+ssize_t vfio_pci_core_write(struct vfio_device *core_vdev, const char __user *buf,
+               size_t count, loff_t *ppos);
+int vfio_pci_core_mmap(struct vfio_device *core_vdev, struct vm_area_struct *vma);
+void vfio_pci_core_request(struct vfio_device *core_vdev, unsigned int count);
+int vfio_pci_core_match(struct vfio_device *core_vdev, char *buf);
+int vfio_pci_core_enable(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_disable(struct vfio_pci_core_device *vdev);
+void vfio_pci_core_finish_enable(struct vfio_pci_core_device *vdev);
+
+static inline bool vfio_pci_is_vga(struct pci_dev *pdev)
+{
+       return (pdev->class >> 8) == PCI_CLASS_DISPLAY_VGA;
+}
+
+#endif /* VFIO_PCI_CORE_H */