qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH v2] vhost: Warn if DEVIOTLB_UNMAP is not supported and ats is


From: Eric Auger
Subject: Re: [PATCH v2] vhost: Warn if DEVIOTLB_UNMAP is not supported and ats is set
Date: Thu, 20 Oct 2022 15:03:10 +0200
User-agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.11.0

Hi Jason,

On 10/20/22 05:58, Jason Wang wrote:
> On Wed, Oct 19, 2022 at 8:27 PM Eric Auger <eric.auger@redhat.com> wrote:
>> Since b68ba1ca5767 ("memory: Add IOMMU_NOTIFIER_DEVIOTLB_UNMAP
>> IOMMUTLBNotificationType"), vhost attempts to register DEVIOTLB_UNMAP
>> notifier. This latter is supported by the intel-iommu which supports
>> device-iotlb if the corresponding option is set. Then 958ec334bca3
>> ("vhost: Unbreak SMMU and virtio-iommu on dev-iotlb support") allowed
>> silent fallback to the legacy UNMAP notifier if the viommu does not
>> support device iotlb.
>>
>> Initially vhost/viommu integration was introduced with intel iommu
>> assuming ats=on was set on virtio-pci device and device-iotlb was set
>> on the intel iommu. vhost acts as an ATS capable device since it
>> implements an IOTLB on kernel side. However translated transactions
>> that hit the device IOTLB do not transit through the vIOMMU. So this
>> requires a limited ATS support on viommu side. Anyway this assumed
>> ATS was eventually enabled .
>>
>> But neither SMMUv3 nor virtio-iommu do support ATS and the integration
>> with vhost just relies on the fact those vIOMMU send UNMAP notifications
>> whenever the guest trigger them. This works without ATS being enabled.
>>
>> This patch makes sure we get a warning if ATS is set on a device
>> protected by virtio-iommu or vsmmuv3, reminding that we don't have
>> full support of ATS on those vIOMMUs and setting ats=on on the
>> virtio-pci end-point is not a requirement.
>>
>> Signed-off-by: Eric Auger <eric.auger@redhat.com>
>>
>> ---
>>
>> v1 -> v2:
>> - s/enabled/capable
>> - tweak the error message on vhost side
>> ---
>>  include/hw/virtio/virtio-bus.h |  3 +++
>>  hw/virtio/vhost.c              | 21 ++++++++++++++++++++-
>>  hw/virtio/virtio-bus.c         | 14 ++++++++++++++
>>  hw/virtio/virtio-pci.c         | 11 +++++++++++
>>  4 files changed, 48 insertions(+), 1 deletion(-)
>>
>> diff --git a/include/hw/virtio/virtio-bus.h b/include/hw/virtio/virtio-bus.h
>> index 7ab8c9dab0..23360a1daa 100644
>> --- a/include/hw/virtio/virtio-bus.h
>> +++ b/include/hw/virtio/virtio-bus.h
>> @@ -94,6 +94,7 @@ struct VirtioBusClass {
>>      bool has_variable_vring_alignment;
>>      AddressSpace *(*get_dma_as)(DeviceState *d);
>>      bool (*iommu_enabled)(DeviceState *d);
>> +    bool (*ats_capable)(DeviceState *d);
>>  };
>>
>>  struct VirtioBusState {
>> @@ -157,4 +158,6 @@ int virtio_bus_set_host_notifier(VirtioBusState *bus, 
>> int n, bool assign);
>>  void virtio_bus_cleanup_host_notifier(VirtioBusState *bus, int n);
>>  /* Whether the IOMMU is enabled for this device */
>>  bool virtio_bus_device_iommu_enabled(VirtIODevice *vdev);
>> +/* Whether ATS is enabled for this device */
>> +bool virtio_bus_device_ats_capable(VirtIODevice *vdev);
>>  #endif /* VIRTIO_BUS_H */
>> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
>> index 5185c15295..3cf9efce5e 100644
>> --- a/hw/virtio/vhost.c
>> +++ b/hw/virtio/vhost.c
>> @@ -324,6 +324,16 @@ static bool vhost_dev_has_iommu(struct vhost_dev *dev)
>>      }
>>  }
>>
>> +static bool vhost_dev_ats_capable(struct vhost_dev *dev)
> I suggest to rename this as pf_capable() since ATS is PCI specific but
> vhost isn't.
Does pf sound for page fault?
>
>> +{
>> +    VirtIODevice *vdev = dev->vdev;
>> +
>> +    if (vdev && virtio_bus_device_ats_capable(vdev)) {
>> +        return true;
>> +    }
>> +    return false;
>> +}
>> +
>>  static void *vhost_memory_map(struct vhost_dev *dev, hwaddr addr,
>>                                hwaddr *plen, bool is_write)
>>  {
>> @@ -737,6 +747,7 @@ static void vhost_iommu_region_add(MemoryListener 
>> *listener,
>>      Int128 end;
>>      int iommu_idx;
>>      IOMMUMemoryRegion *iommu_mr;
>> +    Error *err = NULL;
>>      int ret;
>>
>>      if (!memory_region_is_iommu(section->mr)) {
>> @@ -760,8 +771,16 @@ static void vhost_iommu_region_add(MemoryListener 
>> *listener,
>>      iommu->iommu_offset = section->offset_within_address_space -
>>                            section->offset_within_region;
>>      iommu->hdev = dev;
>> -    ret = memory_region_register_iommu_notifier(section->mr, &iommu->n, 
>> NULL);
>> +    ret = memory_region_register_iommu_notifier(section->mr, &iommu->n, 
>> &err);
>>      if (ret) {
>> +        if (vhost_dev_ats_capable(dev)) {
>> +            error_reportf_err(err,
>> +                              "%s: Although the device exposes ATS 
>> capability, "
>> +                              "fallback to legacy IOMMU UNMAP notifier: ",
>> +                              iommu_mr->parent_obj.name);
> I'm not sure if it's a real error, or I wonder what we need to do is
>
> 1) check is ATS is enabled
> 2) fallback to UNMAP is ATS is not enabled
Isn't the problem due to the fact that vhost, by construction, requires
"pf" (would it be though DEVIOTLB_UNMAP or UNMAP). Don't UNMAP
notifications also implement part of ATS protocol? I guess this is the
reason why you mandated ats in the first place.

So if ATS is not enabled, shouldn't we fallback to virtio instead of vhost?

Thanks

Eric
>
>> +        } else {
>> +            error_free(err);
>> +        }
>>          /*
>>           * Some vIOMMUs do not support dev-iotlb yet.  If so, try to use the
>>           * UNMAP legacy message
>> diff --git a/hw/virtio/virtio-bus.c b/hw/virtio/virtio-bus.c
>> index 896feb37a1..d46c3f8ec4 100644
>> --- a/hw/virtio/virtio-bus.c
>> +++ b/hw/virtio/virtio-bus.c
>> @@ -348,6 +348,20 @@ bool virtio_bus_device_iommu_enabled(VirtIODevice *vdev)
>>      return klass->iommu_enabled(qbus->parent);
>>  }
>>
>> +bool virtio_bus_device_ats_capable(VirtIODevice *vdev)
>> +{
>> +    DeviceState *qdev = DEVICE(vdev);
>> +    BusState *qbus = BUS(qdev_get_parent_bus(qdev));
>> +    VirtioBusState *bus = VIRTIO_BUS(qbus);
>> +    VirtioBusClass *klass = VIRTIO_BUS_GET_CLASS(bus);
>> +
>> +    if (!klass->ats_capable) {
>> +        return false;
> I think it's better to check whether or not ATS is enabled. Guest may
> choose to not enable ATS for various reasons.
>
> Thanks
>
>> +    }
>> +
>> +    return klass->ats_capable(qbus->parent);
>> +}
>> +
>>  static void virtio_bus_class_init(ObjectClass *klass, void *data)
>>  {
>>      BusClass *bus_class = BUS_CLASS(klass);
>> diff --git a/hw/virtio/virtio-pci.c b/hw/virtio/virtio-pci.c
>> index e7d80242b7..c2ceba98a6 100644
>> --- a/hw/virtio/virtio-pci.c
>> +++ b/hw/virtio/virtio-pci.c
>> @@ -1141,6 +1141,16 @@ static bool virtio_pci_iommu_enabled(DeviceState *d)
>>      return true;
>>  }
>>
>> +static bool virtio_pci_ats_capable(DeviceState *d)
>> +{
>> +    VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
>> +
>> +    if (proxy->flags & VIRTIO_PCI_FLAG_ATS) {
>> +        return true;
>> +    }
>> +    return false;
>> +}
>> +
>>  static bool virtio_pci_queue_enabled(DeviceState *d, int n)
>>  {
>>      VirtIOPCIProxy *proxy = VIRTIO_PCI(d);
>> @@ -2229,6 +2239,7 @@ static void virtio_pci_bus_class_init(ObjectClass 
>> *klass, void *data)
>>      k->ioeventfd_assign = virtio_pci_ioeventfd_assign;
>>      k->get_dma_as = virtio_pci_get_dma_as;
>>      k->iommu_enabled = virtio_pci_iommu_enabled;
>> +    k->ats_capable = virtio_pci_ats_capable;
>>      k->queue_enabled = virtio_pci_queue_enabled;
>>  }
>>
>> --
>> 2.35.3
>>




reply via email to

[Prev in Thread] Current Thread [Next in Thread]