On Thu, Mar 10, 2016 at 02:15:53PM +0800, Chen Fan wrote:
> 
> On 03/10/2016 12:37 AM, Alex Williamson wrote:
> >On Mon, 7 Mar 2016 11:23:02 +0800
> >Cao jin <caoj.f...@cn.fujitsu.com> wrote:
> >
> >>From: Chen Fan <chen.fan.f...@cn.fujitsu.com>
> >>
> >>Signed-off-by: Chen Fan <chen.fan.f...@cn.fujitsu.com>
> >>---
> >>  hw/vfio/pci.c | 57 
> >> +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  hw/vfio/pci.h |  1 +
> >>  2 files changed, 58 insertions(+)
> >>
> >>diff --git a/hw/vfio/pci.c b/hw/vfio/pci.c
> >>index 24848c9..8e902d2 100644
> >>--- a/hw/vfio/pci.c
> >>+++ b/hw/vfio/pci.c
> >>@@ -1937,6 +1937,8 @@ static void vfio_check_host_bus_reset(VFIOPCIDevice 
> >>*vdev, Error **errp)
> >>      /* List all affected devices by bus reset */
> >>      devices = &info->devices[0];
> >>+    vdev->single_depend_dev = (info->count == 1);
> >>+
> >>      /* Verify that we have all the groups required */
> >>      for (i = 0; i < info->count; i++) {
> >>          PCIHostDeviceAddress host;
> >>@@ -2998,6 +3000,49 @@ static void vfio_exitfn(PCIDevice *pdev)
> >>      vfio_unregister_bars(vdev);
> >>  }
> >>+static VFIOPCIDevice *vfio_pci_get_do_reset_device(VFIOPCIDevice *vdev)
> >>+{
> >>+    struct vfio_pci_hot_reset_info *info = NULL;
> >>+    struct vfio_pci_dependent_device *devices;
> >>+    VFIOGroup *group;
> >>+    VFIODevice *vbasedev_iter;
> >>+    int ret;
> >>+
> >>+    ret = vfio_get_hot_reset_info(vdev, &info);
> >>+    if (ret) {
> >>+        error_report("vfio: Cannot enable AER for device %s,"
> >>+                     " device does not support hot reset.",
> >>+                     vdev->vbasedev.name);
> >>+        return NULL;
> >Isn't this path called for all devices, not just those trying to
> >support AER?
> >
> >>+    }
> >>+
> >>+    devices = &info->devices[0];
> >>+
> >>+    QLIST_FOREACH(group, &vfio_group_list, next) {
> >>+        if (group->groupid == devices[0].group_id) {
> >>+            break;
> >>+        }
> >>+    }
> >>+
> >>+    if (!group) {
> >>+        error_report("vfio: Cannot enable AER for device %s, "
> >>+                    "depends on group %d which is not owned.",
> >>+                    vdev->vbasedev.name, devices[0].group_id);
> >>+        return NULL;
> >Same here, we're not in an AER specific code path and we haven't even
> >tested if the device is trying to support AER.
> >
> >>+    }
> >>+
> >>+    QLIST_FOREACH(vbasedev_iter, &group->device_list, next) {
> >>+        if (vbasedev_iter->type != VFIO_DEVICE_TYPE_PCI ||
> >>+            !(vdev->features & VFIO_FEATURE_ENABLE_AER)) {
> >>+            continue;
> >>+        }
> >>+
> >>+        return container_of(vbasedev_iter, VFIOPCIDevice, vbasedev);
> >So the reset device is simply the first device in the group list, this
> >needs to be documented, but DMA isolation (grouping) and bus isolation
> >are separate things and we can have more than one group per bus...
> >often an IOMMU group is a single device, so have we really solved
> >anything here?  If the next device is on the same bus but in a separate
> >group, we're going to hot reset again, right?  Thanks,
> You are right, I recall my original idea was not something what like this.
> :)
> I tend to favor MST's ideas which said in V1 series patchset:
> "If the assumption that vfio functions are combined
> in the same way as on the host, then this is not needed:
> just reset when function 0 is reset."

If you do this, you can do your checks on realize, without
need for a separate validate callback.


> 
> so, seems we could implement this in next version.
> 1. requiring functions on same host bus must were assigned on the same
> virtual
>     bus. here we should not have a subordinate bus. because nowadays bridge
>     do not support pass through. so we can simply reset the vfio device with
> the
>     smallest devfn in a bus reset as long as one device has aer on the bus.
> 
>     with this, we don't need to care the groups isolation, because we only
> need the devices
>     by a bus hot reset, if the devices all on one virtual bus. reset anyone
> is sufficient.
> 
> 2. in order to identify the reset is from a normal reset or aer recovery
> reset, we could
>     add a flags in vfio device to mark the aer have occurred in
> err_notifier_handle, if
>     subsequent reset is coming with the is_bus_rst in parent bus is true. we
> can
>     directly do the hot reset.
> 
> Thanks,
> Chen
> 
> >
> >Alex
> >
> >>+    }
> >>+
> >>+    return NULL;
> >>+}
> >>+
> >>  static void vfio_pci_reset(DeviceState *dev)
> >>  {
> >>      PCIDevice *pdev = DO_UPCAST(PCIDevice, qdev, dev);
> >>@@ -3005,6 +3050,18 @@ static void vfio_pci_reset(DeviceState *dev)
> >>      trace_vfio_pci_reset(vdev->vbasedev.name);
> >>+    if (pdev->bus->in_hot_reset) {
> >>+        VFIOPCIDevice *tmp;
> >>+
> >>+        tmp = vfio_pci_get_do_reset_device(vdev);
> >>+        if (tmp) {
> >>+            if (tmp == vdev) {
> >>+                vfio_pci_hot_reset(vdev, vdev->single_depend_dev);
> >>+            }
> >>+            return;
> >>+        }
> >>+    }
> >>+
> >>      vfio_pci_pre_reset(vdev);
> >>      if (vdev->resetfn && !vdev->resetfn(vdev)) {
> >>diff --git a/hw/vfio/pci.h b/hw/vfio/pci.h
> >>index aff46c2..32bd31f 100644
> >>--- a/hw/vfio/pci.h
> >>+++ b/hw/vfio/pci.h
> >>@@ -143,6 +143,7 @@ typedef struct VFIOPCIDevice {
> >>      bool no_kvm_intx;
> >>      bool no_kvm_msi;
> >>      bool no_kvm_msix;
> >>+    bool single_depend_dev;
> >>  } VFIOPCIDevice;
> >>  uint32_t vfio_pci_read_config(PCIDevice *pdev, uint32_t addr, int len);
> >
> >
> >.
> >
> 
> 

Reply via email to