aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2025-09-11 12:40:38 +0100
committerPeter Maydell <peter.maydell@linaro.org>2025-09-11 12:40:38 +0100
commit7aba16fdd88a742b3886c3bcdb9b4057c9d9658e (patch)
tree2b8433ba9bf89e4ac1932303f20cad945bf324a4
parent769acb2a1e47b97ada8e0db6ff73e303b23764d8 (diff)
parentbb986792a968ee51cda72cd4cc05822198495375 (diff)
downloadqemu-7aba16fdd88a742b3886c3bcdb9b4057c9d9658e.zip
qemu-7aba16fdd88a742b3886c3bcdb9b4057c9d9658e.tar.gz
qemu-7aba16fdd88a742b3886c3bcdb9b4057c9d9658e.tar.bz2
Merge tag 'pull-vfio-20250908' of https://github.com/legoater/qemu into staging
vfio queue: * Large refactor of the VFIO code to use QOM casts and follow the current coding style guidelines * Removal of the deprecated vfio-platform, vfio-calxeda-xgmac and vfio-amd-xgbe devices * Fail with error if dma_max_mappings limit is hit * Added 'x-pci-class-code' property to vfio-user-pci device * Added a new helper to retrieve a VFIOPCIDevice from a VFIODevice * Fixed IGD OpRegion detection # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEoPZlSPBIlev+awtgUaNDx8/77KEFAmi/CfMACgkQUaNDx8/7 # 7KFkbhAAmbIxFxqLzRO3vnsSRGMkBnvZiQdz/b/iHHV8Uj6eJ6Vr5YxoR2c4XQqz # kkU1+sBBezIWWWQ1dwRW19oObFp8ZvZKWT5AELqSXu/Svdh/kcJ99JnZa+JoK+r9 # rMTFEyjKOc0p9IDI1EIT6wJSqtUi2nXm3w1M4O1qkC17KriLtNLxtxEPCc6l6Ks4 # 0SEDddcVBhk8T0Jb8bHuRoaXqCER11bH07xzCQWTI7tW3cebX6622+F+H72/GvL9 # Gzs/61xTnoiIyGMs+jKM1hoURF0Fvv24zaHmSImxZX1vvF+ezeaRl2equ/H6AbDl # 0+ShqRIj4XChRe0jf+08UDMor9sjRZYRw7NDSkM7hf9kS2VU/44FutAeOL0qAjb4 # oQqIAA1XBqDUW+5SzuzF2t2idBokLKH+d6qEmTTaMQEMrCDzv6Rx41e+27S3Qmai # Ir+D37S57rrUvQFT6asCu6SOIrUPQHPZHDZkod7VPFTNsJkIaHzlViThzip4+CxO # WbO8j0qXYq6OZ4C99GngkosT750DHoLrH5CKujNS4qHAqjisH145xkChM6LwFpzO # o6SlBJg9mmMAsV7hHONk9x1GyESXHsoECQhjXrR7Yibv5ffPapEm/ruG3/gnZ5jA # AgnQLrbKrla5AX8UsGi/Pz75BqadWBC0uABtYV+A0XTEluMC+0Q= # =8KqI # -----END PGP SIGNATURE----- # gpg: Signature made Mon 08 Sep 2025 17:53:07 BST # gpg: using RSA key A0F66548F04895EBFE6B0B6051A343C7CFFBECA1 # gpg: Good signature from "Cédric Le Goater <clg@redhat.com>" [full] # gpg: aka "Cédric Le Goater <clg@kaod.org>" [full] # Primary key fingerprint: A0F6 6548 F048 95EB FE6B 0B60 51A3 43C7 CFFB ECA1 * tag 'pull-vfio-20250908' of https://github.com/legoater/qemu: (31 commits) vfio/pci.h: rename VFIOPCIDevice pdev field to parent_obj s390x/s390-pci-vfio.c: use QOM casts where appropriate vfio-user/pci.c: use QOM casts where appropriate vfio/igd.c: use QOM casts where appropriate vfio/cpr.c: use QOM casts where appropriate vfio/pci-quirks.c: use QOM casts where appropriate vfio/pci.c: use QOM casts where appropriate vfio/pci.h: update VFIOPCIDevice declaration vfio-user/pci.c: rename VFIOUserPCIDevice device field to parent_obj vfio-user/pci.c: use QOM casts where appropriate vfio-user/pci.c: update VFIOUserPCIDevice declaration vfio-user/container.h: rename VFIOUserContainer bcontainer field to parent_obj vfio/container.c: use QOM casts where appropriate vfio-user/container.h: update VFIOUserContainer declaration vfio/vfio-container.h: rename VFIOContainer bcontainer field to parent_obj vfio/spapr.c: use QOM casts where appropriate ppc/spapr_pci_vfio.c: use QOM casts where appropriate hw/vfio/container.c: use QOM casts where appropriate hw/vfio/cpr-legacy.c: use QOM casts where appropriate vfio/vfio-container.h: update VFIOContainer declaration ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
-rw-r--r--MAINTAINERS2
-rw-r--r--docs/about/deprecated.rst25
-rw-r--r--docs/about/removed-features.rst25
-rw-r--r--docs/devel/kconfig.rst2
-rw-r--r--hw/arm/Kconfig3
-rw-r--r--hw/arm/virt.c5
-rw-r--r--hw/core/sysbus-fdt.c383
-rw-r--r--hw/ppc/spapr_pci_vfio.c2
-rw-r--r--hw/s390x/s390-pci-vfio.c14
-rw-r--r--hw/vfio-user/container.c26
-rw-r--r--hw/vfio-user/container.h7
-rw-r--r--hw/vfio-user/pci.c18
-rw-r--r--hw/vfio/Kconfig16
-rw-r--r--hw/vfio/amd-xgbe.c61
-rw-r--r--hw/vfio/calxeda-xgmac.c61
-rw-r--r--hw/vfio/container.c35
-rw-r--r--hw/vfio/cpr-legacy.c14
-rw-r--r--hw/vfio/cpr.c12
-rw-r--r--hw/vfio/device.c2
-rw-r--r--hw/vfio/igd.c45
-rw-r--r--hw/vfio/iommufd.c4
-rw-r--r--hw/vfio/listener.c20
-rw-r--r--hw/vfio/meson.build3
-rw-r--r--hw/vfio/pci-quirks.c48
-rw-r--r--hw/vfio/pci.c217
-rw-r--r--hw/vfio/pci.h20
-rw-r--r--hw/vfio/platform.c716
-rw-r--r--hw/vfio/spapr.c16
-rw-r--r--hw/vfio/trace-events11
-rw-r--r--hw/vfio/vfio-region.h (renamed from include/hw/vfio/vfio-region.h)0
-rw-r--r--include/hw/vfio/vfio-amd-xgbe.h46
-rw-r--r--include/hw/vfio/vfio-calxeda-xgmac.h43
-rw-r--r--include/hw/vfio/vfio-container-base.h13
-rw-r--r--include/hw/vfio/vfio-container.h7
-rw-r--r--include/hw/vfio/vfio-device.h2
-rw-r--r--include/hw/vfio/vfio-platform.h78
36 files changed, 329 insertions, 1673 deletions
diff --git a/MAINTAINERS b/MAINTAINERS
index 1ae28e8..fb04538 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -1575,6 +1575,7 @@ F: tests/functional/ppc64/test_tuxrun.py
PowerNV (Non-Virtualized)
M: Nicholas Piggin <npiggin@gmail.com>
R: Aditya Gupta <adityag@linux.ibm.com>
+R: Glenn Miles <milesg@linux.ibm.com>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: docs/system/ppc/powernv.rst
@@ -2781,6 +2782,7 @@ T: git https://github.com/philmd/qemu.git fw_cfg-next
XIVE
R: Gautam Menghani <gautam@linux.ibm.com>
+R: Glenn Miles <milesg@linux.ibm.com>
L: qemu-ppc@nongnu.org
S: Odd Fixes
F: hw/*/*xive*
diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index b242073..2fa2c47 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -488,31 +488,6 @@ Stream ``reconnect`` (since 9.2)
The ``reconnect`` option only allows specifying second granularity timeouts,
which is not enough for all types of use cases, use ``reconnect-ms`` instead.
-VFIO device options
-'''''''''''''''''''
-
-``-device vfio-calxeda-xgmac`` (since 10.0)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The vfio-calxeda-xgmac device allows to assign a host Calxeda Highbank
-10Gb XGMAC Ethernet controller device ("calxeda,hb-xgmac" compatibility
-string) to a guest. Calxeda HW has been ewasted now and there is no point
-keeping that device.
-
-``-device vfio-amd-xgbe`` (since 10.0)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The vfio-amd-xgbe device allows to assign a host AMD 10GbE controller
-to a guest ("amd,xgbe-seattle-v1a" compatibility string). AMD "Seattle"
-is not supported anymore and there is no point keeping that device.
-
-``-device vfio-platform`` (since 10.0)
-^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-The vfio-platform device allows to assign a host platform device
-to a guest in a generic manner. Integrating a new device into
-the vfio-platform infrastructure requires some adaptation at
-both kernel and qemu level. No such attempt has been done for years
-and the conclusion is that vfio-platform has not got any traction.
-PCIe passthrough shall be the mainline solution.
-
CPU device properties
'''''''''''''''''''''
diff --git a/docs/about/removed-features.rst b/docs/about/removed-features.rst
index fff781d..2d3a684 100644
--- a/docs/about/removed-features.rst
+++ b/docs/about/removed-features.rst
@@ -1280,6 +1280,31 @@ The corresponding upstream server project is no longer maintained.
Users are recommended to switch to an alternative distributed block
device driver such as RBD.
+VFIO devices
+------------
+
+``-device vfio-calxeda-xgmac`` (since 10.2)
+'''''''''''''''''''''''''''''''''''''''''''
+The vfio-calxeda-xgmac device allows to assign a host Calxeda Highbank
+10Gb XGMAC Ethernet controller device ("calxeda,hb-xgmac" compatibility
+string) to a guest. Calxeda HW has been ewasted now and there is no point
+keeping that device.
+
+``-device vfio-amd-xgbe`` (since 10.2)
+''''''''''''''''''''''''''''''''''''''
+The vfio-amd-xgbe device allows to assign a host AMD 10GbE controller
+to a guest ("amd,xgbe-seattle-v1a" compatibility string). AMD "Seattle"
+is not supported anymore and there is no point keeping that device.
+
+``-device vfio-platform`` (since 10.2)
+''''''''''''''''''''''''''''''''''''''
+The vfio-platform device allows to assign a host platform device
+to a guest in a generic manner. Integrating a new device into
+the vfio-platform infrastructure requires some adaptation at
+both kernel and qemu level. No such attempt has been done for years
+and the conclusion is that vfio-platform has not got any traction.
+PCIe passthrough shall be the mainline solution.
+
Tools
-----
diff --git a/docs/devel/kconfig.rst b/docs/devel/kconfig.rst
index 493b76c..1d4a114 100644
--- a/docs/devel/kconfig.rst
+++ b/docs/devel/kconfig.rst
@@ -59,8 +59,6 @@ stanza like the following::
config ARM_VIRT
bool
imply PCI_DEVICES
- imply VFIO_AMD_XGBE
- imply VFIO_XGMAC
select A15MPCORE
select ACPI
select ARM_SMMUV3
diff --git a/hw/arm/Kconfig b/hw/arm/Kconfig
index 2aa4b5d..3baa6c6 100644
--- a/hw/arm/Kconfig
+++ b/hw/arm/Kconfig
@@ -5,9 +5,6 @@ config ARM_VIRT
depends on TCG || KVM || HVF
imply PCI_DEVICES
imply TEST_DEVICES
- imply VFIO_AMD_XGBE
- imply VFIO_PLATFORM
- imply VFIO_XGMAC
imply TPM_TIS_SYSBUS
imply TPM_TIS_I2C
imply NVDIMM
diff --git a/hw/arm/virt.c b/hw/arm/virt.c
index e5c4142..6f01746 100644
--- a/hw/arm/virt.c
+++ b/hw/arm/virt.c
@@ -38,8 +38,6 @@
#include "hw/arm/primecell.h"
#include "hw/arm/virt.h"
#include "hw/block/flash.h"
-#include "hw/vfio/vfio-calxeda-xgmac.h"
-#include "hw/vfio/vfio-amd-xgbe.h"
#include "hw/display/ramfb.h"
#include "net/net.h"
#include "system/device_tree.h"
@@ -3218,10 +3216,7 @@ static void virt_machine_class_init(ObjectClass *oc, const void *data)
* configuration of the particular instance.
*/
mc->max_cpus = 512;
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_CALXEDA_XGMAC);
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_AMD_XGBE);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_RAMFB_DEVICE);
- machine_class_allow_dynamic_sysbus_dev(mc, TYPE_VFIO_PLATFORM);
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_UEFI_VARS_SYSBUS);
#ifdef CONFIG_TPM
machine_class_allow_dynamic_sysbus_dev(mc, TYPE_TPM_TIS_SYSBUS);
diff --git a/hw/core/sysbus-fdt.c b/hw/core/sysbus-fdt.c
index c339a27..0711736 100644
--- a/hw/core/sysbus-fdt.c
+++ b/hw/core/sysbus-fdt.c
@@ -32,10 +32,6 @@
#include "system/device_tree.h"
#include "system/tpm.h"
#include "hw/platform-bus.h"
-#include "hw/vfio/vfio-platform.h"
-#include "hw/vfio/vfio-calxeda-xgmac.h"
-#include "hw/vfio/vfio-amd-xgbe.h"
-#include "hw/vfio/vfio-region.h"
#include "hw/display/ramfb.h"
#include "hw/uefi/var-service-api.h"
#include "hw/arm/fdt.h"
@@ -66,380 +62,6 @@ typedef struct HostProperty {
bool optional;
} HostProperty;
-#ifdef CONFIG_LINUX
-
-/**
- * copy_properties_from_host
- *
- * copies properties listed in an array from host device tree to
- * guest device tree. If a non optional property is not found, the
- * function asserts. An optional property is ignored if not found
- * in the host device tree.
- * @props: array of HostProperty to copy
- * @nb_props: number of properties in the array
- * @host_dt: host device tree blob
- * @guest_dt: guest device tree blob
- * @node_path: host dt node path where the property is supposed to be
- found
- * @nodename: guest node name the properties should be added to
- */
-static void copy_properties_from_host(HostProperty *props, int nb_props,
- void *host_fdt, void *guest_fdt,
- char *node_path, char *nodename)
-{
- int i, prop_len;
- const void *r;
- Error *err = NULL;
-
- for (i = 0; i < nb_props; i++) {
- r = qemu_fdt_getprop(host_fdt, node_path,
- props[i].name,
- &prop_len,
- &err);
- if (r) {
- qemu_fdt_setprop(guest_fdt, nodename,
- props[i].name, r, prop_len);
- } else {
- if (props[i].optional && prop_len == -FDT_ERR_NOTFOUND) {
- /* optional property does not exist */
- error_free(err);
- } else {
- error_report_err(err);
- }
- if (!props[i].optional) {
- /* mandatory property not found: bail out */
- exit(1);
- }
- err = NULL;
- }
- }
-}
-
-/* clock properties whose values are copied/pasted from host */
-static HostProperty clock_copied_properties[] = {
- {"compatible", false},
- {"#clock-cells", false},
- {"clock-frequency", true},
- {"clock-output-names", true},
-};
-
-/**
- * fdt_build_clock_node
- *
- * Build a guest clock node, used as a dependency from a passthrough'ed
- * device. Most information are retrieved from the host clock node.
- * Also check the host clock is a fixed one.
- *
- * @host_fdt: host device tree blob from which info are retrieved
- * @guest_fdt: guest device tree blob where the clock node is added
- * @host_phandle: phandle of the clock in host device tree
- * @guest_phandle: phandle to assign to the guest node
- */
-static void fdt_build_clock_node(void *host_fdt, void *guest_fdt,
- uint32_t host_phandle,
- uint32_t guest_phandle)
-{
- char *node_path = NULL;
- char *nodename;
- const void *r;
- int ret, node_offset, prop_len, path_len = 16;
-
- node_offset = fdt_node_offset_by_phandle(host_fdt, host_phandle);
- if (node_offset <= 0) {
- error_report("not able to locate clock handle %d in host device tree",
- host_phandle);
- exit(1);
- }
- node_path = g_malloc(path_len);
- while ((ret = fdt_get_path(host_fdt, node_offset, node_path, path_len))
- == -FDT_ERR_NOSPACE) {
- path_len += 16;
- node_path = g_realloc(node_path, path_len);
- }
- if (ret < 0) {
- error_report("not able to retrieve node path for clock handle %d",
- host_phandle);
- exit(1);
- }
-
- r = qemu_fdt_getprop(host_fdt, node_path, "compatible", &prop_len,
- &error_fatal);
- if (strcmp(r, "fixed-clock")) {
- error_report("clock handle %d is not a fixed clock", host_phandle);
- exit(1);
- }
-
- nodename = strrchr(node_path, '/');
- qemu_fdt_add_subnode(guest_fdt, nodename);
-
- copy_properties_from_host(clock_copied_properties,
- ARRAY_SIZE(clock_copied_properties),
- host_fdt, guest_fdt,
- node_path, nodename);
-
- qemu_fdt_setprop_cell(guest_fdt, nodename, "phandle", guest_phandle);
-
- g_free(node_path);
-}
-
-/**
- * sysfs_to_dt_name: convert the name found in sysfs into the node name
- * for instance e0900000.xgmac is converted into xgmac@e0900000
- * @sysfs_name: directory name in sysfs
- *
- * returns the device tree name upon success or NULL in case the sysfs name
- * does not match the expected format
- */
-static char *sysfs_to_dt_name(const char *sysfs_name)
-{
- gchar **substrings = g_strsplit(sysfs_name, ".", 2);
- char *dt_name = NULL;
-
- if (!substrings || !substrings[0] || !substrings[1]) {
- goto out;
- }
- dt_name = g_strdup_printf("%s@%s", substrings[1], substrings[0]);
-out:
- g_strfreev(substrings);
- return dt_name;
-}
-
-/* Device Specific Code */
-
-/**
- * add_calxeda_midway_xgmac_fdt_node
- *
- * Generates a simple node with following properties:
- * compatible string, regs, interrupts, dma-coherent
- */
-static int add_calxeda_midway_xgmac_fdt_node(SysBusDevice *sbdev, void *opaque)
-{
- PlatformBusFDTData *data = opaque;
- PlatformBusDevice *pbus = data->pbus;
- void *fdt = data->fdt;
- const char *parent_node = data->pbus_node_name;
- int compat_str_len, i;
- char *nodename;
- uint32_t *irq_attr, *reg_attr;
- uint64_t mmio_base, irq_number;
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
- VFIODevice *vbasedev = &vdev->vbasedev;
-
- mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
- nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
- vbasedev->name, mmio_base);
- qemu_fdt_add_subnode(fdt, nodename);
-
- compat_str_len = strlen(vdev->compat) + 1;
- qemu_fdt_setprop(fdt, nodename, "compatible",
- vdev->compat, compat_str_len);
-
- qemu_fdt_setprop(fdt, nodename, "dma-coherent", "", 0);
-
- reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
- for (i = 0; i < vbasedev->num_regions; i++) {
- mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
- reg_attr[2 * i] = cpu_to_be32(mmio_base);
- reg_attr[2 * i + 1] = cpu_to_be32(
- memory_region_size(vdev->regions[i]->mem));
- }
- qemu_fdt_setprop(fdt, nodename, "reg", reg_attr,
- vbasedev->num_regions * 2 * sizeof(uint32_t));
-
- irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
- for (i = 0; i < vbasedev->num_irqs; i++) {
- irq_number = platform_bus_get_irqn(pbus, sbdev , i)
- + data->irq_start;
- irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
- irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
- irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
- }
- qemu_fdt_setprop(fdt, nodename, "interrupts",
- irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
- g_free(irq_attr);
- g_free(reg_attr);
- g_free(nodename);
- return 0;
-}
-
-/* AMD xgbe properties whose values are copied/pasted from host */
-static HostProperty amd_xgbe_copied_properties[] = {
- {"compatible", false},
- {"dma-coherent", true},
- {"amd,per-channel-interrupt", true},
- {"phy-mode", false},
- {"mac-address", true},
- {"amd,speed-set", false},
- {"amd,serdes-blwc", true},
- {"amd,serdes-cdr-rate", true},
- {"amd,serdes-pq-skew", true},
- {"amd,serdes-tx-amp", true},
- {"amd,serdes-dfe-tap-config", true},
- {"amd,serdes-dfe-tap-enable", true},
- {"clock-names", false},
-};
-
-/**
- * add_amd_xgbe_fdt_node
- *
- * Generates the combined xgbe/phy node following kernel >=4.2
- * binding documentation:
- * Documentation/devicetree/bindings/net/amd-xgbe.txt:
- * Also 2 clock nodes are created (dma and ptp)
- *
- * Asserts in case of error
- */
-static int add_amd_xgbe_fdt_node(SysBusDevice *sbdev, void *opaque)
-{
- PlatformBusFDTData *data = opaque;
- PlatformBusDevice *pbus = data->pbus;
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
- VFIODevice *vbasedev = &vdev->vbasedev;
- VFIOINTp *intp;
- const char *parent_node = data->pbus_node_name;
- char **node_path, *nodename, *dt_name;
- void *guest_fdt = data->fdt, *host_fdt;
- const void *r;
- int i, prop_len;
- uint32_t *irq_attr, *reg_attr;
- const uint32_t *host_clock_phandles;
- uint64_t mmio_base, irq_number;
- uint32_t guest_clock_phandles[2];
-
- host_fdt = load_device_tree_from_sysfs();
-
- dt_name = sysfs_to_dt_name(vbasedev->name);
- if (!dt_name) {
- error_report("%s incorrect sysfs device name %s",
- __func__, vbasedev->name);
- exit(1);
- }
- node_path = qemu_fdt_node_path(host_fdt, dt_name, vdev->compat,
- &error_fatal);
- if (!node_path || !node_path[0]) {
- error_report("%s unable to retrieve node path for %s/%s",
- __func__, dt_name, vdev->compat);
- exit(1);
- }
-
- if (node_path[1]) {
- error_report("%s more than one node matching %s/%s!",
- __func__, dt_name, vdev->compat);
- exit(1);
- }
-
- g_free(dt_name);
-
- if (vbasedev->num_regions != 5) {
- error_report("%s Does the host dt node combine XGBE/PHY?", __func__);
- exit(1);
- }
-
- /* generate nodes for DMA_CLK and PTP_CLK */
- r = qemu_fdt_getprop(host_fdt, node_path[0], "clocks",
- &prop_len, &error_fatal);
- if (prop_len != 8) {
- error_report("%s clocks property should contain 2 handles", __func__);
- exit(1);
- }
- host_clock_phandles = r;
- guest_clock_phandles[0] = qemu_fdt_alloc_phandle(guest_fdt);
- guest_clock_phandles[1] = qemu_fdt_alloc_phandle(guest_fdt);
-
- /**
- * clock handles fetched from host dt are in be32 layout whereas
- * rest of the code uses cpu layout. Also guest clock handles are
- * in cpu layout.
- */
- fdt_build_clock_node(host_fdt, guest_fdt,
- be32_to_cpu(host_clock_phandles[0]),
- guest_clock_phandles[0]);
-
- fdt_build_clock_node(host_fdt, guest_fdt,
- be32_to_cpu(host_clock_phandles[1]),
- guest_clock_phandles[1]);
-
- /* combined XGBE/PHY node */
- mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, 0);
- nodename = g_strdup_printf("%s/%s@%" PRIx64, parent_node,
- vbasedev->name, mmio_base);
- qemu_fdt_add_subnode(guest_fdt, nodename);
-
- copy_properties_from_host(amd_xgbe_copied_properties,
- ARRAY_SIZE(amd_xgbe_copied_properties),
- host_fdt, guest_fdt,
- node_path[0], nodename);
-
- qemu_fdt_setprop_cells(guest_fdt, nodename, "clocks",
- guest_clock_phandles[0],
- guest_clock_phandles[1]);
-
- reg_attr = g_new(uint32_t, vbasedev->num_regions * 2);
- for (i = 0; i < vbasedev->num_regions; i++) {
- mmio_base = platform_bus_get_mmio_addr(pbus, sbdev, i);
- reg_attr[2 * i] = cpu_to_be32(mmio_base);
- reg_attr[2 * i + 1] = cpu_to_be32(
- memory_region_size(vdev->regions[i]->mem));
- }
- qemu_fdt_setprop(guest_fdt, nodename, "reg", reg_attr,
- vbasedev->num_regions * 2 * sizeof(uint32_t));
-
- irq_attr = g_new(uint32_t, vbasedev->num_irqs * 3);
- for (i = 0; i < vbasedev->num_irqs; i++) {
- irq_number = platform_bus_get_irqn(pbus, sbdev , i)
- + data->irq_start;
- irq_attr[3 * i] = cpu_to_be32(GIC_FDT_IRQ_TYPE_SPI);
- irq_attr[3 * i + 1] = cpu_to_be32(irq_number);
- /*
- * General device interrupt and PCS auto-negotiation interrupts are
- * level-sensitive while the 4 per-channel interrupts are edge
- * sensitive
- */
- QLIST_FOREACH(intp, &vdev->intp_list, next) {
- if (intp->pin == i) {
- break;
- }
- }
- if (intp->flags & VFIO_IRQ_INFO_AUTOMASKED) {
- irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_LEVEL_HI);
- } else {
- irq_attr[3 * i + 2] = cpu_to_be32(GIC_FDT_IRQ_FLAGS_EDGE_LO_HI);
- }
- }
- qemu_fdt_setprop(guest_fdt, nodename, "interrupts",
- irq_attr, vbasedev->num_irqs * 3 * sizeof(uint32_t));
-
- g_free(host_fdt);
- g_strfreev(node_path);
- g_free(irq_attr);
- g_free(reg_attr);
- g_free(nodename);
- return 0;
-}
-
-/* DT compatible matching */
-static bool vfio_platform_match(SysBusDevice *sbdev,
- const BindingEntry *entry)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
- const char *compat;
- unsigned int n;
-
- for (n = vdev->num_compat, compat = vdev->compat; n > 0;
- n--, compat += strlen(compat) + 1) {
- if (!strcmp(entry->compat, compat)) {
- return true;
- }
- }
-
- return false;
-}
-
-#define VFIO_PLATFORM_BINDING(compat, add_fn) \
- {TYPE_VFIO_PLATFORM, (compat), (add_fn), vfio_platform_match}
-
-#endif /* CONFIG_LINUX */
-
#ifdef CONFIG_TPM
/*
* add_tpm_tis_fdt_node: Create a DT node for TPM TIS
@@ -510,11 +132,6 @@ static bool type_match(SysBusDevice *sbdev, const BindingEntry *entry)
/* list of supported dynamic sysbus bindings */
static const BindingEntry bindings[] = {
-#ifdef CONFIG_LINUX
- TYPE_BINDING(TYPE_VFIO_CALXEDA_XGMAC, add_calxeda_midway_xgmac_fdt_node),
- TYPE_BINDING(TYPE_VFIO_AMD_XGBE, add_amd_xgbe_fdt_node),
- VFIO_PLATFORM_BINDING("amd,xgbe-seattle-v1a", add_amd_xgbe_fdt_node),
-#endif
#ifdef CONFIG_TPM
TYPE_BINDING(TYPE_TPM_TIS_SYSBUS, add_tpm_tis_fdt_node),
#endif
diff --git a/hw/ppc/spapr_pci_vfio.c b/hw/ppc/spapr_pci_vfio.c
index e318d0d..7e1c71e 100644
--- a/hw/ppc/spapr_pci_vfio.c
+++ b/hw/ppc/spapr_pci_vfio.c
@@ -106,7 +106,7 @@ static VFIOContainer *vfio_eeh_as_container(AddressSpace *as)
out:
vfio_address_space_put(space);
- return container_of(bcontainer, VFIOContainer, bcontainer);
+ return VFIO_IOMMU_LEGACY(bcontainer);
}
static bool vfio_eeh_as_ok(AddressSpace *as)
diff --git a/hw/s390x/s390-pci-vfio.c b/hw/s390x/s390-pci-vfio.c
index aaf9131..938a551 100644
--- a/hw/s390x/s390-pci-vfio.c
+++ b/hw/s390x/s390-pci-vfio.c
@@ -62,7 +62,7 @@ S390PCIDMACount *s390_pci_start_dma_count(S390pciState *s,
{
S390PCIDMACount *cnt;
uint32_t avail;
- VFIOPCIDevice *vpdev = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpdev = VFIO_PCI_BASE(pbdev->pdev);
int id;
assert(vpdev);
@@ -108,7 +108,7 @@ static void s390_pci_read_base(S390PCIBusDevice *pbdev,
{
struct vfio_info_cap_header *hdr;
struct vfio_device_info_cap_zpci_base *cap;
- VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpci = VFIO_PCI_BASE(pbdev->pdev);
uint64_t vfio_size;
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
@@ -162,7 +162,7 @@ static bool get_host_fh(S390PCIBusDevice *pbdev, struct vfio_device_info *info,
{
struct vfio_info_cap_header *hdr;
struct vfio_device_info_cap_zpci_base *cap;
- VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpci = VFIO_PCI_BASE(pbdev->pdev);
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_BASE);
@@ -185,7 +185,7 @@ static void s390_pci_read_group(S390PCIBusDevice *pbdev,
struct vfio_device_info_cap_zpci_group *cap;
S390pciState *s = s390_get_phb();
ClpRspQueryPciGrp *resgrp;
- VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpci = VFIO_PCI_BASE(pbdev->pdev);
uint8_t start_gid = pbdev->zpci_fn.pfgid;
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_GROUP);
@@ -264,7 +264,7 @@ static void s390_pci_read_util(S390PCIBusDevice *pbdev,
{
struct vfio_info_cap_header *hdr;
struct vfio_device_info_cap_zpci_util *cap;
- VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpci = VFIO_PCI_BASE(pbdev->pdev);
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_UTIL);
@@ -291,7 +291,7 @@ static void s390_pci_read_pfip(S390PCIBusDevice *pbdev,
{
struct vfio_info_cap_header *hdr;
struct vfio_device_info_cap_zpci_pfip *cap;
- VFIOPCIDevice *vpci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vpci = VFIO_PCI_BASE(pbdev->pdev);
hdr = vfio_get_device_info_cap(info, VFIO_DEVICE_INFO_CAP_ZPCI_PFIP);
@@ -314,7 +314,7 @@ static void s390_pci_read_pfip(S390PCIBusDevice *pbdev,
static struct vfio_device_info *get_device_info(S390PCIBusDevice *pbdev)
{
- VFIOPCIDevice *vfio_pci = container_of(pbdev->pdev, VFIOPCIDevice, pdev);
+ VFIOPCIDevice *vfio_pci = VFIO_PCI_BASE(pbdev->pdev);
return vfio_get_device_info(vfio_pci->vbasedev.fd);
}
diff --git a/hw/vfio-user/container.c b/hw/vfio-user/container.c
index d589dd9..3cdbd44 100644
--- a/hw/vfio-user/container.c
+++ b/hw/vfio-user/container.c
@@ -24,16 +24,14 @@
*/
static void vfio_user_listener_begin(VFIOContainerBase *bcontainer)
{
- VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer,
- bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(bcontainer);
container->proxy->async_ops = true;
}
static void vfio_user_listener_commit(VFIOContainerBase *bcontainer)
{
- VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer,
- bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(bcontainer);
/* wait here for any async requests sent during the transaction */
container->proxy->async_ops = false;
@@ -44,8 +42,8 @@ static int vfio_user_dma_unmap(const VFIOContainerBase *bcontainer,
hwaddr iova, ram_addr_t size,
IOMMUTLBEntry *iotlb, bool unmap_all)
{
- VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer,
- bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(bcontainer);
+
Error *local_err = NULL;
int ret = 0;
@@ -86,8 +84,8 @@ static int vfio_user_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova,
ram_addr_t size, void *vaddr, bool readonly,
MemoryRegion *mrp)
{
- VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer,
- bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(bcontainer);
+
int fd = memory_region_get_fd(mrp);
Error *local_err = NULL;
int ret = 0;
@@ -173,8 +171,7 @@ static int vfio_user_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
static bool vfio_user_setup(VFIOContainerBase *bcontainer, Error **errp)
{
- VFIOUserContainer *container = container_of(bcontainer, VFIOUserContainer,
- bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(bcontainer);
assert(container->proxy->dma_pgsizes != 0);
bcontainer->pgsizes = container->proxy->dma_pgsizes;
@@ -218,7 +215,7 @@ vfio_user_container_connect(AddressSpace *as, VFIODevice *vbasedev,
goto put_space_exit;
}
- bcontainer = &container->bcontainer;
+ bcontainer = VFIO_IOMMU(container);
ret = ram_block_uncoordinated_discard_disable(true);
if (ret) {
@@ -263,7 +260,7 @@ put_space_exit:
static void vfio_user_container_disconnect(VFIOUserContainer *container)
{
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
VFIOAddressSpace *space = bcontainer->space;
@@ -291,7 +288,7 @@ static bool vfio_user_device_get(VFIOUserContainer *container,
vbasedev->fd = -1;
- vfio_device_prepare(vbasedev, &container->bcontainer, &info);
+ vfio_device_prepare(vbasedev, VFIO_IOMMU(container), &info);
return true;
}
@@ -315,8 +312,7 @@ static bool vfio_user_device_attach(const char *name, VFIODevice *vbasedev,
static void vfio_user_device_detach(VFIODevice *vbasedev)
{
- VFIOUserContainer *container = container_of(vbasedev->bcontainer,
- VFIOUserContainer, bcontainer);
+ VFIOUserContainer *container = VFIO_IOMMU_USER(vbasedev->bcontainer);
vfio_device_unprepare(vbasedev);
diff --git a/hw/vfio-user/container.h b/hw/vfio-user/container.h
index 2bb1fa1..96aa678 100644
--- a/hw/vfio-user/container.h
+++ b/hw/vfio-user/container.h
@@ -13,10 +13,11 @@
#include "hw/vfio-user/proxy.h"
/* MMU container sub-class for vfio-user. */
-typedef struct VFIOUserContainer {
- VFIOContainerBase bcontainer;
+struct VFIOUserContainer {
+ VFIOContainerBase parent_obj;
+
VFIOUserProxy *proxy;
-} VFIOUserContainer;
+};
OBJECT_DECLARE_SIMPLE_TYPE(VFIOUserContainer, VFIO_IOMMU_USER);
diff --git a/hw/vfio-user/pci.c b/hw/vfio-user/pci.c
index be71c77..e2c3097 100644
--- a/hw/vfio-user/pci.c
+++ b/hw/vfio-user/pci.c
@@ -20,7 +20,8 @@
OBJECT_DECLARE_SIMPLE_TYPE(VFIOUserPCIDevice, VFIO_USER_PCI)
struct VFIOUserPCIDevice {
- VFIOPCIDevice device;
+ VFIOPCIDevice parent_obj;
+
SocketAddress *socket;
bool send_queued; /* all sends are queued */
uint32_t wait_time; /* timeout for message replies */
@@ -64,7 +65,7 @@ static void vfio_user_msix_setup(VFIOPCIDevice *vdev)
vdev->msix->pba_region = pba_reg;
vfio_reg = vdev->bars[vdev->msix->pba_bar].mr;
- msix_reg = &vdev->pdev.msix_pba_mmio;
+ msix_reg = &PCI_DEVICE(vdev)->msix_pba_mmio;
memory_region_init_io(pba_reg, OBJECT(vdev), &vfio_user_pba_ops, vdev,
"VFIO MSIX PBA", int128_get64(msix_reg->size));
memory_region_add_subregion_overlap(vfio_reg, vdev->msix->pba_offset,
@@ -85,7 +86,7 @@ static void vfio_user_msix_teardown(VFIOPCIDevice *vdev)
static void vfio_user_dma_read(VFIOPCIDevice *vdev, VFIOUserDMARW *msg)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIOUserProxy *proxy = vdev->vbasedev.proxy;
VFIOUserDMARW *res;
MemTxResult r;
@@ -133,7 +134,7 @@ static void vfio_user_dma_read(VFIOPCIDevice *vdev, VFIOUserDMARW *msg)
static void vfio_user_dma_write(VFIOPCIDevice *vdev, VFIOUserDMARW *msg)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIOUserProxy *proxy = vdev->vbasedev.proxy;
MemTxResult r;
@@ -213,8 +214,9 @@ static void vfio_user_compute_needs_reset(VFIODevice *vbasedev)
static Object *vfio_user_pci_get_object(VFIODevice *vbasedev)
{
- VFIOUserPCIDevice *vdev = container_of(vbasedev, VFIOUserPCIDevice,
- device.vbasedev);
+ VFIOUserPCIDevice *vdev = VFIO_USER_PCI(container_of(vbasedev,
+ VFIOPCIDevice,
+ vbasedev));
return OBJECT(vdev);
}
@@ -406,6 +408,8 @@ static const Property vfio_user_pci_dev_properties[] = {
sub_vendor_id, PCI_ANY_ID),
DEFINE_PROP_UINT32("x-pci-sub-device-id", VFIOPCIDevice,
sub_device_id, PCI_ANY_ID),
+ DEFINE_PROP_UINT32("x-pci-class-code", VFIOPCIDevice,
+ class_code, PCI_ANY_ID),
DEFINE_PROP_BOOL("x-send-queued", VFIOUserPCIDevice, send_queued, false),
DEFINE_PROP_UINT32("x-msg-timeout", VFIOUserPCIDevice, wait_time, 5000),
DEFINE_PROP_BOOL("x-no-posted-writes", VFIOUserPCIDevice, no_post, false),
@@ -417,7 +421,7 @@ static void vfio_user_pci_set_socket(Object *obj, Visitor *v, const char *name,
VFIOUserPCIDevice *udev = VFIO_USER_PCI(obj);
bool success;
- if (udev->device.vbasedev.proxy) {
+ if (VFIO_PCI_BASE(udev)->vbasedev.proxy) {
error_setg(errp, "Proxy is connected");
return;
}
diff --git a/hw/vfio/Kconfig b/hw/vfio/Kconfig
index 91d9023..27de24e 100644
--- a/hw/vfio/Kconfig
+++ b/hw/vfio/Kconfig
@@ -17,22 +17,6 @@ config VFIO_CCW
select VFIO
depends on LINUX && S390_CCW_VIRTIO
-config VFIO_PLATFORM
- bool
- default y
- select VFIO
- depends on LINUX && PLATFORM_BUS
-
-config VFIO_XGMAC
- bool
- default y
- depends on VFIO_PLATFORM
-
-config VFIO_AMD_XGBE
- bool
- default y
- depends on VFIO_PLATFORM
-
config VFIO_AP
bool
default y
diff --git a/hw/vfio/amd-xgbe.c b/hw/vfio/amd-xgbe.c
deleted file mode 100644
index 58f590e..0000000
--- a/hw/vfio/amd-xgbe.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * AMD XGBE VFIO device
- *
- * Copyright Linaro Limited, 2015
- *
- * Authors:
- * Eric Auger <eric.auger@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/vfio/vfio-amd-xgbe.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
-#include "qemu/error-report.h"
-
-static void amd_xgbe_realize(DeviceState *dev, Error **errp)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
- VFIOAmdXgbeDeviceClass *k = VFIO_AMD_XGBE_DEVICE_GET_CLASS(dev);
-
- warn_report("-device vfio-amd-xgbe is deprecated");
- vdev->compat = g_strdup("amd,xgbe-seattle-v1a");
- vdev->num_compat = 1;
-
- k->parent_realize(dev, errp);
-}
-
-static const VMStateDescription vfio_platform_amd_xgbe_vmstate = {
- .name = "vfio-amd-xgbe",
- .unmigratable = 1,
-};
-
-static void vfio_amd_xgbe_class_init(ObjectClass *klass, const void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- VFIOAmdXgbeDeviceClass *vcxc =
- VFIO_AMD_XGBE_DEVICE_CLASS(klass);
- device_class_set_parent_realize(dc, amd_xgbe_realize,
- &vcxc->parent_realize);
- dc->desc = "VFIO AMD XGBE";
- dc->vmsd = &vfio_platform_amd_xgbe_vmstate;
-}
-
-static const TypeInfo vfio_amd_xgbe_dev_info = {
- .name = TYPE_VFIO_AMD_XGBE,
- .parent = TYPE_VFIO_PLATFORM,
- .instance_size = sizeof(VFIOAmdXgbeDevice),
- .class_init = vfio_amd_xgbe_class_init,
- .class_size = sizeof(VFIOAmdXgbeDeviceClass),
-};
-
-static void register_amd_xgbe_dev_type(void)
-{
- type_register_static(&vfio_amd_xgbe_dev_info);
-}
-
-type_init(register_amd_xgbe_dev_type)
diff --git a/hw/vfio/calxeda-xgmac.c b/hw/vfio/calxeda-xgmac.c
deleted file mode 100644
index 03f2ff5..0000000
--- a/hw/vfio/calxeda-xgmac.c
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * calxeda xgmac VFIO device
- *
- * Copyright Linaro Limited, 2014
- *
- * Authors:
- * Eric Auger <eric.auger@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#include "qemu/osdep.h"
-#include "hw/vfio/vfio-calxeda-xgmac.h"
-#include "migration/vmstate.h"
-#include "qemu/module.h"
-#include "qemu/error-report.h"
-
-static void calxeda_xgmac_realize(DeviceState *dev, Error **errp)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
- VFIOCalxedaXgmacDeviceClass *k = VFIO_CALXEDA_XGMAC_DEVICE_GET_CLASS(dev);
-
- warn_report("-device vfio-calxeda-xgmac is deprecated");
- vdev->compat = g_strdup("calxeda,hb-xgmac");
- vdev->num_compat = 1;
-
- k->parent_realize(dev, errp);
-}
-
-static const VMStateDescription vfio_platform_calxeda_xgmac_vmstate = {
- .name = "vfio-calxeda-xgmac",
- .unmigratable = 1,
-};
-
-static void vfio_calxeda_xgmac_class_init(ObjectClass *klass, const void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- VFIOCalxedaXgmacDeviceClass *vcxc =
- VFIO_CALXEDA_XGMAC_DEVICE_CLASS(klass);
- device_class_set_parent_realize(dc, calxeda_xgmac_realize,
- &vcxc->parent_realize);
- dc->desc = "VFIO Calxeda XGMAC";
- dc->vmsd = &vfio_platform_calxeda_xgmac_vmstate;
-}
-
-static const TypeInfo vfio_calxeda_xgmac_dev_info = {
- .name = TYPE_VFIO_CALXEDA_XGMAC,
- .parent = TYPE_VFIO_PLATFORM,
- .instance_size = sizeof(VFIOCalxedaXgmacDevice),
- .class_init = vfio_calxeda_xgmac_class_init,
- .class_size = sizeof(VFIOCalxedaXgmacDeviceClass),
-};
-
-static void register_calxeda_xgmac_dev_type(void)
-{
- type_register_static(&vfio_calxeda_xgmac_dev_info);
-}
-
-type_init(register_calxeda_xgmac_dev_type)
diff --git a/hw/vfio/container.c b/hw/vfio/container.c
index 3e13fea..030c6d3 100644
--- a/hw/vfio/container.c
+++ b/hw/vfio/container.c
@@ -71,7 +71,7 @@ static int vfio_dma_unmap_bitmap(const VFIOContainer *container,
hwaddr iova, ram_addr_t size,
IOMMUTLBEntry *iotlb)
{
- const VFIOContainerBase *bcontainer = &container->bcontainer;
+ const VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
struct vfio_iommu_type1_dma_unmap *unmap;
struct vfio_bitmap *bitmap;
VFIOBitmap vbmap;
@@ -124,8 +124,7 @@ static int vfio_legacy_dma_unmap_one(const VFIOContainerBase *bcontainer,
hwaddr iova, ram_addr_t size,
IOMMUTLBEntry *iotlb)
{
- const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ const VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
struct vfio_iommu_type1_dma_unmap unmap = {
.argsz = sizeof(unmap),
.flags = 0,
@@ -213,8 +212,7 @@ static int vfio_legacy_dma_map(const VFIOContainerBase *bcontainer, hwaddr iova,
ram_addr_t size, void *vaddr, bool readonly,
MemoryRegion *mr)
{
- const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ const VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
struct vfio_iommu_type1_dma_map map = {
.argsz = sizeof(map),
.flags = VFIO_DMA_MAP_FLAG_READ,
@@ -246,8 +244,7 @@ static int
vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer,
bool start, Error **errp)
{
- const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ const VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
int ret;
struct vfio_iommu_type1_dirty_bitmap dirty = {
.argsz = sizeof(dirty),
@@ -272,8 +269,7 @@ vfio_legacy_set_dirty_page_tracking(const VFIOContainerBase *bcontainer,
static int vfio_legacy_query_dirty_bitmap(const VFIOContainerBase *bcontainer,
VFIOBitmap *vbmap, hwaddr iova, hwaddr size, Error **errp)
{
- const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ const VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
struct vfio_iommu_type1_dirty_bitmap *dbitmap;
struct vfio_iommu_type1_dirty_bitmap_get *range;
int ret;
@@ -495,7 +491,7 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container,
{
struct vfio_info_cap_header *hdr;
struct vfio_iommu_type1_info_cap_migration *cap_mig;
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
hdr = vfio_get_iommu_info_cap(info, VFIO_IOMMU_TYPE1_INFO_CAP_MIGRATION);
if (!hdr) {
@@ -518,8 +514,7 @@ static void vfio_get_iommu_info_migration(VFIOContainer *container,
static bool vfio_legacy_setup(VFIOContainerBase *bcontainer, Error **errp)
{
- VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
g_autofree struct vfio_iommu_type1_info *info = NULL;
int ret;
@@ -634,7 +629,7 @@ static bool vfio_container_connect(VFIOGroup *group, AddressSpace *as,
if (!cpr_is_incoming()) {
QLIST_FOREACH(bcontainer, &space->containers, next) {
- container = container_of(bcontainer, VFIOContainer, bcontainer);
+ container = VFIO_IOMMU_LEGACY(bcontainer);
if (!ioctl(group->fd, VFIO_GROUP_SET_CONTAINER, &container->fd)) {
return vfio_container_group_add(container, group, errp);
}
@@ -652,7 +647,7 @@ static bool vfio_container_connect(VFIOGroup *group, AddressSpace *as,
* create the container struct and group list.
*/
QLIST_FOREACH(bcontainer, &space->containers, next) {
- container = container_of(bcontainer, VFIOContainer, bcontainer);
+ container = VFIO_IOMMU_LEGACY(bcontainer);
if (vfio_cpr_container_match(container, group, fd)) {
return vfio_container_group_add(container, group, errp);
@@ -672,7 +667,7 @@ static bool vfio_container_connect(VFIOGroup *group, AddressSpace *as,
goto fail;
}
new_container = true;
- bcontainer = &container->bcontainer;
+ bcontainer = VFIO_IOMMU(container);
if (!vfio_legacy_cpr_register_container(container, errp)) {
goto fail;
@@ -735,7 +730,7 @@ fail:
static void vfio_container_disconnect(VFIOGroup *group)
{
VFIOContainer *container = group->container;
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
QLIST_REMOVE(group, container_next);
@@ -781,7 +776,7 @@ static VFIOGroup *vfio_group_get(int groupid, AddressSpace *as, Error **errp)
QLIST_FOREACH(group, &vfio_group_list, next) {
if (group->groupid == groupid) {
/* Found it. Now is it already in the right context? */
- if (group->container->bcontainer.space->as == as) {
+ if (VFIO_IOMMU(group->container)->space->as == as) {
return group;
} else {
error_setg(errp, "group %d used in multiple address spaces",
@@ -895,7 +890,7 @@ static bool vfio_device_get(VFIOGroup *group, const char *name,
}
}
- vfio_device_prepare(vbasedev, &group->container->bcontainer, info);
+ vfio_device_prepare(vbasedev, VFIO_IOMMU(group->container), info);
vbasedev->fd = fd;
vbasedev->group = group;
@@ -1087,7 +1082,7 @@ static int vfio_legacy_pci_hot_reset(VFIODevice *vbasedev, bool single)
/* Prep dependent devices for reset and clear our marker. */
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
if (!vbasedev_iter->dev->realized ||
- vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ !vfio_pci_from_vfio_device(vbasedev_iter)) {
continue;
}
tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
@@ -1172,7 +1167,7 @@ out:
QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
if (!vbasedev_iter->dev->realized ||
- vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ !vfio_pci_from_vfio_device(vbasedev_iter)) {
continue;
}
tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
diff --git a/hw/vfio/cpr-legacy.c b/hw/vfio/cpr-legacy.c
index 553b203..8f43719 100644
--- a/hw/vfio/cpr-legacy.c
+++ b/hw/vfio/cpr-legacy.c
@@ -41,8 +41,8 @@ static int vfio_legacy_cpr_dma_map(const VFIOContainerBase *bcontainer,
hwaddr iova, ram_addr_t size, void *vaddr,
bool readonly, MemoryRegion *mr)
{
- const VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ const VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
+
struct vfio_iommu_type1_dma_map map = {
.argsz = sizeof(map),
.flags = VFIO_DMA_MAP_FLAG_VADDR,
@@ -65,7 +65,7 @@ static void vfio_region_remap(MemoryListener *listener,
{
VFIOContainer *container = container_of(listener, VFIOContainer,
cpr.remap_listener);
- vfio_container_region_add(&container->bcontainer, section, true);
+ vfio_container_region_add(VFIO_IOMMU(container), section, true);
}
static bool vfio_cpr_supported(VFIOContainer *container, Error **errp)
@@ -98,7 +98,7 @@ static int vfio_container_pre_save(void *opaque)
static int vfio_container_post_load(void *opaque, int version_id)
{
VFIOContainer *container = opaque;
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
VFIOIOMMUClass *vioc = VFIO_IOMMU_GET_CLASS(bcontainer);
dma_map_fn saved_dma_map = vioc->dma_map;
Error *local_err = NULL;
@@ -135,7 +135,7 @@ static int vfio_cpr_fail_notifier(NotifierWithReturn *notifier,
{
VFIOContainer *container =
container_of(notifier, VFIOContainer, cpr.transfer_notifier);
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
if (e->type != MIG_EVENT_PRECOPY_FAILED) {
return 0;
@@ -167,7 +167,7 @@ static int vfio_cpr_fail_notifier(NotifierWithReturn *notifier,
bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp)
{
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
Error **cpr_blocker = &container->cpr.blocker;
migration_add_notifier_mode(&bcontainer->cpr_reboot_notifier,
@@ -191,7 +191,7 @@ bool vfio_legacy_cpr_register_container(VFIOContainer *container, Error **errp)
void vfio_legacy_cpr_unregister_container(VFIOContainer *container)
{
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
migration_remove_notifier(&bcontainer->cpr_reboot_notifier);
migrate_del_blocker(&container->cpr.blocker);
diff --git a/hw/vfio/cpr.c b/hw/vfio/cpr.c
index a831243..2c71fc1 100644
--- a/hw/vfio/cpr.c
+++ b/hw/vfio/cpr.c
@@ -56,7 +56,7 @@ static void vfio_cpr_claim_vectors(VFIOPCIDevice *vdev, int nr_vectors,
{
int i, fd;
bool pending = false;
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
vdev->nr_vectors = nr_vectors;
vdev->msi_vectors = g_new0(VFIOMSIVector, nr_vectors);
@@ -99,7 +99,7 @@ static void vfio_cpr_claim_vectors(VFIOPCIDevice *vdev, int nr_vectors,
static int vfio_cpr_pci_pre_load(void *opaque)
{
VFIOPCIDevice *vdev = opaque;
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int size = MIN(pci_config_size(pdev), vdev->config_size);
int i;
@@ -113,7 +113,7 @@ static int vfio_cpr_pci_pre_load(void *opaque)
static int vfio_cpr_pci_post_load(void *opaque, int version_id)
{
VFIOPCIDevice *vdev = opaque;
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int nr_vectors;
vfio_sub_page_bar_update_mappings(vdev);
@@ -173,8 +173,8 @@ const VMStateDescription vfio_cpr_pci_vmstate = {
.post_load = vfio_cpr_pci_post_load,
.needed = cpr_incoming_needed,
.fields = (VMStateField[]) {
- VMSTATE_PCI_DEVICE(pdev, VFIOPCIDevice),
- VMSTATE_MSIX_TEST(pdev, VFIOPCIDevice, pci_msix_present),
+ VMSTATE_PCI_DEVICE(parent_obj, VFIOPCIDevice),
+ VMSTATE_MSIX_TEST(parent_obj, VFIOPCIDevice, pci_msix_present),
VMSTATE_VFIO_INTX(intx, VFIOPCIDevice),
VMSTATE_END_OF_LIST()
}
@@ -214,7 +214,7 @@ static int set_irqfd_notifier_gsi(KVMState *s, EventNotifier *n,
static int vfio_cpr_set_msi_virq(VFIOPCIDevice *vdev, Error **errp, bool enable)
{
const char *op = (enable ? "enable" : "disable");
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int i, nr_vectors, ret = 0;
if (msix_enabled(pdev)) {
diff --git a/hw/vfio/device.c b/hw/vfio/device.c
index 52a1996..08f12ac 100644
--- a/hw/vfio/device.c
+++ b/hw/vfio/device.c
@@ -129,7 +129,7 @@ static inline const char *action_to_str(int action)
static const char *index_to_str(VFIODevice *vbasedev, int index)
{
- if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) {
+ if (!vfio_pci_from_vfio_device(vbasedev)) {
return NULL;
}
diff --git a/hw/vfio/igd.c b/hw/vfio/igd.c
index ee0767b..4bfa2e0 100644
--- a/hw/vfio/igd.c
+++ b/hw/vfio/igd.c
@@ -200,7 +200,7 @@ static bool vfio_pci_igd_opregion_detect(VFIOPCIDevice *vdev,
}
/* Hotplugging is not supported for opregion access */
- if (vdev->pdev.qdev.hotplugged) {
+ if (DEVICE(vdev)->hotplugged) {
warn_report("IGD device detected, but OpRegion is not supported "
"on hotplugged device.");
return false;
@@ -260,11 +260,12 @@ static int vfio_pci_igd_copy(VFIOPCIDevice *vdev, PCIDevice *pdev,
static int vfio_pci_igd_host_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
PCIBus *bus;
PCIDevice *host_bridge;
int ret;
- bus = pci_device_root_bus(&vdev->pdev);
+ bus = pci_device_root_bus(pdev);
host_bridge = pci_find_device(bus, 0, PCI_DEVFN(0, 0));
if (!host_bridge) {
@@ -327,13 +328,14 @@ type_init(vfio_pci_igd_register_types)
static int vfio_pci_igd_lpc_init(VFIOPCIDevice *vdev,
struct vfio_region_info *info)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
PCIDevice *lpc_bridge;
int ret;
- lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
+ lpc_bridge = pci_find_device(pci_device_root_bus(pdev),
0, PCI_DEVFN(0x1f, 0));
if (!lpc_bridge) {
- lpc_bridge = pci_create_simple(pci_device_root_bus(&vdev->pdev),
+ lpc_bridge = pci_create_simple(pci_device_root_bus(pdev),
PCI_DEVFN(0x1f, 0), "vfio-pci-igd-lpc-bridge");
}
@@ -350,13 +352,14 @@ static bool vfio_pci_igd_setup_lpc_bridge(VFIOPCIDevice *vdev, Error **errp)
{
struct vfio_region_info *host = NULL;
struct vfio_region_info *lpc = NULL;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
PCIDevice *lpc_bridge;
int ret;
/*
* Copying IDs or creating new devices are not supported on hotplug
*/
- if (vdev->pdev.qdev.hotplugged) {
+ if (DEVICE(vdev)->hotplugged) {
error_setg(errp, "IGD LPC is not supported on hotplugged device");
return false;
}
@@ -366,7 +369,7 @@ static bool vfio_pci_igd_setup_lpc_bridge(VFIOPCIDevice *vdev, Error **errp)
* can stuff host values into, so if there's already one there and it's not
* one we can hack on, this quirk is no-go. Sorry Q35.
*/
- lpc_bridge = pci_find_device(pci_device_root_bus(&vdev->pdev),
+ lpc_bridge = pci_find_device(pci_device_root_bus(pdev),
0, PCI_DEVFN(0x1f, 0));
if (lpc_bridge && !object_dynamic_cast(OBJECT(lpc_bridge),
"vfio-pci-igd-lpc-bridge")) {
@@ -460,7 +463,7 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
int gen;
if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
- !vfio_is_vga(vdev) || nr != 0) {
+ !vfio_is_base_display(vdev) || nr != 0) {
return;
}
@@ -510,6 +513,7 @@ void vfio_probe_igd_bar0_quirk(VFIOPCIDevice *vdev, int nr)
static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
{
struct vfio_region_info *opregion = NULL;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int ret, gen;
uint64_t gms_size = 0;
uint64_t *bdsm_size;
@@ -518,7 +522,7 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
Error *err = NULL;
if (!vfio_pci_is(vdev, PCI_VENDOR_ID_INTEL, PCI_ANY_ID) ||
- !vfio_is_vga(vdev)) {
+ !vfio_is_base_display(vdev)) {
return true;
}
@@ -529,21 +533,22 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
info_report("OpRegion detected on Intel display %x.", vdev->device_id);
gen = igd_gen(vdev);
- gmch = vfio_pci_read_config(&vdev->pdev, IGD_GMCH, 4);
+ gmch = vfio_pci_read_config(pdev, IGD_GMCH, 4);
/*
* For backward compatibility, enable legacy mode when
* - Device geneation is 6 to 9 (including both)
- * - IGD claims VGA cycles on host
+ * - IGD exposes itself as VGA controller and claims VGA cycles on host
* - Machine type is i440fx (pc_piix)
* - IGD device is at guest BDF 00:02.0
* - Not manually disabled by x-igd-legacy-mode=off
*/
if ((vdev->igd_legacy_mode != ON_OFF_AUTO_OFF) &&
+ vfio_is_vga(vdev) &&
(gen >= 6 && gen <= 9) &&
!(gmch & IGD_GMCH_VGA_DISABLE) &&
!strcmp(MACHINE_GET_CLASS(qdev_get_machine())->family, "pc_piix") &&
- (&vdev->pdev == pci_find_device(pci_device_root_bus(&vdev->pdev),
+ (pdev == pci_find_device(pci_device_root_bus(pdev),
0, PCI_DEVFN(0x2, 0)))) {
/*
* IGD legacy mode requires:
@@ -565,7 +570,7 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
*/
ret = vfio_device_get_region_info(&vdev->vbasedev,
VFIO_PCI_ROM_REGION_INDEX, &rom);
- if ((ret || !rom->size) && !vdev->pdev.romfile) {
+ if ((ret || !rom->size) && !pdev->romfile) {
error_setg(&err, "Device has no ROM");
goto error;
}
@@ -610,8 +615,8 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
* ASLS (OpRegion address) is read-only, emulated
* It contains HPA, guest firmware need to reprogram it with GPA.
*/
- pci_set_long(vdev->pdev.config + IGD_ASLS, 0);
- pci_set_long(vdev->pdev.wmask + IGD_ASLS, ~0);
+ pci_set_long(pdev->config + IGD_ASLS, 0);
+ pci_set_long(pdev->wmask + IGD_ASLS, ~0);
pci_set_long(vdev->emulated_config_bits + IGD_ASLS, ~0);
/*
@@ -625,8 +630,8 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
}
/* GMCH is read-only, emulated */
- pci_set_long(vdev->pdev.config + IGD_GMCH, gmch);
- pci_set_long(vdev->pdev.wmask + IGD_GMCH, 0);
+ pci_set_long(pdev->config + IGD_GMCH, gmch);
+ pci_set_long(pdev->wmask + IGD_GMCH, 0);
pci_set_long(vdev->emulated_config_bits + IGD_GMCH, ~0);
}
@@ -635,12 +640,12 @@ static bool vfio_pci_igd_config_quirk(VFIOPCIDevice *vdev, Error **errp)
/* BDSM is read-write, emulated. BIOS needs to be able to write it */
if (gen < 11) {
- pci_set_long(vdev->pdev.config + IGD_BDSM, 0);
- pci_set_long(vdev->pdev.wmask + IGD_BDSM, ~0);
+ pci_set_long(pdev->config + IGD_BDSM, 0);
+ pci_set_long(pdev->wmask + IGD_BDSM, ~0);
pci_set_long(vdev->emulated_config_bits + IGD_BDSM, ~0);
} else {
- pci_set_quad(vdev->pdev.config + IGD_BDSM_GEN11, 0);
- pci_set_quad(vdev->pdev.wmask + IGD_BDSM_GEN11, ~0);
+ pci_set_quad(pdev->config + IGD_BDSM_GEN11, 0);
+ pci_set_quad(pdev->wmask + IGD_BDSM_GEN11, ~0);
pci_set_quad(vdev->emulated_config_bits + IGD_BDSM_GEN11, ~0);
}
}
diff --git a/hw/vfio/iommufd.c b/hw/vfio/iommufd.c
index 48c590b..8c27222 100644
--- a/hw/vfio/iommufd.c
+++ b/hw/vfio/iommufd.c
@@ -737,8 +737,8 @@ iommufd_cdev_dep_get_realized_vpdev(struct vfio_pci_dependent_device *dep_dev,
}
vbasedev_tmp = iommufd_cdev_pci_find_by_devid(dep_dev->devid);
- if (!vbasedev_tmp || !vbasedev_tmp->dev->realized ||
- vbasedev_tmp->type != VFIO_DEVICE_TYPE_PCI) {
+ if (!vfio_pci_from_vfio_device(vbasedev_tmp) ||
+ !vbasedev_tmp->dev->realized) {
return NULL;
}
diff --git a/hw/vfio/listener.c b/hw/vfio/listener.c
index f498e23..e093833 100644
--- a/hw/vfio/listener.c
+++ b/hw/vfio/listener.c
@@ -250,8 +250,9 @@ static int vfio_ram_discard_notify_populate(RamDiscardListener *rdl,
return 0;
}
-static void vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer,
- MemoryRegionSection *section)
+static bool vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer,
+ MemoryRegionSection *section,
+ Error **errp)
{
RamDiscardManager *rdm = memory_region_get_ram_discard_manager(section->mr);
int target_page_size = qemu_target_page_size();
@@ -316,13 +317,15 @@ static void vfio_ram_discard_register_listener(VFIOContainerBase *bcontainer,
if (vrdl_mappings + max_memslots - vrdl_count >
bcontainer->dma_max_mappings) {
- warn_report("%s: possibly running out of DMA mappings. E.g., try"
+ error_setg(errp, "%s: possibly running out of DMA mappings. E.g., try"
" increasing the 'block-size' of virtio-mem devies."
" Maximum possible DMA mappings: %d, Maximum possible"
" memslots: %d", __func__, bcontainer->dma_max_mappings,
max_memslots);
+ return false;
}
}
+ return true;
}
static void vfio_ram_discard_unregister_listener(VFIOContainerBase *bcontainer,
@@ -450,7 +453,7 @@ static void vfio_device_error_append(VFIODevice *vbasedev, Error **errp)
* MMIO region mapping failures are not fatal but in this case PCI
* peer-to-peer transactions are broken.
*/
- if (vbasedev && vbasedev->type == VFIO_DEVICE_TYPE_PCI) {
+ if (vfio_pci_from_vfio_device(vbasedev)) {
error_append_hint(errp, "%s: PCI peer-to-peer transactions "
"on BARs are not supported.\n", vbasedev->name);
}
@@ -571,9 +574,14 @@ void vfio_container_region_add(VFIOContainerBase *bcontainer,
*/
if (memory_region_has_ram_discard_manager(section->mr)) {
if (!cpr_remap) {
- vfio_ram_discard_register_listener(bcontainer, section);
+ if (!vfio_ram_discard_register_listener(bcontainer, section, &err)) {
+ goto fail;
+ }
} else if (!vfio_cpr_ram_discard_register_listener(bcontainer,
section)) {
+ error_setg(&err,
+ "vfio_cpr_ram_discard_register_listener for %s failed",
+ memory_region_name(section->mr));
goto fail;
}
return;
@@ -751,7 +759,7 @@ static bool vfio_section_is_vfio_pci(MemoryRegionSection *section,
owner = memory_region_owner(section->mr);
QLIST_FOREACH(vbasedev, &bcontainer->device_list, container_next) {
- if (vbasedev->type != VFIO_DEVICE_TYPE_PCI) {
+ if (!vfio_pci_from_vfio_device(vbasedev)) {
continue;
}
pcidev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
diff --git a/hw/vfio/meson.build b/hw/vfio/meson.build
index bfaf6be..d3ed3cb 100644
--- a/hw/vfio/meson.build
+++ b/hw/vfio/meson.build
@@ -13,14 +13,11 @@ vfio_ss.add(when: 'CONFIG_VFIO_PCI', if_true: files(
'pci.c',
))
vfio_ss.add(when: 'CONFIG_VFIO_CCW', if_true: files('ccw.c'))
-vfio_ss.add(when: 'CONFIG_VFIO_PLATFORM', if_true: files('platform.c'))
vfio_ss.add(when: 'CONFIG_VFIO_AP', if_true: files('ap.c'))
vfio_ss.add(when: 'CONFIG_VFIO_IGD', if_true: files('igd.c'))
specific_ss.add_all(when: 'CONFIG_VFIO', if_true: vfio_ss)
-system_ss.add(when: 'CONFIG_VFIO_XGMAC', if_true: files('calxeda-xgmac.c'))
-system_ss.add(when: 'CONFIG_VFIO_AMD_XGBE', if_true: files('amd-xgbe.c'))
system_ss.add(when: 'CONFIG_VFIO', if_true: files(
'cpr.c',
'cpr-legacy.c',
diff --git a/hw/vfio/pci-quirks.c b/hw/vfio/pci-quirks.c
index 3f00225..c97606d 100644
--- a/hw/vfio/pci-quirks.c
+++ b/hw/vfio/pci-quirks.c
@@ -113,6 +113,7 @@ static uint64_t vfio_generic_window_quirk_data_read(void *opaque,
{
VFIOConfigWindowQuirk *window = opaque;
VFIOPCIDevice *vdev = window->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint64_t data;
/* Always read data reg, discard if window enabled */
@@ -120,7 +121,7 @@ static uint64_t vfio_generic_window_quirk_data_read(void *opaque,
addr + window->data_offset, size);
if (window->window_enabled) {
- data = vfio_pci_read_config(&vdev->pdev, window->address_val, size);
+ data = vfio_pci_read_config(pdev, window->address_val, size);
trace_vfio_quirk_generic_window_data_read(vdev->vbasedev.name,
memory_region_name(window->data_mem), data);
}
@@ -133,9 +134,10 @@ static void vfio_generic_window_quirk_data_write(void *opaque, hwaddr addr,
{
VFIOConfigWindowQuirk *window = opaque;
VFIOPCIDevice *vdev = window->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
if (window->window_enabled) {
- vfio_pci_write_config(&vdev->pdev, window->address_val, data, size);
+ vfio_pci_write_config(pdev, window->address_val, data, size);
trace_vfio_quirk_generic_window_data_write(vdev->vbasedev.name,
memory_region_name(window->data_mem), data);
return;
@@ -156,6 +158,7 @@ static uint64_t vfio_generic_quirk_mirror_read(void *opaque,
{
VFIOConfigMirrorQuirk *mirror = opaque;
VFIOPCIDevice *vdev = mirror->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint64_t data;
/* Read and discard in case the hardware cares */
@@ -163,7 +166,7 @@ static uint64_t vfio_generic_quirk_mirror_read(void *opaque,
addr + mirror->offset, size);
addr += mirror->config_offset;
- data = vfio_pci_read_config(&vdev->pdev, addr, size);
+ data = vfio_pci_read_config(pdev, addr, size);
trace_vfio_quirk_generic_mirror_read(vdev->vbasedev.name,
memory_region_name(mirror->mem),
addr, data);
@@ -175,9 +178,10 @@ static void vfio_generic_quirk_mirror_write(void *opaque, hwaddr addr,
{
VFIOConfigMirrorQuirk *mirror = opaque;
VFIOPCIDevice *vdev = mirror->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
addr += mirror->config_offset;
- vfio_pci_write_config(&vdev->pdev, addr, data, size);
+ vfio_pci_write_config(pdev, addr, data, size);
trace_vfio_quirk_generic_mirror_write(vdev->vbasedev.name,
memory_region_name(mirror->mem),
addr, data);
@@ -211,7 +215,8 @@ static uint64_t vfio_ati_3c3_quirk_read(void *opaque,
hwaddr addr, unsigned size)
{
VFIOPCIDevice *vdev = opaque;
- uint64_t data = vfio_pci_read_config(&vdev->pdev,
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ uint64_t data = vfio_pci_read_config(pdev,
PCI_BASE_ADDRESS_4 + 1, size);
trace_vfio_quirk_ati_3c3_read(vdev->vbasedev.name, data);
@@ -563,6 +568,7 @@ static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
{
VFIONvidia3d0Quirk *quirk = opaque;
VFIOPCIDevice *vdev = quirk->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIONvidia3d0State old_state = quirk->state;
uint64_t data = vfio_vga_read(&vdev->vga->region[QEMU_PCI_VGA_IO_HI],
addr + 0x10, size);
@@ -573,7 +579,7 @@ static uint64_t vfio_nvidia_3d0_quirk_read(void *opaque,
(quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) {
uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1);
- data = vfio_pci_read_config(&vdev->pdev, offset, size);
+ data = vfio_pci_read_config(pdev, offset, size);
trace_vfio_quirk_nvidia_3d0_read(vdev->vbasedev.name,
offset, size, data);
}
@@ -586,6 +592,7 @@ static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr,
{
VFIONvidia3d0Quirk *quirk = opaque;
VFIOPCIDevice *vdev = quirk->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIONvidia3d0State old_state = quirk->state;
quirk->state = NONE;
@@ -599,7 +606,7 @@ static void vfio_nvidia_3d0_quirk_write(void *opaque, hwaddr addr,
if ((quirk->offset & ~(PCI_CONFIG_SPACE_SIZE - 1)) == 0x1800) {
uint8_t offset = quirk->offset & (PCI_CONFIG_SPACE_SIZE - 1);
- vfio_pci_write_config(&vdev->pdev, offset, data, size);
+ vfio_pci_write_config(pdev, offset, data, size);
trace_vfio_quirk_nvidia_3d0_write(vdev->vbasedev.name,
offset, data, size);
return;
@@ -815,7 +822,7 @@ static void vfio_nvidia_quirk_mirror_write(void *opaque, hwaddr addr,
{
VFIOConfigMirrorQuirk *mirror = opaque;
VFIOPCIDevice *vdev = mirror->vdev;
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
LastDataSet *last = (LastDataSet *)&mirror->data;
vfio_generic_quirk_mirror_write(opaque, addr, data, size);
@@ -1005,6 +1012,7 @@ static void vfio_rtl8168_quirk_address_write(void *opaque, hwaddr addr,
{
VFIOrtl8168Quirk *rtl = opaque;
VFIOPCIDevice *vdev = rtl->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
rtl->enabled = false;
@@ -1013,7 +1021,7 @@ static void vfio_rtl8168_quirk_address_write(void *opaque, hwaddr addr,
rtl->addr = (uint32_t)data;
if (data & 0x80000000U) { /* Do write */
- if (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX) {
+ if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
hwaddr offset = data & 0xfff;
uint64_t val = rtl->data;
@@ -1021,7 +1029,7 @@ static void vfio_rtl8168_quirk_address_write(void *opaque, hwaddr addr,
(uint16_t)offset, val);
/* Write to the proper guest MSI-X table instead */
- memory_region_dispatch_write(&vdev->pdev.msix_table_mmio,
+ memory_region_dispatch_write(&pdev->msix_table_mmio,
offset, val,
size_memop(size) | MO_LE,
MEMTXATTRS_UNSPECIFIED);
@@ -1049,11 +1057,12 @@ static uint64_t vfio_rtl8168_quirk_data_read(void *opaque,
{
VFIOrtl8168Quirk *rtl = opaque;
VFIOPCIDevice *vdev = rtl->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint64_t data = vfio_region_read(&vdev->bars[2].region, addr + 0x70, size);
- if (rtl->enabled && (vdev->pdev.cap_present & QEMU_PCI_CAP_MSIX)) {
+ if (rtl->enabled && (pdev->cap_present & QEMU_PCI_CAP_MSIX)) {
hwaddr offset = rtl->addr & 0xfff;
- memory_region_dispatch_read(&vdev->pdev.msix_table_mmio, offset,
+ memory_region_dispatch_read(&pdev->msix_table_mmio, offset,
&data, size_memop(size) | MO_LE,
MEMTXATTRS_UNSPECIFIED);
trace_vfio_quirk_rtl8168_msix_read(vdev->vbasedev.name, offset, data);
@@ -1297,7 +1306,7 @@ static void vfio_radeon_set_gfx_only_reset(VFIOPCIDevice *vdev)
static int vfio_radeon_reset(VFIOPCIDevice *vdev)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int i, ret = 0;
uint32_t data;
@@ -1454,7 +1463,7 @@ static bool is_valid_std_cap_offset(uint8_t pos)
static bool vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
{
ERRP_GUARD();
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int ret, pos;
bool c8_conflict = false, d4_conflict = false;
uint8_t tmp;
@@ -1547,6 +1556,7 @@ static bool vfio_add_nv_gpudirect_cap(VFIOPCIDevice *vdev, Error **errp)
static bool vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
{
ERRP_GUARD();
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint8_t membar_phys[16];
int ret, pos = 0xE8;
@@ -1565,7 +1575,7 @@ static bool vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
return false;
}
- ret = pci_add_capability(&vdev->pdev, PCI_CAP_ID_VNDR, pos,
+ ret = pci_add_capability(pdev, PCI_CAP_ID_VNDR, pos,
VMD_SHADOW_CAP_LEN, errp);
if (ret < 0) {
error_prepend(errp, "Failed to add VMD MEMBAR Shadow cap: ");
@@ -1574,10 +1584,10 @@ static bool vfio_add_vmd_shadow_cap(VFIOPCIDevice *vdev, Error **errp)
memset(vdev->emulated_config_bits + pos, 0xFF, VMD_SHADOW_CAP_LEN);
pos += PCI_CAP_FLAGS;
- pci_set_byte(vdev->pdev.config + pos++, VMD_SHADOW_CAP_LEN);
- pci_set_byte(vdev->pdev.config + pos++, VMD_SHADOW_CAP_VER);
- pci_set_long(vdev->pdev.config + pos, 0x53484457); /* SHDW */
- memcpy(vdev->pdev.config + pos + 4, membar_phys, 16);
+ pci_set_byte(pdev->config + pos++, VMD_SHADOW_CAP_LEN);
+ pci_set_byte(pdev->config + pos++, VMD_SHADOW_CAP_VER);
+ pci_set_long(pdev->config + pos, 0x53484457); /* SHDW */
+ memcpy(pdev->config + pos + 4, membar_phys, 16);
return true;
}
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index 07257d0..d14e96b 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -117,6 +117,7 @@ static void vfio_intx_mmap_enable(void *opaque)
static void vfio_intx_interrupt(void *opaque)
{
VFIOPCIDevice *vdev = opaque;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
if (!event_notifier_test_and_clear(&vdev->intx.interrupt)) {
return;
@@ -125,7 +126,7 @@ static void vfio_intx_interrupt(void *opaque)
trace_vfio_intx_interrupt(vdev->vbasedev.name, 'A' + vdev->intx.pin);
vdev->intx.pending = true;
- pci_irq_assert(&vdev->pdev);
+ pci_irq_assert(pdev);
vfio_mmap_set_enabled(vdev, false);
if (vdev->intx.mmap_timeout) {
timer_mod(vdev->intx.mmap_timer,
@@ -136,6 +137,7 @@ static void vfio_intx_interrupt(void *opaque)
void vfio_pci_intx_eoi(VFIODevice *vbasedev)
{
VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
if (!vdev->intx.pending) {
return;
@@ -144,13 +146,14 @@ void vfio_pci_intx_eoi(VFIODevice *vbasedev)
trace_vfio_pci_intx_eoi(vbasedev->name);
vdev->intx.pending = false;
- pci_irq_deassert(&vdev->pdev);
+ pci_irq_deassert(pdev);
vfio_device_irq_unmask(vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
}
static bool vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
{
#ifdef CONFIG_KVM
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int irq_fd = event_notifier_get_fd(&vdev->intx.interrupt);
if (vdev->no_kvm_intx || !kvm_irqfds_enabled() ||
@@ -163,7 +166,7 @@ static bool vfio_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
qemu_set_fd_handler(irq_fd, NULL, NULL, vdev);
vfio_device_irq_mask(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
- pci_irq_deassert(&vdev->pdev);
+ pci_irq_deassert(pdev);
/* Get an eventfd for resample/unmask */
if (!vfio_notifier_init(vdev, &vdev->intx.unmask, "intx-unmask", 0, errp)) {
@@ -241,6 +244,8 @@ static bool vfio_cpr_intx_enable_kvm(VFIOPCIDevice *vdev, Error **errp)
static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev)
{
#ifdef CONFIG_KVM
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
if (!vdev->intx.kvm_accel) {
return;
}
@@ -251,7 +256,7 @@ static void vfio_intx_disable_kvm(VFIOPCIDevice *vdev)
*/
vfio_device_irq_mask(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
- pci_irq_deassert(&vdev->pdev);
+ pci_irq_deassert(pdev);
/* Tell KVM to stop listening for an INTx irqfd */
if (kvm_irqchip_remove_irqfd_notifier_gsi(kvm_state, &vdev->intx.interrupt,
@@ -307,7 +312,7 @@ static void vfio_intx_routing_notifier(PCIDevice *pdev)
return;
}
- route = pci_device_route_intx_to_irq(&vdev->pdev, vdev->intx.pin);
+ route = pci_device_route_intx_to_irq(pdev, vdev->intx.pin);
if (pci_intx_route_changed(&vdev->intx.route, &route)) {
vfio_intx_update(vdev, &route);
@@ -324,7 +329,8 @@ static void vfio_irqchip_change(Notifier *notify, void *data)
static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp)
{
- uint8_t pin = vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ uint8_t pin = vfio_pci_read_config(pdev, PCI_INTERRUPT_PIN, 1);
Error *err = NULL;
int32_t fd;
@@ -342,7 +348,7 @@ static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp)
}
vdev->intx.pin = pin - 1; /* Pin A (1) -> irq[0] */
- pci_config_set_interrupt_pin(vdev->pdev.config, pin);
+ pci_config_set_interrupt_pin(pdev->config, pin);
#ifdef CONFIG_KVM
/*
@@ -350,7 +356,7 @@ static bool vfio_intx_enable(VFIOPCIDevice *vdev, Error **errp)
* where we won't actually use the result anyway.
*/
if (kvm_irqfds_enabled() && kvm_resamplefds_enabled()) {
- vdev->intx.route = pci_device_route_intx_to_irq(&vdev->pdev,
+ vdev->intx.route = pci_device_route_intx_to_irq(pdev,
vdev->intx.pin);
}
#endif
@@ -390,13 +396,14 @@ skip_signaling:
static void vfio_intx_disable(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int fd;
timer_del(vdev->intx.mmap_timer);
vfio_intx_disable_kvm(vdev);
vfio_device_irq_disable(&vdev->vbasedev, VFIO_PCI_INTX_IRQ_INDEX);
vdev->intx.pending = false;
- pci_irq_deassert(&vdev->pdev);
+ pci_irq_deassert(pdev);
vfio_mmap_set_enabled(vdev, true);
fd = event_notifier_get_fd(&vdev->intx.interrupt);
@@ -428,6 +435,7 @@ static void vfio_msi_interrupt(void *opaque)
{
VFIOMSIVector *vector = opaque;
VFIOPCIDevice *vdev = vector->vdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
MSIMessage (*get_msg)(PCIDevice *dev, unsigned vector);
void (*notify)(PCIDevice *dev, unsigned vector);
MSIMessage msg;
@@ -442,9 +450,9 @@ static void vfio_msi_interrupt(void *opaque)
notify = msix_notify;
/* A masked vector firing needs to use the PBA, enable it */
- if (msix_is_masked(&vdev->pdev, nr)) {
+ if (msix_is_masked(pdev, nr)) {
set_bit(nr, vdev->msix->pending);
- memory_region_set_enabled(&vdev->pdev.msix_pba_mmio, true);
+ memory_region_set_enabled(&pdev->msix_pba_mmio, true);
trace_vfio_msix_pba_enable(vdev->vbasedev.name);
}
} else if (vdev->interrupt == VFIO_INT_MSI) {
@@ -454,9 +462,9 @@ static void vfio_msi_interrupt(void *opaque)
abort();
}
- msg = get_msg(&vdev->pdev, nr);
+ msg = get_msg(pdev, nr);
trace_vfio_msi_interrupt(vdev->vbasedev.name, nr, msg.address, msg.data);
- notify(&vdev->pdev, nr);
+ notify(pdev, nr);
}
void vfio_pci_msi_set_handler(VFIOPCIDevice *vdev, int nr, bool enable)
@@ -495,6 +503,7 @@ static int vfio_enable_msix_no_vec(VFIOPCIDevice *vdev)
static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
struct vfio_irq_set *irq_set;
int ret = 0, i, argsz;
int32_t *fds;
@@ -537,7 +546,7 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
*/
if (vdev->msi_vectors[i].use) {
if (vdev->msi_vectors[i].virq < 0 ||
- (msix && msix_is_masked(&vdev->pdev, i))) {
+ (msix && msix_is_masked(pdev, i))) {
fd = event_notifier_get_fd(&vdev->msi_vectors[i].interrupt);
} else {
fd = event_notifier_get_fd(&vdev->msi_vectors[i].kvm_interrupt);
@@ -557,12 +566,14 @@ static int vfio_enable_vectors(VFIOPCIDevice *vdev, bool msix)
void vfio_pci_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
int vector_n, bool msix)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
if ((msix && vdev->no_kvm_msix) || (!msix && vdev->no_kvm_msi)) {
return;
}
vector->virq = kvm_irqchip_add_msi_route(&vfio_route_change,
- vector_n, &vdev->pdev);
+ vector_n, pdev);
}
static void vfio_connect_kvm_msi_virq(VFIOMSIVector *vector, int nr)
@@ -631,7 +642,7 @@ static void set_irq_signalling(VFIODevice *vbasedev, VFIOMSIVector *vector,
void vfio_pci_vector_init(VFIOPCIDevice *vdev, int nr)
{
VFIOMSIVector *vector = &vdev->msi_vectors[nr];
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
Error *local_err = NULL;
vector->vdev = vdev;
@@ -720,7 +731,7 @@ static int vfio_msix_vector_do_use(PCIDevice *pdev, unsigned int nr,
clear_bit(nr, vdev->msix->pending);
if (find_first_bit(vdev->msix->pending,
vdev->nr_vectors) == vdev->nr_vectors) {
- memory_region_set_enabled(&vdev->pdev.msix_pba_mmio, false);
+ memory_region_set_enabled(&pdev->msix_pba_mmio, false);
trace_vfio_msix_pba_disable(vdev->vbasedev.name);
}
@@ -771,7 +782,9 @@ static void vfio_msix_vector_release(PCIDevice *pdev, unsigned int nr)
void vfio_pci_msix_set_notifiers(VFIOPCIDevice *vdev)
{
- msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use,
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
+ msix_set_vector_notifiers(pdev, vfio_msix_vector_use,
vfio_msix_vector_release, NULL);
}
@@ -798,6 +811,7 @@ void vfio_pci_commit_kvm_msi_virq_batch(VFIOPCIDevice *vdev)
static void vfio_msix_enable(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int ret;
vfio_disable_interrupts(vdev);
@@ -814,7 +828,7 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
*/
vfio_pci_prepare_kvm_msi_virq_batch(vdev);
- if (msix_set_vector_notifiers(&vdev->pdev, vfio_msix_vector_use,
+ if (msix_set_vector_notifiers(pdev, vfio_msix_vector_use,
vfio_msix_vector_release, NULL)) {
error_report("vfio: msix_set_vector_notifiers failed");
}
@@ -852,11 +866,12 @@ static void vfio_msix_enable(VFIOPCIDevice *vdev)
static void vfio_msi_enable(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int ret, i;
vfio_disable_interrupts(vdev);
- vdev->nr_vectors = msi_nr_vectors_allocated(&vdev->pdev);
+ vdev->nr_vectors = msi_nr_vectors_allocated(pdev);
retry:
/*
* Setting vector notifiers needs to enable route for each vector.
@@ -949,10 +964,11 @@ static void vfio_msi_disable_common(VFIOPCIDevice *vdev)
static void vfio_msix_disable(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
Error *err = NULL;
int i;
- msix_unset_vector_notifiers(&vdev->pdev);
+ msix_unset_vector_notifiers(pdev);
/*
* MSI-X will only release vectors if MSI-X is still enabled on the
@@ -960,8 +976,8 @@ static void vfio_msix_disable(VFIOPCIDevice *vdev)
*/
for (i = 0; i < vdev->nr_vectors; i++) {
if (vdev->msi_vectors[i].use) {
- vfio_msix_vector_release(&vdev->pdev, i);
- msix_vector_unuse(&vdev->pdev, i);
+ vfio_msix_vector_release(pdev, i);
+ msix_vector_unuse(pdev, i);
}
}
@@ -998,6 +1014,7 @@ static void vfio_msi_disable(VFIOPCIDevice *vdev)
static void vfio_update_msi(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int i;
for (i = 0; i < vdev->nr_vectors; i++) {
@@ -1008,8 +1025,8 @@ static void vfio_update_msi(VFIOPCIDevice *vdev)
continue;
}
- msg = msi_get_message(&vdev->pdev, i);
- vfio_update_kvm_msi_virq(vector, msg, &vdev->pdev);
+ msg = msi_get_message(pdev, i);
+ vfio_update_kvm_msi_virq(vector, msg, pdev);
}
}
@@ -1171,13 +1188,14 @@ static const MemoryRegionOps vfio_rom_ops = {
static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIODevice *vbasedev = &vdev->vbasedev;
uint32_t orig, size = cpu_to_le32((uint32_t)PCI_ROM_ADDRESS_MASK);
char *name;
- if (vdev->pdev.romfile || !vdev->pdev.rom_bar) {
+ if (pdev->romfile || !pdev->rom_bar) {
/* Since pci handles romfile, just print a message and return */
- if (vfio_opt_rom_in_denylist(vdev) && vdev->pdev.romfile) {
+ if (vfio_opt_rom_in_denylist(vdev) && pdev->romfile) {
warn_report("Device at %s is known to cause system instability"
" issues during option rom execution",
vdev->vbasedev.name);
@@ -1206,7 +1224,7 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
}
if (vfio_opt_rom_in_denylist(vdev)) {
- if (vdev->pdev.rom_bar > 0) {
+ if (pdev->rom_bar > 0) {
warn_report("Device at %s is known to cause system instability"
" issues during option rom execution",
vdev->vbasedev.name);
@@ -1225,12 +1243,12 @@ static void vfio_pci_size_rom(VFIOPCIDevice *vdev)
name = g_strdup_printf("vfio[%s].rom", vdev->vbasedev.name);
- memory_region_init_io(&vdev->pdev.rom, OBJECT(vdev),
+ memory_region_init_io(&pdev->rom, OBJECT(vdev),
&vfio_rom_ops, vdev, name, size);
g_free(name);
- pci_register_bar(&vdev->pdev, PCI_ROM_SLOT,
- PCI_BASE_ADDRESS_SPACE_MEMORY, &vdev->pdev.rom);
+ pci_register_bar(pdev, PCI_ROM_SLOT,
+ PCI_BASE_ADDRESS_SPACE_MEMORY, &pdev->rom);
vdev->rom_read_failed = false;
}
@@ -1503,6 +1521,7 @@ static void vfio_disable_interrupts(VFIOPCIDevice *vdev)
static bool vfio_msi_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint16_t ctrl;
bool msi_64bit, msi_maskbit;
int ret, entries;
@@ -1523,7 +1542,7 @@ static bool vfio_msi_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
trace_vfio_msi_setup(vdev->vbasedev.name, pos);
- ret = msi_init(&vdev->pdev, pos, entries, msi_64bit, msi_maskbit, &err);
+ ret = msi_init(pdev, pos, entries, msi_64bit, msi_maskbit, &err);
if (ret < 0) {
if (ret == -ENOTSUP) {
return true;
@@ -1716,6 +1735,7 @@ static bool vfio_pci_relocate_msix(VFIOPCIDevice *vdev, Error **errp)
*/
static bool vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint8_t pos;
uint16_t ctrl;
uint32_t table, pba;
@@ -1723,7 +1743,7 @@ static bool vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
VFIOMSIXInfo *msix;
int ret;
- pos = pci_find_capability(&vdev->pdev, PCI_CAP_ID_MSIX);
+ pos = pci_find_capability(pdev, PCI_CAP_ID_MSIX);
if (!pos) {
return true;
}
@@ -1815,12 +1835,13 @@ static bool vfio_msix_early_setup(VFIOPCIDevice *vdev, Error **errp)
static bool vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int ret;
Error *err = NULL;
vdev->msix->pending = g_new0(unsigned long,
BITS_TO_LONGS(vdev->msix->entries));
- ret = msix_init(&vdev->pdev, vdev->msix->entries,
+ ret = msix_init(pdev, vdev->msix->entries,
vdev->bars[vdev->msix->table_bar].mr,
vdev->msix->table_bar, vdev->msix->table_offset,
vdev->bars[vdev->msix->pba_bar].mr,
@@ -1852,7 +1873,7 @@ static bool vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
* vector-use notifier is called, which occurs on unmask, we test whether
* PBA emulation is needed and again disable if not.
*/
- memory_region_set_enabled(&vdev->pdev.msix_pba_mmio, false);
+ memory_region_set_enabled(&pdev->msix_pba_mmio, false);
/*
* The emulated machine may provide a paravirt interface for MSIX setup
@@ -1864,7 +1885,7 @@ static bool vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
*/
if (object_property_get_bool(OBJECT(qdev_get_machine()),
"vfio-no-msix-emulation", NULL)) {
- memory_region_set_enabled(&vdev->pdev.msix_table_mmio, false);
+ memory_region_set_enabled(&pdev->msix_table_mmio, false);
}
return true;
@@ -1872,10 +1893,12 @@ static bool vfio_msix_setup(VFIOPCIDevice *vdev, int pos, Error **errp)
void vfio_pci_teardown_msi(VFIOPCIDevice *vdev)
{
- msi_uninit(&vdev->pdev);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
+ msi_uninit(pdev);
if (vdev->msix) {
- msix_uninit(&vdev->pdev,
+ msix_uninit(pdev,
vdev->bars[vdev->msix->table_bar].mr,
vdev->bars[vdev->msix->pba_bar].mr);
g_free(vdev->msix->pending);
@@ -1936,6 +1959,7 @@ static void vfio_bars_prepare(VFIOPCIDevice *vdev)
static void vfio_bar_register(VFIOPCIDevice *vdev, int nr)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIOBAR *bar = &vdev->bars[nr];
char *name;
@@ -1957,7 +1981,7 @@ static void vfio_bar_register(VFIOPCIDevice *vdev, int nr)
}
}
- pci_register_bar(&vdev->pdev, nr, bar->type, bar->mr);
+ pci_register_bar(pdev, nr, bar->type, bar->mr);
}
static void vfio_bars_register(VFIOPCIDevice *vdev)
@@ -1971,6 +1995,7 @@ static void vfio_bars_register(VFIOPCIDevice *vdev)
void vfio_pci_bars_exit(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int i;
for (i = 0; i < PCI_ROM_SLOT; i++) {
@@ -1984,7 +2009,7 @@ void vfio_pci_bars_exit(VFIOPCIDevice *vdev)
}
if (vdev->vga) {
- pci_unregister_vga(&vdev->pdev);
+ pci_unregister_vga(pdev);
vfio_vga_quirk_exit(vdev);
}
}
@@ -2056,8 +2081,10 @@ static void vfio_set_word_bits(uint8_t *buf, uint16_t val, uint16_t mask)
static void vfio_add_emulated_word(VFIOPCIDevice *vdev, int pos,
uint16_t val, uint16_t mask)
{
- vfio_set_word_bits(vdev->pdev.config + pos, val, mask);
- vfio_set_word_bits(vdev->pdev.wmask + pos, ~mask, mask);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
+ vfio_set_word_bits(pdev->config + pos, val, mask);
+ vfio_set_word_bits(pdev->wmask + pos, ~mask, mask);
vfio_set_word_bits(vdev->emulated_config_bits + pos, mask, mask);
}
@@ -2069,8 +2096,10 @@ static void vfio_set_long_bits(uint8_t *buf, uint32_t val, uint32_t mask)
static void vfio_add_emulated_long(VFIOPCIDevice *vdev, int pos,
uint32_t val, uint32_t mask)
{
- vfio_set_long_bits(vdev->pdev.config + pos, val, mask);
- vfio_set_long_bits(vdev->pdev.wmask + pos, ~mask, mask);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
+ vfio_set_long_bits(pdev->config + pos, val, mask);
+ vfio_set_long_bits(pdev->wmask + pos, ~mask, mask);
vfio_set_long_bits(vdev->emulated_config_bits + pos, mask, mask);
}
@@ -2078,7 +2107,8 @@ static void vfio_pci_enable_rp_atomics(VFIOPCIDevice *vdev)
{
struct vfio_device_info_cap_pci_atomic_comp *cap;
g_autofree struct vfio_device_info *info = NULL;
- PCIBus *bus = pci_get_bus(&vdev->pdev);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ PCIBus *bus = pci_get_bus(pdev);
PCIDevice *parent = bus->parent_dev;
struct vfio_info_cap_header *hdr;
uint32_t mask = 0;
@@ -2094,8 +2124,8 @@ static void vfio_pci_enable_rp_atomics(VFIOPCIDevice *vdev)
if (pci_bus_is_root(bus) || !parent || !parent->exp.exp_cap ||
pcie_cap_get_type(parent) != PCI_EXP_TYPE_ROOT_PORT ||
pcie_cap_get_version(parent) != PCI_EXP_FLAGS_VER2 ||
- vdev->pdev.devfn ||
- vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+ pdev->devfn ||
+ pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
return;
}
@@ -2139,8 +2169,10 @@ static void vfio_pci_enable_rp_atomics(VFIOPCIDevice *vdev)
static void vfio_pci_disable_rp_atomics(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+
if (vdev->clear_parent_atomics_on_exit) {
- PCIDevice *parent = pci_get_bus(&vdev->pdev)->parent_dev;
+ PCIDevice *parent = pci_get_bus(pdev)->parent_dev;
uint8_t *pos = parent->config + parent->exp.exp_cap + PCI_EXP_DEVCAP2;
pci_long_test_and_clear_mask(pos, PCI_EXP_DEVCAP2_ATOMIC_COMP32 |
@@ -2152,10 +2184,11 @@ static void vfio_pci_disable_rp_atomics(VFIOPCIDevice *vdev)
static bool vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
Error **errp)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint16_t flags;
uint8_t type;
- flags = pci_get_word(vdev->pdev.config + pos + PCI_CAP_FLAGS);
+ flags = pci_get_word(pdev->config + pos + PCI_CAP_FLAGS);
type = (flags & PCI_EXP_FLAGS_TYPE) >> 4;
if (type != PCI_EXP_TYPE_ENDPOINT &&
@@ -2167,8 +2200,8 @@ static bool vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
return false;
}
- if (!pci_bus_is_express(pci_get_bus(&vdev->pdev))) {
- PCIBus *bus = pci_get_bus(&vdev->pdev);
+ if (!pci_bus_is_express(pci_get_bus(pdev))) {
+ PCIBus *bus = pci_get_bus(pdev);
PCIDevice *bridge;
/*
@@ -2200,7 +2233,7 @@ static bool vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
return true;
}
- } else if (pci_bus_is_root(pci_get_bus(&vdev->pdev))) {
+ } else if (pci_bus_is_root(pci_get_bus(pdev))) {
/*
* On a Root Complex bus Endpoints become Root Complex Integrated
* Endpoints, which changes the type and clears the LNK & LNK2 fields.
@@ -2268,20 +2301,20 @@ static bool vfio_setup_pcie_cap(VFIOPCIDevice *vdev, int pos, uint8_t size,
1, PCI_EXP_FLAGS_VERS);
}
- pos = pci_add_capability(&vdev->pdev, PCI_CAP_ID_EXP, pos, size,
- errp);
+ pos = pci_add_capability(pdev, PCI_CAP_ID_EXP, pos, size, errp);
if (pos < 0) {
return false;
}
- vdev->pdev.exp.exp_cap = pos;
+ pdev->exp.exp_cap = pos;
return true;
}
static void vfio_check_pcie_flr(VFIOPCIDevice *vdev, uint8_t pos)
{
- uint32_t cap = pci_get_long(vdev->pdev.config + pos + PCI_EXP_DEVCAP);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ uint32_t cap = pci_get_long(pdev->config + pos + PCI_EXP_DEVCAP);
if (cap & PCI_EXP_DEVCAP_FLR) {
trace_vfio_check_pcie_flr(vdev->vbasedev.name);
@@ -2291,7 +2324,8 @@ static void vfio_check_pcie_flr(VFIOPCIDevice *vdev, uint8_t pos)
static void vfio_check_pm_reset(VFIOPCIDevice *vdev, uint8_t pos)
{
- uint16_t csr = pci_get_word(vdev->pdev.config + pos + PCI_PM_CTRL);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ uint16_t csr = pci_get_word(pdev->config + pos + PCI_PM_CTRL);
if (!(csr & PCI_PM_CTRL_NO_SOFT_RESET)) {
trace_vfio_check_pm_reset(vdev->vbasedev.name);
@@ -2301,7 +2335,8 @@ static void vfio_check_pm_reset(VFIOPCIDevice *vdev, uint8_t pos)
static void vfio_check_af_flr(VFIOPCIDevice *vdev, uint8_t pos)
{
- uint8_t cap = pci_get_byte(vdev->pdev.config + pos + PCI_AF_CAP);
+ PCIDevice *pdev = PCI_DEVICE(vdev);
+ uint8_t cap = pci_get_byte(pdev->config + pos + PCI_AF_CAP);
if ((cap & PCI_AF_CAP_TP) && (cap & PCI_AF_CAP_FLR)) {
trace_vfio_check_af_flr(vdev->vbasedev.name);
@@ -2312,7 +2347,7 @@ static void vfio_check_af_flr(VFIOPCIDevice *vdev, uint8_t pos)
static bool vfio_add_vendor_specific_cap(VFIOPCIDevice *vdev, int pos,
uint8_t size, Error **errp)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
pos = pci_add_capability(pdev, PCI_CAP_ID_VNDR, pos, size, errp);
if (pos < 0) {
@@ -2334,7 +2369,7 @@ static bool vfio_add_vendor_specific_cap(VFIOPCIDevice *vdev, int pos,
static bool vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp)
{
ERRP_GUARD();
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint8_t cap_id, next, size;
bool ret;
@@ -2420,17 +2455,18 @@ static bool vfio_add_std_cap(VFIOPCIDevice *vdev, uint8_t pos, Error **errp)
static int vfio_setup_rebar_ecap(VFIOPCIDevice *vdev, uint16_t pos)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint32_t ctrl;
int i, nbar;
- ctrl = pci_get_long(vdev->pdev.config + pos + PCI_REBAR_CTRL);
+ ctrl = pci_get_long(pdev->config + pos + PCI_REBAR_CTRL);
nbar = (ctrl & PCI_REBAR_CTRL_NBAR_MASK) >> PCI_REBAR_CTRL_NBAR_SHIFT;
for (i = 0; i < nbar; i++) {
uint32_t cap;
int size;
- ctrl = pci_get_long(vdev->pdev.config + pos + PCI_REBAR_CTRL + (i * 8));
+ ctrl = pci_get_long(pdev->config + pos + PCI_REBAR_CTRL + (i * 8));
size = (ctrl & PCI_REBAR_CTRL_BAR_SIZE) >> PCI_REBAR_CTRL_BAR_SHIFT;
/* The cap register reports sizes 1MB to 128TB, with 4 reserved bits */
@@ -2468,7 +2504,7 @@ static int vfio_setup_rebar_ecap(VFIOPCIDevice *vdev, uint16_t pos)
static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint32_t header;
uint16_t cap_id, next, size;
uint8_t cap_ver;
@@ -2562,7 +2598,7 @@ static void vfio_add_ext_cap(VFIOPCIDevice *vdev)
bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
if (!(pdev->config[PCI_STATUS] & PCI_STATUS_CAP_LIST) ||
!pdev->config[PCI_CAPABILITY_LIST]) {
@@ -2579,7 +2615,7 @@ bool vfio_pci_add_capabilities(VFIOPCIDevice *vdev, Error **errp)
void vfio_pci_pre_reset(VFIOPCIDevice *vdev)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
uint16_t cmd;
vfio_disable_interrupts(vdev);
@@ -2775,8 +2811,8 @@ static const VMStateDescription vmstate_vfio_pci_config = {
.version_id = 1,
.minimum_version_id = 1,
.fields = (const VMStateField[]) {
- VMSTATE_PCI_DEVICE(pdev, VFIOPCIDevice),
- VMSTATE_MSIX_TEST(pdev, VFIOPCIDevice, vfio_msix_present),
+ VMSTATE_PCI_DEVICE(parent_obj, VFIOPCIDevice),
+ VMSTATE_MSIX_TEST(parent_obj, VFIOPCIDevice, vfio_msix_present),
VMSTATE_END_OF_LIST()
},
.subsections = (const VMStateDescription * const []) {
@@ -2796,7 +2832,7 @@ static int vfio_pci_save_config(VFIODevice *vbasedev, QEMUFile *f, Error **errp)
static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
{
VFIOPCIDevice *vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
pcibus_t old_addr[PCI_NUM_REGIONS - 1];
int bar, ret;
@@ -2833,9 +2869,18 @@ static int vfio_pci_load_config(VFIODevice *vbasedev, QEMUFile *f)
return ret;
}
+/* Transform from VFIODevice to VFIOPCIDevice. Return NULL if fails. */
+VFIOPCIDevice *vfio_pci_from_vfio_device(VFIODevice *vbasedev)
+{
+ if (vbasedev && vbasedev->type == VFIO_DEVICE_TYPE_PCI) {
+ return container_of(vbasedev, VFIOPCIDevice, vbasedev);
+ }
+ return NULL;
+}
+
void vfio_sub_page_bar_update_mappings(VFIOPCIDevice *vdev)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
int page_size = qemu_real_host_page_size();
int bar;
@@ -2919,6 +2964,7 @@ bool vfio_populate_vga(VFIOPCIDevice *vdev, Error **errp)
bool vfio_pci_populate_device(VFIOPCIDevice *vdev, Error **errp)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIODevice *vbasedev = &vdev->vbasedev;
struct vfio_region_info *reg_info = NULL;
struct vfio_irq_info irq_info;
@@ -2970,7 +3016,7 @@ bool vfio_pci_populate_device(VFIOPCIDevice *vdev, Error **errp)
vdev->config_size = reg_info->size;
if (vdev->config_size == PCI_CONFIG_SPACE_SIZE) {
- vdev->pdev.cap_present &= ~QEMU_PCI_CAP_EXPRESS;
+ pdev->cap_present &= ~QEMU_PCI_CAP_EXPRESS;
}
vdev->config_offset = reg_info->offset;
@@ -3174,25 +3220,26 @@ static void vfio_unregister_req_notifier(VFIOPCIDevice *vdev)
void vfio_pci_config_register_vga(VFIOPCIDevice *vdev)
{
+ PCIDevice *pdev = PCI_DEVICE(vdev);
assert(vdev->vga != NULL);
- pci_register_vga(&vdev->pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
+ pci_register_vga(pdev, &vdev->vga->region[QEMU_PCI_VGA_MEM].mem,
&vdev->vga->region[QEMU_PCI_VGA_IO_LO].mem,
&vdev->vga->region[QEMU_PCI_VGA_IO_HI].mem);
}
bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
VFIODevice *vbasedev = &vdev->vbasedev;
uint32_t config_space_size;
int ret;
- config_space_size = MIN(pci_config_size(&vdev->pdev), vdev->config_size);
+ config_space_size = MIN(pci_config_size(pdev), vdev->config_size);
/* Get a copy of config space */
ret = vfio_pci_config_space_read(vdev, 0, config_space_size,
- vdev->pdev.config);
+ pdev->config);
if (ret < (int)config_space_size) {
ret = ret < 0 ? -ret : EFAULT;
error_setg_errno(errp, ret, "failed to read device config space");
@@ -3277,10 +3324,10 @@ bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
PCI_HEADER_TYPE_MULTI_FUNCTION;
/* Restore or clear multifunction, this is always controlled by QEMU */
- if (vdev->pdev.cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
- vdev->pdev.config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
+ if (pdev->cap_present & QEMU_PCI_CAP_MULTIFUNCTION) {
+ pdev->config[PCI_HEADER_TYPE] |= PCI_HEADER_TYPE_MULTI_FUNCTION;
} else {
- vdev->pdev.config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
+ pdev->config[PCI_HEADER_TYPE] &= ~PCI_HEADER_TYPE_MULTI_FUNCTION;
}
/*
@@ -3288,8 +3335,8 @@ bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
* BAR, such as might be the case with the option ROM, we can get
* confusing, unwritable, residual addresses from the host here.
*/
- memset(&vdev->pdev.config[PCI_BASE_ADDRESS_0], 0, 24);
- memset(&vdev->pdev.config[PCI_ROM_ADDRESS], 0, 4);
+ memset(&pdev->config[PCI_BASE_ADDRESS_0], 0, 24);
+ memset(&pdev->config[PCI_ROM_ADDRESS], 0, 4);
vfio_pci_size_rom(vdev);
@@ -3310,7 +3357,7 @@ bool vfio_pci_config_setup(VFIOPCIDevice *vdev, Error **errp)
bool vfio_pci_interrupt_setup(VFIOPCIDevice *vdev, Error **errp)
{
- PCIDevice *pdev = &vdev->pdev;
+ PCIDevice *pdev = PCI_DEVICE(vdev);
/* QEMU emulates all of MSI & MSIX */
if (pdev->cap_present & QEMU_PCI_CAP_MSIX) {
@@ -3323,10 +3370,10 @@ bool vfio_pci_interrupt_setup(VFIOPCIDevice *vdev, Error **errp)
vdev->msi_cap_size);
}
- if (vfio_pci_read_config(&vdev->pdev, PCI_INTERRUPT_PIN, 1)) {
+ if (vfio_pci_read_config(pdev, PCI_INTERRUPT_PIN, 1)) {
vdev->intx.mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
vfio_intx_mmap_enable, vdev);
- pci_device_set_intx_routing_notifier(&vdev->pdev,
+ pci_device_set_intx_routing_notifier(pdev,
vfio_intx_routing_notifier);
vdev->irqchip_change_notifier.notify = vfio_irqchip_change;
kvm_irqchip_add_change_notifier(&vdev->irqchip_change_notifier);
@@ -3338,7 +3385,7 @@ bool vfio_pci_interrupt_setup(VFIOPCIDevice *vdev, Error **errp)
*/
if (!cpr_is_incoming() && !vfio_intx_enable(vdev, errp)) {
timer_free(vdev->intx.mmap_timer);
- pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
+ pci_device_set_intx_routing_notifier(pdev, NULL);
kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
return false;
}
@@ -3489,7 +3536,7 @@ out_deregister:
if (vdev->interrupt == VFIO_INT_INTx) {
vfio_intx_disable(vdev);
}
- pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
+ pci_device_set_intx_routing_notifier(pdev, NULL);
if (vdev->irqchip_change_notifier.notify) {
kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
}
@@ -3521,7 +3568,7 @@ static void vfio_exitfn(PCIDevice *pdev)
vfio_unregister_req_notifier(vdev);
vfio_unregister_err_notifier(vdev);
- pci_device_set_intx_routing_notifier(&vdev->pdev, NULL);
+ pci_device_set_intx_routing_notifier(pdev, NULL);
if (vdev->irqchip_change_notifier.notify) {
kvm_irqchip_remove_change_notifier(&vdev->irqchip_change_notifier);
}
diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
index 810a842..e0aef82 100644
--- a/hw/vfio/pci.h
+++ b/hw/vfio/pci.h
@@ -123,7 +123,8 @@ typedef struct VFIOMSIXInfo {
OBJECT_DECLARE_SIMPLE_TYPE(VFIOPCIDevice, VFIO_PCI_BASE)
struct VFIOPCIDevice {
- PCIDevice pdev;
+ PCIDevice parent_obj;
+
VFIODevice vbasedev;
VFIOINTx intx;
unsigned int config_size;
@@ -203,6 +204,11 @@ static inline bool vfio_is_vga(VFIOPCIDevice *vdev)
return (vdev->class_code >> 8) == PCI_CLASS_DISPLAY_VGA;
}
+static inline bool vfio_is_base_display(VFIOPCIDevice *vdev)
+{
+ return (vdev->class_code >> 16) == PCI_BASE_CLASS_DISPLAY;
+}
+
/* MSI/MSI-X/INTx */
void vfio_pci_vector_init(VFIOPCIDevice *vdev, int nr);
void vfio_pci_add_kvm_msi_virq(VFIOPCIDevice *vdev, VFIOMSIVector *vector,
@@ -221,6 +227,18 @@ void vfio_pci_write_config(PCIDevice *pdev,
uint64_t vfio_vga_read(void *opaque, hwaddr addr, unsigned size);
void vfio_vga_write(void *opaque, hwaddr addr, uint64_t data, unsigned size);
+/**
+ * vfio_pci_from_vfio_device: Transform from VFIODevice to
+ * VFIOPCIDevice
+ *
+ * This function checks if the given @vbasedev is a VFIO PCI device.
+ * If it is, it returns the containing VFIOPCIDevice.
+ *
+ * @vbasedev: The VFIODevice to transform
+ *
+ * Return: The VFIOPCIDevice on success, NULL on failure.
+ */
+VFIOPCIDevice *vfio_pci_from_vfio_device(VFIODevice *vbasedev);
void vfio_sub_page_bar_update_mappings(VFIOPCIDevice *vdev);
bool vfio_opt_rom_in_denylist(VFIOPCIDevice *vdev);
bool vfio_config_quirk_setup(VFIOPCIDevice *vdev, Error **errp);
diff --git a/hw/vfio/platform.c b/hw/vfio/platform.c
deleted file mode 100644
index 5c1795a..0000000
--- a/hw/vfio/platform.c
+++ /dev/null
@@ -1,716 +0,0 @@
-/*
- * vfio based device assignment support - platform devices
- *
- * Copyright Linaro Limited, 2014
- *
- * Authors:
- * Kim Phillips <kim.phillips@linaro.org>
- * Eric Auger <eric.auger@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Based on vfio based PCI device assignment support:
- * Copyright Red Hat, Inc. 2012
- */
-
-#include "qemu/osdep.h"
-#include CONFIG_DEVICES /* CONFIG_IOMMUFD */
-#include "qapi/error.h"
-#include <sys/ioctl.h>
-#include <linux/vfio.h>
-
-#include "hw/vfio/vfio-platform.h"
-#include "system/iommufd.h"
-#include "migration/vmstate.h"
-#include "qemu/error-report.h"
-#include "qemu/lockable.h"
-#include "qemu/main-loop.h"
-#include "qemu/module.h"
-#include "qemu/range.h"
-#include "system/memory.h"
-#include "system/address-spaces.h"
-#include "qemu/queue.h"
-#include "hw/sysbus.h"
-#include "trace.h"
-#include "hw/irq.h"
-#include "hw/platform-bus.h"
-#include "hw/qdev-properties.h"
-#include "system/kvm.h"
-#include "hw/vfio/vfio-region.h"
-
-/*
- * Functions used whatever the injection method
- */
-
-static inline bool vfio_irq_is_automasked(VFIOINTp *intp)
-{
- return intp->flags & VFIO_IRQ_INFO_AUTOMASKED;
-}
-
-/**
- * vfio_init_intp - allocate, initialize the IRQ struct pointer
- * and add it into the list of IRQs
- * @vbasedev: the VFIO device handle
- * @info: irq info struct retrieved from VFIO driver
- * @errp: error object
- */
-static VFIOINTp *vfio_init_intp(VFIODevice *vbasedev,
- struct vfio_irq_info info, Error **errp)
-{
- int ret;
- VFIOPlatformDevice *vdev =
- container_of(vbasedev, VFIOPlatformDevice, vbasedev);
- SysBusDevice *sbdev = SYS_BUS_DEVICE(vdev);
- VFIOINTp *intp;
-
- intp = g_malloc0(sizeof(*intp));
- intp->vdev = vdev;
- intp->pin = info.index;
- intp->flags = info.flags;
- intp->state = VFIO_IRQ_INACTIVE;
- intp->kvm_accel = false;
-
- sysbus_init_irq(sbdev, &intp->qemuirq);
-
- /* Get an eventfd for trigger */
- intp->interrupt = g_new0(EventNotifier, 1);
- ret = event_notifier_init(intp->interrupt, 0);
- if (ret) {
- g_free(intp->interrupt);
- g_free(intp);
- error_setg_errno(errp, -ret,
- "failed to initialize trigger eventfd notifier");
- return NULL;
- }
- if (vfio_irq_is_automasked(intp)) {
- /* Get an eventfd for resample/unmask */
- intp->unmask = g_new0(EventNotifier, 1);
- ret = event_notifier_init(intp->unmask, 0);
- if (ret) {
- g_free(intp->interrupt);
- g_free(intp->unmask);
- g_free(intp);
- error_setg_errno(errp, -ret,
- "failed to initialize resample eventfd notifier");
- return NULL;
- }
- }
-
- QLIST_INSERT_HEAD(&vdev->intp_list, intp, next);
- return intp;
-}
-
-/**
- * vfio_set_trigger_eventfd - set VFIO eventfd handling
- *
- * @intp: IRQ struct handle
- * @handler: handler to be called on eventfd signaling
- *
- * Setup VFIO signaling and attach an optional user-side handler
- * to the eventfd
- */
-static int vfio_set_trigger_eventfd(VFIOINTp *intp,
- eventfd_user_side_handler_t handler)
-{
- VFIODevice *vbasedev = &intp->vdev->vbasedev;
- int32_t fd = event_notifier_get_fd(intp->interrupt);
- Error *err = NULL;
-
- qemu_set_fd_handler(fd, (IOHandler *)handler, NULL, intp);
-
- if (!vfio_device_irq_set_signaling(vbasedev, intp->pin, 0,
- VFIO_IRQ_SET_ACTION_TRIGGER, fd, &err)) {
- error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
- qemu_set_fd_handler(fd, NULL, NULL, NULL);
- return -EINVAL;
- }
-
- return 0;
-}
-
-/*
- * Functions only used when eventfds are handled on user-side
- * ie. without irqfd
- */
-
-/**
- * vfio_mmap_set_enabled - enable/disable the fast path mode
- * @vdev: the VFIO platform device
- * @enabled: the target mmap state
- *
- * enabled = true ~ fast path = MMIO region is mmaped (no KVM TRAP);
- * enabled = false ~ slow path = MMIO region is trapped and region callbacks
- * are called; slow path enables to trap the device IRQ status register reset
-*/
-
-static void vfio_mmap_set_enabled(VFIOPlatformDevice *vdev, bool enabled)
-{
- int i;
-
- for (i = 0; i < vdev->vbasedev.num_regions; i++) {
- vfio_region_mmaps_set_enabled(vdev->regions[i], enabled);
- }
-}
-
-/**
- * vfio_intp_mmap_enable - timer function, restores the fast path
- * if there is no more active IRQ
- * @opaque: actually points to the VFIO platform device
- *
- * Called on mmap timer timeout, this function checks whether the
- * IRQ is still active and if not, restores the fast path.
- * by construction a single eventfd is handled at a time.
- * if the IRQ is still active, the timer is re-programmed.
- */
-static void vfio_intp_mmap_enable(void *opaque)
-{
- VFIOINTp *tmp;
- VFIOPlatformDevice *vdev = (VFIOPlatformDevice *)opaque;
-
- QEMU_LOCK_GUARD(&vdev->intp_mutex);
- QLIST_FOREACH(tmp, &vdev->intp_list, next) {
- if (tmp->state == VFIO_IRQ_ACTIVE) {
- trace_vfio_platform_intp_mmap_enable(tmp->pin);
- /* re-program the timer to check active status later */
- timer_mod(vdev->mmap_timer,
- qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
- vdev->mmap_timeout);
- return;
- }
- }
- vfio_mmap_set_enabled(vdev, true);
-}
-
-/**
- * vfio_intp_inject_pending_lockheld - Injects a pending IRQ
- * @opaque: opaque pointer, in practice the VFIOINTp handle
- *
- * The function is called on a previous IRQ completion, from
- * vfio_platform_eoi, while the intp_mutex is locked.
- * Also in such situation, the slow path already is set and
- * the mmap timer was already programmed.
- */
-static void vfio_intp_inject_pending_lockheld(VFIOINTp *intp)
-{
- trace_vfio_platform_intp_inject_pending_lockheld(intp->pin,
- event_notifier_get_fd(intp->interrupt));
-
- intp->state = VFIO_IRQ_ACTIVE;
-
- /* trigger the virtual IRQ */
- qemu_set_irq(intp->qemuirq, 1);
-}
-
-/**
- * vfio_intp_interrupt - The user-side eventfd handler
- * @opaque: opaque pointer which in practice is the VFIOINTp handle
- *
- * the function is entered in event handler context:
- * the vIRQ is injected into the guest if there is no other active
- * or pending IRQ.
- */
-static void vfio_intp_interrupt(VFIOINTp *intp)
-{
- int ret;
- VFIOINTp *tmp;
- VFIOPlatformDevice *vdev = intp->vdev;
- bool delay_handling = false;
-
- QEMU_LOCK_GUARD(&vdev->intp_mutex);
- if (intp->state == VFIO_IRQ_INACTIVE) {
- QLIST_FOREACH(tmp, &vdev->intp_list, next) {
- if (tmp->state == VFIO_IRQ_ACTIVE ||
- tmp->state == VFIO_IRQ_PENDING) {
- delay_handling = true;
- break;
- }
- }
- }
- if (delay_handling) {
- /*
- * the new IRQ gets a pending status and is pushed in
- * the pending queue
- */
- intp->state = VFIO_IRQ_PENDING;
- trace_vfio_intp_interrupt_set_pending(intp->pin);
- QSIMPLEQ_INSERT_TAIL(&vdev->pending_intp_queue,
- intp, pqnext);
- event_notifier_test_and_clear(intp->interrupt);
- return;
- }
-
- trace_vfio_platform_intp_interrupt(intp->pin,
- event_notifier_get_fd(intp->interrupt));
-
- ret = event_notifier_test_and_clear(intp->interrupt);
- if (!ret) {
- error_report("Error when clearing fd=%d (ret = %d)",
- event_notifier_get_fd(intp->interrupt), ret);
- }
-
- intp->state = VFIO_IRQ_ACTIVE;
-
- /* sets slow path */
- vfio_mmap_set_enabled(vdev, false);
-
- /* trigger the virtual IRQ */
- qemu_set_irq(intp->qemuirq, 1);
-
- /*
- * Schedule the mmap timer which will restore fastpath when no IRQ
- * is active anymore
- */
- if (vdev->mmap_timeout) {
- timer_mod(vdev->mmap_timer,
- qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) +
- vdev->mmap_timeout);
- }
-}
-
-/**
- * vfio_platform_eoi - IRQ completion routine
- * @vbasedev: the VFIO device handle
- *
- * De-asserts the active virtual IRQ and unmasks the physical IRQ
- * (effective for level sensitive IRQ auto-masked by the VFIO driver).
- * Then it handles next pending IRQ if any.
- * eoi function is called on the first access to any MMIO region
- * after an IRQ was triggered, trapped since slow path was set.
- * It is assumed this access corresponds to the IRQ status
- * register reset. With such a mechanism, a single IRQ can be
- * handled at a time since there is no way to know which IRQ
- * was completed by the guest (we would need additional details
- * about the IRQ status register mask).
- */
-static void vfio_platform_eoi(VFIODevice *vbasedev)
-{
- VFIOINTp *intp;
- VFIOPlatformDevice *vdev =
- container_of(vbasedev, VFIOPlatformDevice, vbasedev);
-
- QEMU_LOCK_GUARD(&vdev->intp_mutex);
- QLIST_FOREACH(intp, &vdev->intp_list, next) {
- if (intp->state == VFIO_IRQ_ACTIVE) {
- trace_vfio_platform_eoi(intp->pin,
- event_notifier_get_fd(intp->interrupt));
- intp->state = VFIO_IRQ_INACTIVE;
-
- /* deassert the virtual IRQ */
- qemu_set_irq(intp->qemuirq, 0);
-
- if (vfio_irq_is_automasked(intp)) {
- /* unmasks the physical level-sensitive IRQ */
- vfio_device_irq_unmask(vbasedev, intp->pin);
- }
-
- /* a single IRQ can be active at a time */
- break;
- }
- }
- /* in case there are pending IRQs, handle the first one */
- if (!QSIMPLEQ_EMPTY(&vdev->pending_intp_queue)) {
- intp = QSIMPLEQ_FIRST(&vdev->pending_intp_queue);
- vfio_intp_inject_pending_lockheld(intp);
- QSIMPLEQ_REMOVE_HEAD(&vdev->pending_intp_queue, pqnext);
- }
-}
-
-/**
- * vfio_start_eventfd_injection - starts the virtual IRQ injection using
- * user-side handled eventfds
- * @sbdev: the sysbus device handle
- * @irq: the qemu irq handle
- */
-
-static void vfio_start_eventfd_injection(SysBusDevice *sbdev, qemu_irq irq)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
- VFIOINTp *intp;
-
- QLIST_FOREACH(intp, &vdev->intp_list, next) {
- if (intp->qemuirq == irq) {
- break;
- }
- }
- assert(intp);
-
- if (vfio_set_trigger_eventfd(intp, vfio_intp_interrupt)) {
- abort();
- }
-}
-
-/*
- * Functions used for irqfd
- */
-
-/**
- * vfio_set_resample_eventfd - sets the resamplefd for an IRQ
- * @intp: the IRQ struct handle
- * programs the VFIO driver to unmask this IRQ when the
- * intp->unmask eventfd is triggered
- */
-static int vfio_set_resample_eventfd(VFIOINTp *intp)
-{
- int32_t fd = event_notifier_get_fd(intp->unmask);
- VFIODevice *vbasedev = &intp->vdev->vbasedev;
- Error *err = NULL;
-
- qemu_set_fd_handler(fd, NULL, NULL, NULL);
- if (!vfio_device_irq_set_signaling(vbasedev, intp->pin, 0,
- VFIO_IRQ_SET_ACTION_UNMASK, fd, &err)) {
- error_reportf_err(err, VFIO_MSG_PREFIX, vbasedev->name);
- return -EINVAL;
- }
- return 0;
-}
-
-/**
- * vfio_start_irqfd_injection - starts the virtual IRQ injection using
- * irqfd
- *
- * @sbdev: the sysbus device handle
- * @irq: the qemu irq handle
- *
- * In case the irqfd setup fails, we fallback to userspace handled eventfd
- */
-static void vfio_start_irqfd_injection(SysBusDevice *sbdev, qemu_irq irq)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(sbdev);
- VFIOINTp *intp;
-
- if (!kvm_irqfds_enabled() || !kvm_resamplefds_enabled() ||
- !vdev->irqfd_allowed) {
- goto fail_irqfd;
- }
-
- QLIST_FOREACH(intp, &vdev->intp_list, next) {
- if (intp->qemuirq == irq) {
- break;
- }
- }
- assert(intp);
-
- if (kvm_irqchip_add_irqfd_notifier(kvm_state, intp->interrupt,
- intp->unmask, irq) < 0) {
- goto fail_irqfd;
- }
-
- if (vfio_set_trigger_eventfd(intp, NULL) < 0) {
- goto fail_vfio;
- }
- if (vfio_irq_is_automasked(intp)) {
- if (vfio_set_resample_eventfd(intp) < 0) {
- goto fail_vfio;
- }
- trace_vfio_platform_start_level_irqfd_injection(intp->pin,
- event_notifier_get_fd(intp->interrupt),
- event_notifier_get_fd(intp->unmask));
- } else {
- trace_vfio_platform_start_edge_irqfd_injection(intp->pin,
- event_notifier_get_fd(intp->interrupt));
- }
-
- intp->kvm_accel = true;
-
- return;
-fail_vfio:
- kvm_irqchip_remove_irqfd_notifier(kvm_state, intp->interrupt, irq);
- abort();
-fail_irqfd:
- vfio_start_eventfd_injection(sbdev, irq);
-}
-
-/* VFIO skeleton */
-
-static void vfio_platform_compute_needs_reset(VFIODevice *vbasedev)
-{
- vbasedev->needs_reset = true;
-}
-
-/* not implemented yet */
-static int vfio_platform_hot_reset_multi(VFIODevice *vbasedev)
-{
- return -1;
-}
-
-/**
- * vfio_populate_device - Allocate and populate MMIO region
- * and IRQ structs according to driver returned information
- * @vbasedev: the VFIO device handle
- * @errp: error object
- *
- */
-static bool vfio_populate_device(VFIODevice *vbasedev, Error **errp)
-{
- VFIOINTp *intp, *tmp;
- int i, ret = -1;
- VFIOPlatformDevice *vdev =
- container_of(vbasedev, VFIOPlatformDevice, vbasedev);
-
- if (!(vbasedev->flags & VFIO_DEVICE_FLAGS_PLATFORM)) {
- error_setg(errp, "this isn't a platform device");
- return false;
- }
-
- vdev->regions = g_new0(VFIORegion *, vbasedev->num_regions);
-
- for (i = 0; i < vbasedev->num_regions; i++) {
- char *name = g_strdup_printf("VFIO %s region %d\n", vbasedev->name, i);
-
- vdev->regions[i] = g_new0(VFIORegion, 1);
- ret = vfio_region_setup(OBJECT(vdev), vbasedev,
- vdev->regions[i], i, name);
- g_free(name);
- if (ret) {
- error_setg_errno(errp, -ret, "failed to get region %d info", i);
- goto reg_error;
- }
- }
-
- vdev->mmap_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL,
- vfio_intp_mmap_enable, vdev);
-
- QSIMPLEQ_INIT(&vdev->pending_intp_queue);
-
- for (i = 0; i < vbasedev->num_irqs; i++) {
- struct vfio_irq_info irq;
-
- ret = vfio_device_get_irq_info(vbasedev, i, &irq);
-
- if (ret) {
- error_setg_errno(errp, -ret, "failed to get device irq info");
- goto irq_err;
- } else {
- trace_vfio_platform_populate_interrupts(irq.index,
- irq.count,
- irq.flags);
- intp = vfio_init_intp(vbasedev, irq, errp);
- if (!intp) {
- goto irq_err;
- }
- }
- }
- return true;
-irq_err:
- timer_del(vdev->mmap_timer);
- QLIST_FOREACH_SAFE(intp, &vdev->intp_list, next, tmp) {
- QLIST_REMOVE(intp, next);
- g_free(intp);
- }
-reg_error:
- for (i = 0; i < vbasedev->num_regions; i++) {
- if (vdev->regions[i]) {
- vfio_region_finalize(vdev->regions[i]);
- }
- g_free(vdev->regions[i]);
- }
- g_free(vdev->regions);
- return false;
-}
-
-/* specialized functions for VFIO Platform devices */
-static VFIODeviceOps vfio_platform_ops = {
- .vfio_compute_needs_reset = vfio_platform_compute_needs_reset,
- .vfio_hot_reset_multi = vfio_platform_hot_reset_multi,
- .vfio_eoi = vfio_platform_eoi,
-};
-
-/**
- * vfio_base_device_init - perform preliminary VFIO setup
- * @vbasedev: the VFIO device handle
- * @errp: error object
- *
- * Implement the VFIO command sequence that allows to discover
- * assigned device resources: group extraction, device
- * fd retrieval, resource query.
- * Precondition: the device name must be initialized
- */
-static bool vfio_base_device_init(VFIODevice *vbasedev, Error **errp)
-{
- /* @fd takes precedence over @sysfsdev which takes precedence over @host */
- if (vbasedev->fd < 0 && vbasedev->sysfsdev) {
- vfio_device_free_name(vbasedev);
- vbasedev->name = g_path_get_basename(vbasedev->sysfsdev);
- } else if (vbasedev->fd < 0) {
- if (!vbasedev->name || strchr(vbasedev->name, '/')) {
- error_setg(errp, "wrong host device name");
- return false;
- }
-
- vbasedev->sysfsdev = g_strdup_printf("/sys/bus/platform/devices/%s",
- vbasedev->name);
- }
-
- if (!vfio_device_get_name(vbasedev, errp)) {
- return false;
- }
-
- if (!vfio_device_attach(vbasedev->name, vbasedev,
- &address_space_memory, errp)) {
- return false;
- }
-
- if (vfio_populate_device(vbasedev, errp)) {
- return true;
- }
-
- vfio_device_detach(vbasedev);
- return false;
-}
-
-/**
- * vfio_platform_realize - the device realize function
- * @dev: device state pointer
- * @errp: error
- *
- * initialize the device, its memory regions and IRQ structures
- * IRQ are started separately
- */
-static void vfio_platform_realize(DeviceState *dev, Error **errp)
-{
- ERRP_GUARD();
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(dev);
- SysBusDevice *sbdev = SYS_BUS_DEVICE(dev);
- VFIODevice *vbasedev = &vdev->vbasedev;
- int i;
-
- warn_report("-device vfio-platform is deprecated");
- qemu_mutex_init(&vdev->intp_mutex);
-
- trace_vfio_platform_realize(vbasedev->sysfsdev ?
- vbasedev->sysfsdev : vbasedev->name,
- vdev->compat);
-
- if (!vfio_base_device_init(vbasedev, errp)) {
- goto init_err;
- }
-
- if (!vdev->compat) {
- GError *gerr = NULL;
- gchar *contents;
- gsize length;
- char *path;
-
- path = g_strdup_printf("%s/of_node/compatible", vbasedev->sysfsdev);
- if (!g_file_get_contents(path, &contents, &length, &gerr)) {
- error_setg(errp, "%s", gerr->message);
- g_error_free(gerr);
- g_free(path);
- return;
- }
- g_free(path);
- vdev->compat = contents;
- for (vdev->num_compat = 0; length; vdev->num_compat++) {
- size_t skip = strlen(contents) + 1;
- contents += skip;
- length -= skip;
- }
- }
-
- for (i = 0; i < vbasedev->num_regions; i++) {
- if (vfio_region_mmap(vdev->regions[i])) {
- warn_report("%s mmap unsupported, performance may be slow",
- memory_region_name(vdev->regions[i]->mem));
- }
- sysbus_init_mmio(sbdev, vdev->regions[i]->mem);
- }
- return;
-
-init_err:
- if (vdev->vbasedev.name) {
- error_prepend(errp, VFIO_MSG_PREFIX, vdev->vbasedev.name);
- } else {
- error_prepend(errp, "vfio error: ");
- }
-}
-
-static const VMStateDescription vfio_platform_vmstate = {
- .name = "vfio-platform",
- .unmigratable = 1,
-};
-
-static const Property vfio_platform_dev_properties[] = {
- DEFINE_PROP_STRING("host", VFIOPlatformDevice, vbasedev.name),
- DEFINE_PROP_STRING("sysfsdev", VFIOPlatformDevice, vbasedev.sysfsdev),
- DEFINE_PROP_BOOL("x-no-mmap", VFIOPlatformDevice, vbasedev.no_mmap, false),
- DEFINE_PROP_UINT32("mmap-timeout-ms", VFIOPlatformDevice,
- mmap_timeout, 1100),
- DEFINE_PROP_BOOL("x-irqfd", VFIOPlatformDevice, irqfd_allowed, true),
-#ifdef CONFIG_IOMMUFD
- DEFINE_PROP_LINK("iommufd", VFIOPlatformDevice, vbasedev.iommufd,
- TYPE_IOMMUFD_BACKEND, IOMMUFDBackend *),
-#endif
-};
-
-static void vfio_platform_instance_init(Object *obj)
-{
- VFIOPlatformDevice *vdev = VFIO_PLATFORM_DEVICE(obj);
- VFIODevice *vbasedev = &vdev->vbasedev;
-
- vfio_device_init(vbasedev, VFIO_DEVICE_TYPE_PLATFORM, &vfio_platform_ops,
- DEVICE(vdev), false);
-}
-
-#ifdef CONFIG_IOMMUFD
-static void vfio_platform_set_fd(Object *obj, const char *str, Error **errp)
-{
- vfio_device_set_fd(&VFIO_PLATFORM_DEVICE(obj)->vbasedev, str, errp);
-}
-#endif
-
-static void vfio_platform_class_init(ObjectClass *klass, const void *data)
-{
- DeviceClass *dc = DEVICE_CLASS(klass);
- SysBusDeviceClass *sbc = SYS_BUS_DEVICE_CLASS(klass);
-
- dc->realize = vfio_platform_realize;
- device_class_set_props(dc, vfio_platform_dev_properties);
-#ifdef CONFIG_IOMMUFD
- object_class_property_add_str(klass, "fd", NULL, vfio_platform_set_fd);
-#endif
- dc->vmsd = &vfio_platform_vmstate;
- dc->desc = "VFIO-based platform device assignment";
- sbc->connect_irq_notifier = vfio_start_irqfd_injection;
- set_bit(DEVICE_CATEGORY_MISC, dc->categories);
-
- object_class_property_set_description(klass, /* 2.4 */
- "host",
- "Host device name of assigned device");
- object_class_property_set_description(klass, /* 2.4 and 2.5 */
- "x-no-mmap",
- "Disable MMAP for device. Allows to trace MMIO "
- "accesses (DEBUG)");
- object_class_property_set_description(klass, /* 2.4 */
- "mmap-timeout-ms",
- "When EOI is not provided by KVM/QEMU, wait time "
- "(milliseconds) to re-enable device direct access "
- "after level interrupt (DEBUG)");
- object_class_property_set_description(klass, /* 2.4 */
- "x-irqfd",
- "Allow disabling irqfd support (DEBUG)");
- object_class_property_set_description(klass, /* 2.6 */
- "sysfsdev",
- "Host sysfs path of assigned device");
-#ifdef CONFIG_IOMMUFD
- object_class_property_set_description(klass, /* 9.0 */
- "iommufd",
- "Set host IOMMUFD backend device");
-#endif
-}
-
-static const TypeInfo vfio_platform_dev_info = {
- .name = TYPE_VFIO_PLATFORM,
- .parent = TYPE_DYNAMIC_SYS_BUS_DEVICE,
- .instance_size = sizeof(VFIOPlatformDevice),
- .instance_init = vfio_platform_instance_init,
- .class_init = vfio_platform_class_init,
- .class_size = sizeof(VFIOPlatformDeviceClass),
-};
-
-static void register_vfio_platform_dev_type(void)
-{
- type_register_static(&vfio_platform_dev_info);
-}
-
-type_init(register_vfio_platform_dev_type)
diff --git a/hw/vfio/spapr.c b/hw/vfio/spapr.c
index 564b70e..c41e458 100644
--- a/hw/vfio/spapr.c
+++ b/hw/vfio/spapr.c
@@ -62,7 +62,7 @@ static void vfio_prereg_listener_region_add(MemoryListener *listener,
VFIOSpaprContainer *scontainer = container_of(listener, VFIOSpaprContainer,
prereg_listener);
VFIOContainer *container = &scontainer->container;
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
const hwaddr gpa = section->offset_within_address_space;
hwaddr end;
int ret;
@@ -244,7 +244,7 @@ static bool vfio_spapr_create_window(VFIOContainer *container,
hwaddr *pgsize, Error **errp)
{
int ret = 0;
- VFIOContainerBase *bcontainer = &container->bcontainer;
+ VFIOContainerBase *bcontainer = VFIO_IOMMU(container);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
IOMMUMemoryRegion *iommu_mr = IOMMU_MEMORY_REGION(section->mr);
@@ -352,8 +352,7 @@ vfio_spapr_container_add_section_window(VFIOContainerBase *bcontainer,
MemoryRegionSection *section,
Error **errp)
{
- VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
VFIOHostDMAWindow *hostwin;
@@ -443,8 +442,7 @@ static void
vfio_spapr_container_del_section_window(VFIOContainerBase *bcontainer,
MemoryRegionSection *section)
{
- VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
@@ -465,8 +463,7 @@ vfio_spapr_container_del_section_window(VFIOContainerBase *bcontainer,
static void vfio_spapr_container_release(VFIOContainerBase *bcontainer)
{
- VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
VFIOHostDMAWindow *hostwin, *next;
@@ -484,8 +481,7 @@ static void vfio_spapr_container_release(VFIOContainerBase *bcontainer)
static bool vfio_spapr_container_setup(VFIOContainerBase *bcontainer,
Error **errp)
{
- VFIOContainer *container = container_of(bcontainer, VFIOContainer,
- bcontainer);
+ VFIOContainer *container = VFIO_IOMMU_LEGACY(bcontainer);
VFIOSpaprContainer *scontainer = container_of(container, VFIOSpaprContainer,
container);
struct vfio_iommu_spapr_tce_info info;
diff --git a/hw/vfio/trace-events b/hw/vfio/trace-events
index fc6ed23..e3d571f 100644
--- a/hw/vfio/trace-events
+++ b/hw/vfio/trace-events
@@ -127,17 +127,6 @@ vfio_region_unmap(const char *name, unsigned long offset, unsigned long end) "Re
vfio_region_sparse_mmap_header(const char *name, int index, int nr_areas) "Device %s region %d: %d sparse mmap entries"
vfio_region_sparse_mmap_entry(int i, unsigned long start, unsigned long end) "sparse entry %d [0x%lx - 0x%lx]"
-# platform.c
-vfio_platform_realize(char *name, char *compat) "vfio device %s, compat = %s"
-vfio_platform_eoi(int pin, int fd) "EOI IRQ pin %d (fd=%d)"
-vfio_platform_intp_mmap_enable(int pin) "IRQ #%d still active, stay in slow path"
-vfio_platform_intp_interrupt(int pin, int fd) "Inject IRQ #%d (fd = %d)"
-vfio_platform_intp_inject_pending_lockheld(int pin, int fd) "Inject pending IRQ #%d (fd = %d)"
-vfio_platform_populate_interrupts(int pin, int count, int flags) "- IRQ index %d: count %d, flags=0x%x"
-vfio_intp_interrupt_set_pending(int index) "irq %d is set PENDING"
-vfio_platform_start_level_irqfd_injection(int index, int fd, int resamplefd) "IRQ index=%d, fd = %d, resamplefd = %d"
-vfio_platform_start_edge_irqfd_injection(int index, int fd) "IRQ index=%d, fd = %d"
-
# spapr.c
vfio_prereg_listener_region_add_skip(uint64_t start, uint64_t end) "0x%"PRIx64" - 0x%"PRIx64
vfio_prereg_listener_region_del_skip(uint64_t start, uint64_t end) "0x%"PRIx64" - 0x%"PRIx64
diff --git a/include/hw/vfio/vfio-region.h b/hw/vfio/vfio-region.h
index ede6e0c..ede6e0c 100644
--- a/include/hw/vfio/vfio-region.h
+++ b/hw/vfio/vfio-region.h
diff --git a/include/hw/vfio/vfio-amd-xgbe.h b/include/hw/vfio/vfio-amd-xgbe.h
deleted file mode 100644
index a894546..0000000
--- a/include/hw/vfio/vfio-amd-xgbe.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * VFIO AMD XGBE device
- *
- * Copyright Linaro Limited, 2015
- *
- * Authors:
- * Eric Auger <eric.auger@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#ifndef HW_VFIO_VFIO_AMD_XGBE_H
-#define HW_VFIO_VFIO_AMD_XGBE_H
-
-#include "hw/vfio/vfio-platform.h"
-#include "qom/object.h"
-
-#define TYPE_VFIO_AMD_XGBE "vfio-amd-xgbe"
-
-/**
- * This device exposes:
- * - 5 MMIO regions: MAC, PCS, SerDes Rx/Tx regs,
- SerDes Integration Registers 1/2 & 2/2
- * - 2 level sensitive IRQs and optional DMA channel IRQs
- */
-struct VFIOAmdXgbeDevice {
- VFIOPlatformDevice vdev;
-};
-
-typedef struct VFIOAmdXgbeDevice VFIOAmdXgbeDevice;
-
-struct VFIOAmdXgbeDeviceClass {
- /*< private >*/
- VFIOPlatformDeviceClass parent_class;
- /*< public >*/
- DeviceRealize parent_realize;
-};
-
-typedef struct VFIOAmdXgbeDeviceClass VFIOAmdXgbeDeviceClass;
-
-DECLARE_OBJ_CHECKERS(VFIOAmdXgbeDevice, VFIOAmdXgbeDeviceClass,
- VFIO_AMD_XGBE_DEVICE, TYPE_VFIO_AMD_XGBE)
-
-#endif
diff --git a/include/hw/vfio/vfio-calxeda-xgmac.h b/include/hw/vfio/vfio-calxeda-xgmac.h
deleted file mode 100644
index 8482f15..0000000
--- a/include/hw/vfio/vfio-calxeda-xgmac.h
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * VFIO calxeda xgmac device
- *
- * Copyright Linaro Limited, 2014
- *
- * Authors:
- * Eric Auger <eric.auger@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- */
-
-#ifndef HW_VFIO_VFIO_CALXEDA_XGMAC_H
-#define HW_VFIO_VFIO_CALXEDA_XGMAC_H
-
-#include "hw/vfio/vfio-platform.h"
-#include "qom/object.h"
-
-#define TYPE_VFIO_CALXEDA_XGMAC "vfio-calxeda-xgmac"
-
-/**
- * This device exposes:
- * - a single MMIO region corresponding to its register space
- * - 3 IRQS (main and 2 power related IRQs)
- */
-struct VFIOCalxedaXgmacDevice {
- VFIOPlatformDevice vdev;
-};
-typedef struct VFIOCalxedaXgmacDevice VFIOCalxedaXgmacDevice;
-
-struct VFIOCalxedaXgmacDeviceClass {
- /*< private >*/
- VFIOPlatformDeviceClass parent_class;
- /*< public >*/
- DeviceRealize parent_realize;
-};
-typedef struct VFIOCalxedaXgmacDeviceClass VFIOCalxedaXgmacDeviceClass;
-
-DECLARE_OBJ_CHECKERS(VFIOCalxedaXgmacDevice, VFIOCalxedaXgmacDeviceClass,
- VFIO_CALXEDA_XGMAC_DEVICE, TYPE_VFIO_CALXEDA_XGMAC)
-
-#endif
diff --git a/include/hw/vfio/vfio-container-base.h b/include/hw/vfio/vfio-container-base.h
index bded6e9..acbd48a 100644
--- a/include/hw/vfio/vfio-container-base.h
+++ b/include/hw/vfio/vfio-container-base.h
@@ -33,8 +33,9 @@ typedef struct VFIOAddressSpace {
/*
* This is the base object for vfio container backends
*/
-typedef struct VFIOContainerBase {
- Object parent;
+struct VFIOContainerBase {
+ Object parent_obj;
+
VFIOAddressSpace *space;
MemoryListener listener;
Error *error;
@@ -51,7 +52,10 @@ typedef struct VFIOContainerBase {
QLIST_HEAD(, VFIODevice) device_list;
GList *iova_ranges;
NotifierWithReturn cpr_reboot_notifier;
-} VFIOContainerBase;
+};
+
+#define TYPE_VFIO_IOMMU "vfio-iommu"
+OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU)
typedef struct VFIOGuestIOMMU {
VFIOContainerBase *bcontainer;
@@ -105,14 +109,11 @@ vfio_container_get_page_size_mask(const VFIOContainerBase *bcontainer)
return bcontainer->pgsizes;
}
-#define TYPE_VFIO_IOMMU "vfio-iommu"
#define TYPE_VFIO_IOMMU_LEGACY TYPE_VFIO_IOMMU "-legacy"
#define TYPE_VFIO_IOMMU_SPAPR TYPE_VFIO_IOMMU "-spapr"
#define TYPE_VFIO_IOMMU_IOMMUFD TYPE_VFIO_IOMMU "-iommufd"
#define TYPE_VFIO_IOMMU_USER TYPE_VFIO_IOMMU "-user"
-OBJECT_DECLARE_TYPE(VFIOContainerBase, VFIOIOMMUClass, VFIO_IOMMU)
-
struct VFIOIOMMUClass {
ObjectClass parent_class;
diff --git a/include/hw/vfio/vfio-container.h b/include/hw/vfio/vfio-container.h
index 21e5807..240f566 100644
--- a/include/hw/vfio/vfio-container.h
+++ b/include/hw/vfio/vfio-container.h
@@ -25,13 +25,14 @@ typedef struct VFIOGroup {
bool ram_block_discard_allowed;
} VFIOGroup;
-typedef struct VFIOContainer {
- VFIOContainerBase bcontainer;
+struct VFIOContainer {
+ VFIOContainerBase parent_obj;
+
int fd; /* /dev/vfio/vfio, empowered by the attached groups */
unsigned iommu_type;
QLIST_HEAD(, VFIOGroup) group_list;
VFIOContainerCPR cpr;
-} VFIOContainer;
+};
OBJECT_DECLARE_SIMPLE_TYPE(VFIOContainer, VFIO_IOMMU_LEGACY);
diff --git a/include/hw/vfio/vfio-device.h b/include/hw/vfio/vfio-device.h
index 6e4d5cc..e7e6243 100644
--- a/include/hw/vfio/vfio-device.h
+++ b/include/hw/vfio/vfio-device.h
@@ -36,7 +36,7 @@
enum {
VFIO_DEVICE_TYPE_PCI = 0,
- VFIO_DEVICE_TYPE_PLATFORM = 1,
+ VFIO_DEVICE_TYPE_UNUSED = 1,
VFIO_DEVICE_TYPE_CCW = 2,
VFIO_DEVICE_TYPE_AP = 3,
};
diff --git a/include/hw/vfio/vfio-platform.h b/include/hw/vfio/vfio-platform.h
deleted file mode 100644
index 256d850..0000000
--- a/include/hw/vfio/vfio-platform.h
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * vfio based device assignment support - platform devices
- *
- * Copyright Linaro Limited, 2014
- *
- * Authors:
- * Kim Phillips <kim.phillips@linaro.org>
- *
- * This work is licensed under the terms of the GNU GPL, version 2. See
- * the COPYING file in the top-level directory.
- *
- * Based on vfio based PCI device assignment support:
- * Copyright Red Hat, Inc. 2012
- */
-
-#ifndef HW_VFIO_VFIO_PLATFORM_H
-#define HW_VFIO_VFIO_PLATFORM_H
-
-#include "hw/sysbus.h"
-#include "hw/vfio/vfio-device.h"
-#include "qemu/event_notifier.h"
-#include "qemu/queue.h"
-#include "qom/object.h"
-
-#define TYPE_VFIO_PLATFORM "vfio-platform"
-
-enum {
- VFIO_IRQ_INACTIVE = 0,
- VFIO_IRQ_PENDING = 1,
- VFIO_IRQ_ACTIVE = 2,
- /* VFIO_IRQ_ACTIVE_AND_PENDING cannot happen with VFIO */
-};
-
-typedef struct VFIOINTp {
- QLIST_ENTRY(VFIOINTp) next; /* entry for IRQ list */
- QSIMPLEQ_ENTRY(VFIOINTp) pqnext; /* entry for pending IRQ queue */
- EventNotifier *interrupt; /* eventfd triggered on interrupt */
- EventNotifier *unmask; /* eventfd for unmask on QEMU bypass */
- qemu_irq qemuirq;
- struct VFIOPlatformDevice *vdev; /* back pointer to device */
- int state; /* inactive, pending, active */
- uint8_t pin; /* index */
- uint32_t flags; /* IRQ info flags */
- bool kvm_accel; /* set when QEMU bypass through KVM enabled */
-} VFIOINTp;
-
-/* function type for user side eventfd handler */
-typedef void (*eventfd_user_side_handler_t)(VFIOINTp *intp);
-
-typedef struct VFIORegion VFIORegion;
-
-struct VFIOPlatformDevice {
- SysBusDevice sbdev;
- VFIODevice vbasedev; /* not a QOM object */
- VFIORegion **regions;
- QLIST_HEAD(, VFIOINTp) intp_list; /* list of IRQs */
- /* queue of pending IRQs */
- QSIMPLEQ_HEAD(, VFIOINTp) pending_intp_queue;
- char *compat; /* DT compatible values, separated by NUL */
- unsigned int num_compat; /* number of compatible values */
- uint32_t mmap_timeout; /* delay to re-enable mmaps after interrupt */
- QEMUTimer *mmap_timer; /* allows fast-path resume after IRQ hit */
- QemuMutex intp_mutex; /* protect the intp_list IRQ state */
- bool irqfd_allowed; /* debug option to force irqfd on/off */
-};
-typedef struct VFIOPlatformDevice VFIOPlatformDevice;
-
-struct VFIOPlatformDeviceClass {
- /*< private >*/
- SysBusDeviceClass parent_class;
- /*< public >*/
-};
-typedef struct VFIOPlatformDeviceClass VFIOPlatformDeviceClass;
-
-DECLARE_OBJ_CHECKERS(VFIOPlatformDevice, VFIOPlatformDeviceClass,
- VFIO_PLATFORM_DEVICE, TYPE_VFIO_PLATFORM)
-
-#endif /* HW_VFIO_VFIO_PLATFORM_H */