From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:48039) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z2QzY-00016X-KF for qemu-devel@nongnu.org; Tue, 09 Jun 2015 17:23:29 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1Z2QzX-00016w-2u for qemu-devel@nongnu.org; Tue, 09 Jun 2015 17:23:28 -0400 Received: from mx1.redhat.com ([209.132.183.28]:39699) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1Z2QzW-00016s-Rb for qemu-devel@nongnu.org; Tue, 09 Jun 2015 17:23:27 -0400 Message-ID: <1433885005.4927.145.camel@redhat.com> From: Alex Williamson Date: Tue, 09 Jun 2015 15:23:25 -0600 In-Reply-To: <0b09272e0161da6e3021633e4db6d0751b846246.1433812962.git.chen.fan.fnst@cn.fujitsu.com> References: <0b09272e0161da6e3021633e4db6d0751b846246.1433812962.git.chen.fan.fnst@cn.fujitsu.com> Content-Type: text/plain; charset="UTF-8" Mime-Version: 1.0 Content-Transfer-Encoding: 7bit Subject: Re: [Qemu-devel] [RFC v9 11/18] vfio: add check host bus reset is support or not List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: Chen Fan Cc: izumi.taku@jp.fujitsu.com, qemu-devel@nongnu.org On Tue, 2015-06-09 at 11:37 +0800, Chen Fan wrote: > we introduce a has_bus_reset capability to sign the vfio > devices if support host bus reset. Old description, no sign of has_bus_reset here. > > Signed-off-by: Chen Fan > --- > hw/vfio/pci.c | 169 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ > 1 file changed, 169 insertions(+) > > diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c > index 06006ce..97af143 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" > @@ -2921,6 +2922,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) { I don't think these last two are necessary, these are internal differentiation of the reset mechanism used, not separate reset mechanisms. We don't require FLR and 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) > { > @@ -2963,6 +3127,11 @@ static int vfio_setup_aer(VFIOPCIDevice *vdev, uint8_t cap_ver, > goto error; > } > > + /* Make sure this devices does conflict the existing aer topology */ > + if (vfio_check_devices_host_bus_reset()) { > + goto error; > + } > + > errcap = vfio_pci_read_config(pdev, pdev->exp.aer_cap + PCI_ERR_CAP, 4); > /* > * The ability to record multiple headers is depending on