[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [RFC v10 12/19] vfio: add check host bus reset is support o
From: |
Chen Fan |
Subject: |
[Qemu-devel] [RFC v10 12/19] vfio: add check host bus reset is support or not |
Date: |
Tue, 16 Jun 2015 16:10:56 +0800 |
when init vfio device, we should test all the devices supported
aer whether conflict with others. For each one, get the hot reset
info for the affected device list. For each affected device, if
it's attached to the VM, it needs to be on or below the bus of
the target device. also, we should test all of the non-AER supporting
vfio-pci devices on or below the target bus to verify they have a reset
mechanism.
Signed-off-by: Chen Fan <address@hidden>
---
hw/vfio/pci.c | 170 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 170 insertions(+)
diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
index ade3196..53fb544 100644
--- a/hw/vfio/pci.c
+++ b/hw/vfio/pci.c
@@ -32,6 +32,7 @@
#include "hw/pci/msi.h"
#include "hw/pci/msix.h"
#include "hw/pci/pci.h"
+#include "hw/pci/pci_bus.h"
#include "hw/pci/pci_bridge.h"
#include "qemu-common.h"
#include "qemu/error-report.h"
@@ -2929,6 +2930,169 @@ out:
return ret;
}
+struct VFIODeviceFind {
+ PCIDevice *pdev;
+ bool found;
+};
+
+static void find_devices(PCIBus *bus, void *opaque)
+{
+ struct VFIODeviceFind *find = opaque;
+ int i;
+
+ if (find->found) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bus->devices); i++) {
+ if (!bus->devices[i]) {
+ continue;
+ }
+
+ if (bus->devices[i] == find->pdev) {
+ find->found = true;
+ break;
+ }
+ }
+}
+
+static void vfio_check_device_reset(PCIBus *bus, void *opaque)
+{
+ int i;
+ PCIDevice *dev;
+ VFIOPCIDevice *vdev;
+ struct VFIODeviceFind *find = opaque;
+
+ if (find->found) {
+ return;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(bus->devices); i++) {
+ if (!bus->devices[i]) {
+ continue;
+ }
+ dev = bus->devices[i];
+ if (!object_dynamic_cast(OBJECT(dev), "vfio-pci")) {
+ continue;
+ }
+ vdev = DO_UPCAST(VFIOPCIDevice, pdev, dev);
+ if (!(vdev->features & VFIO_FEATURE_ENABLE_AER) &&
+ !vdev->vbasedev.reset_works &&
+ !vdev->has_flr &&
+ !vdev->has_pm_reset) {
+ find->pdev = dev;
+ find->found = true;
+ break;
+ }
+ }
+}
+
+static int vfio_check_host_bus_reset(VFIOPCIDevice *vdev)
+{
+ PCIBus *bus = vdev->pdev.bus;
+ struct vfio_pci_hot_reset_info *info = NULL;
+ struct vfio_pci_dependent_device *devices;
+ VFIOGroup *group;
+ int ret, i;
+ struct VFIODeviceFind find;
+
+ ret = vfio_get_hot_reset_info(vdev, &info);
+ if (ret) {
+ goto out;
+ }
+
+ /* List all affected devices by bus reset */
+ devices = &info->devices[0];
+
+ /* Verify that we have all the groups required */
+ for (i = 0; i < info->count; i++) {
+ PCIHostDeviceAddress host;
+ VFIOPCIDevice *tmp;
+ VFIODevice *vbasedev_iter;
+
+ host.domain = devices[i].segment;
+ host.bus = devices[i].bus;
+ host.slot = PCI_SLOT(devices[i].devfn);
+ host.function = PCI_FUNC(devices[i].devfn);
+
+ /* Skip the current device */
+ if (vfio_pci_host_match(&host, &vdev->host)) {
+ continue;
+ }
+
+ /* Ensure we own the group of the affected device */
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ if (group->groupid == devices[i].group_id) {
+ break;
+ }
+ }
+
+ if (!group) {
+ ret = -1;
+ goto out;
+ }
+
+ /* Ensure affected devices for reset under the same bus */
+ QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
+ if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI) {
+ continue;
+ }
+ tmp = container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
+ if (vfio_pci_host_match(&host, &tmp->host)) {
+ find.pdev = &tmp->pdev;
+ find.found = false;
+
+ pci_for_each_bus(bus, find_devices, &find);
+ if (!find.found) {
+ ret = -1;
+ goto out;
+ }
+ break;
+ }
+ }
+ }
+
+ /*
+ * Check the all vfio pci devices on or below the target bus
+ * have a reset mechanism at least.
+ */
+ find.pdev = NULL;
+ find.found = false;
+ pci_for_each_bus(bus, vfio_check_device_reset, &find);
+ if (find.found) {
+ ret = -1;
+ goto out;
+ }
+
+ ret = 0;
+out:
+ g_free(info);
+ return ret;
+}
+
+static int vfio_check_devices_host_bus_reset(void)
+{
+ VFIOGroup *group;
+ VFIODevice *vbasedev;
+ VFIOPCIDevice *vdev;
+
+ /* Check All vfio-pci devices if have bus reset capability */
+ QLIST_FOREACH(group, &vfio_group_list, next) {
+ QLIST_FOREACH(vbasedev, &group->device_list, next) {
+ vdev = container_of(vbasedev, VFIOPCIDevice, vbasedev);
+ if ((vdev->features & VFIO_FEATURE_ENABLE_AER) &&
+ vfio_check_host_bus_reset(vdev)) {
+ error_report("vfio: Cannot enable AER for device %s, "
+ "which does not support host bus reset.",
+ vdev->vbasedev.name);
+ return -1;
+ }
+ }
+ }
+
+ return 0;
+}
+
static int vfio_setup_aer(VFIOPCIDevice *vdev, uint8_t cap_ver,
int pos, uint16_t size)
{
@@ -2971,6 +3135,12 @@ static int vfio_setup_aer(VFIOPCIDevice *vdev, uint8_t
cap_ver,
return ret;
}
+ /* Make sure this devices does conflict the existing aer topology */
+ ret = vfio_check_devices_host_bus_reset();
+ if (ret) {
+ return ret;
+ }
+
errcap = vfio_pci_read_config(pdev, pdev->exp.aer_cap + PCI_ERR_CAP, 4);
/*
* The ability to record multiple headers is depending on
--
1.9.3
- Re: [Qemu-devel] [RFC v10 03/19] pcie: modify the capability size assert, (continued)
- [Qemu-devel] [RFC v10 02/19] vfio: squeeze out vfio_pci_do_hot_reset for support bus reset, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 04/19] vfio: make the 4 bytes aligned for capability size, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 06/19] aer: impove pcie_aer_init to support vfio device, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 08/19] vfio: add ref for group to support own affected groups, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 05/19] vfio: add pcie extanded capability support, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 10/19] vfio: improve vfio_get_group to support adding as is NULL., Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 07/19] vfio: add aer support for vfio device, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 09/19] vfio: extract vfio_register_container_listener from vfio_connect_container, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 11/19] get all affected groups for each device support aer, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 12/19] vfio: add check host bus reset is support or not,
Chen Fan <=
- [Qemu-devel] [RFC v10 14/19] vfio: add sec_bus_reset notifier to notify physical bus reset is needed, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 15/19] vfio: improve vfio_pci_hot_reset to support more case, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 16/19] vfio: do hot bus reset when do virtual secondary bus reset, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 17/19] pcie_aer: expose pcie_aer_msg() interface, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 18/19] vfio-pci: pass the aer error to guest, Chen Fan, 2015/06/16
- [Qemu-devel] [RFC v10 13/19] pci: add bus reset_notifiers callbacks for host bus reset, Chen Fan, 2015/06/16