qemu-devel
[Top][All Lists]
Advanced

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

Re: [Qemu-devel] [PATCH V4 10/10] vhost_net: device IOTLB support


From: Michael S. Tsirkin
Subject: Re: [Qemu-devel] [PATCH V4 10/10] vhost_net: device IOTLB support
Date: Tue, 10 Jan 2017 06:55:14 +0200

On Fri, Dec 30, 2016 at 06:09:19PM +0800, Jason Wang wrote:
> This patches implements Device IOTLB support for vhost kernel. This is
> done through:
> 
> 1) switch to use dma helpers when map/unmap vrings from vhost codes
> 2) introduce a set of VhostOps to:
>    - setting up device IOTLB request callback
>    - processing device IOTLB request
>    - processing device IOTLB invalidation
> 2) kernel support for Device IOTLB API:
> 
> - allow vhost-net to query the IOMMU IOTLB entry through eventfd
> - enable the ability for qemu to update a specified mapping of vhost
> - through ioctl.
> - enable the ability to invalidate a specified range of iova for the
>   device IOTLB of vhost through ioctl. In x86/intel_iommu case this is
>   triggered through iommu memory region notifier from device IOTLB
>   invalidation descriptor processing routine.
> 
> With all the above, kernel vhost_net can co-operate with userspace
> IOMMU. For vhost-user, the support could be easily done on top by
> implementing the VhostOps.
> 
> Cc: Michael S. Tsirkin <address@hidden>
> Signed-off-by: Jason Wang <address@hidden>

Specifically this patch is the one causing issues.


> ---
>  hw/virtio/vhost-backend.c         |  99 +++++++++++++++++++++
>  hw/virtio/vhost.c                 | 178 
> +++++++++++++++++++++++++++++++++-----
>  include/hw/virtio/vhost-backend.h |  13 +++
>  include/hw/virtio/vhost.h         |   4 +
>  net/tap.c                         |   1 +
>  5 files changed, 273 insertions(+), 22 deletions(-)
> 
> diff --git a/hw/virtio/vhost-backend.c b/hw/virtio/vhost-backend.c
> index 272a5ec..be927b8 100644
> --- a/hw/virtio/vhost-backend.c
> +++ b/hw/virtio/vhost-backend.c
> @@ -185,6 +185,102 @@ static int vhost_kernel_vsock_set_running(struct 
> vhost_dev *dev, int start)
>  }
>  #endif /* CONFIG_VHOST_VSOCK */
>  
> +static void vhost_kernel_iotlb_read(void *opaque)
> +{
> +    struct vhost_dev *dev = opaque;
> +    struct vhost_msg msg;
> +    ssize_t len;
> +
> +    while ((len = read((uintptr_t)dev->opaque, &msg, sizeof msg)) > 0) {
> +        struct vhost_iotlb_msg *imsg = &msg.iotlb;
> +        if (len < sizeof msg) {
> +            error_report("Wrong vhost message len: %d", (int)len);
> +            break;
> +        }
> +        if (msg.type != VHOST_IOTLB_MSG) {
> +            error_report("Unknown vhost iotlb message type");
> +            break;
> +        }
> +        switch (imsg->type) {
> +        case VHOST_IOTLB_MISS:
> +            vhost_device_iotlb_miss(dev, imsg->iova,
> +                                    imsg->perm != VHOST_ACCESS_RO);
> +            break;
> +        case VHOST_IOTLB_UPDATE:
> +        case VHOST_IOTLB_INVALIDATE:
> +            error_report("Unexpected IOTLB message type");
> +            break;
> +        case VHOST_IOTLB_ACCESS_FAIL:
> +            /* FIXME: report device iotlb error */
> +            break;
> +        default:
> +            break;
> +        }
> +    }
> +}
> +
> +static int vhost_kernel_update_device_iotlb(struct vhost_dev *dev,
> +                                            uint64_t iova, uint64_t uaddr,
> +                                            uint64_t len,
> +                                            IOMMUAccessFlags perm)
> +{
> +    struct vhost_msg msg;
> +    msg.type = VHOST_IOTLB_MSG;
> +    msg.iotlb.iova =  iova;
> +    msg.iotlb.uaddr = uaddr;
> +    msg.iotlb.size = len;
> +    msg.iotlb.type = VHOST_IOTLB_UPDATE;
> +
> +    switch (perm) {
> +    case IOMMU_RO:
> +        msg.iotlb.perm = VHOST_ACCESS_RO;
> +        break;
> +    case IOMMU_WO:
> +        msg.iotlb.perm = VHOST_ACCESS_WO;
> +        break;
> +    case IOMMU_RW:
> +        msg.iotlb.perm = VHOST_ACCESS_RW;
> +        break;
> +    default:
> +        g_assert_not_reached();
> +    }
> +
> +    if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
> +        error_report("Fail to update device iotlb");
> +        return -EFAULT;
> +    }
> +
> +    return 0;
> +}
> +
> +static int vhost_kernel_invalidate_device_iotlb(struct vhost_dev *dev,
> +                                                uint64_t iova, uint64_t len)
> +{
> +    struct vhost_msg msg;
> +
> +    msg.type = VHOST_IOTLB_MSG;
> +    msg.iotlb.iova = iova;
> +    msg.iotlb.size = len;
> +    msg.iotlb.type = VHOST_IOTLB_INVALIDATE;
> +
> +    if (write((uintptr_t)dev->opaque, &msg, sizeof msg) != sizeof msg) {
> +        error_report("Fail to invalidate device iotlb");
> +        return -EFAULT;
> +    }
> +
> +    return 0;
> +}
> +
> +static void vhost_kernel_set_iotlb_callback(struct vhost_dev *dev,
> +                                           int enabled)
> +{
> +    if (enabled)
> +        qemu_set_fd_handler((uintptr_t)dev->opaque,
> +                            vhost_kernel_iotlb_read, NULL, dev);
> +    else
> +        qemu_set_fd_handler((uintptr_t)dev->opaque, NULL, NULL, NULL);
> +}
> +
>  static const VhostOps kernel_ops = {
>          .backend_type = VHOST_BACKEND_TYPE_KERNEL,
>          .vhost_backend_init = vhost_kernel_init,
> @@ -214,6 +310,9 @@ static const VhostOps kernel_ops = {
>          .vhost_vsock_set_guest_cid = vhost_kernel_vsock_set_guest_cid,
>          .vhost_vsock_set_running = vhost_kernel_vsock_set_running,
>  #endif /* CONFIG_VHOST_VSOCK */
> +        .vhost_set_iotlb_callback = vhost_kernel_set_iotlb_callback,
> +        .vhost_update_device_iotlb = vhost_kernel_update_device_iotlb,
> +        .vhost_invalidate_device_iotlb = 
> vhost_kernel_invalidate_device_iotlb,
>  };
>  
>  int vhost_set_backend_type(struct vhost_dev *dev, VhostBackendType 
> backend_type)
> diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
> index f7f7023..461acef 100644
> --- a/hw/virtio/vhost.c
> +++ b/hw/virtio/vhost.c
> @@ -26,6 +26,7 @@
>  #include "hw/virtio/virtio-bus.h"
>  #include "hw/virtio/virtio-access.h"
>  #include "migration/migration.h"
> +#include "sysemu/dma.h"
>  
>  /* enabled until disconnected backend stabilizes */
>  #define _VHOST_DEBUG 1
> @@ -421,8 +422,35 @@ static inline void vhost_dev_log_resize(struct vhost_dev 
> *dev, uint64_t size)
>      dev->log_size = size;
>  }
>  
> +static void *vhost_memory_map(VirtIODevice *vdev, hwaddr addr,
> +                              hwaddr *plen, int is_write)
> +{
> +    AddressSpace *dma_as = vdev->dma_as;
> +
> +    if (!memory_region_is_iommu(dma_as->root)) {
> +        return dma_memory_map(dma_as, addr, plen, is_write ?
> +                              DMA_DIRECTION_FROM_DEVICE :
> +                              DMA_DIRECTION_TO_DEVICE);
> +    } else {
> +        return (void *)(uintptr_t)addr;
> +    }
> +}
> +
> +static void vhost_memory_unmap(VirtIODevice *vdev, void *buffer,
> +                               hwaddr len, int is_write,
> +                               hwaddr access_len)
> +{
> +    AddressSpace *dma_as = vdev->dma_as;
>  
> -static int vhost_verify_ring_part_mapping(void *part,
> +    if (!memory_region_is_iommu(dma_as->root)) {
> +        dma_memory_unmap(dma_as, buffer, len, is_write ?
> +                         DMA_DIRECTION_FROM_DEVICE : DMA_DIRECTION_TO_DEVICE,
> +                         access_len);
> +    }
> +}
> +
> +static int vhost_verify_ring_part_mapping(struct vhost_dev *dev,
> +                                          void *part,
>                                            uint64_t part_addr,
>                                            uint64_t part_size,
>                                            uint64_t start_addr,
> @@ -436,14 +464,14 @@ static int vhost_verify_ring_part_mapping(void *part,
>          return 0;
>      }
>      l = part_size;
> -    p = cpu_physical_memory_map(part_addr, &l, 1);
> +    p = vhost_memory_map(dev->vdev, part_addr, &l, 1);
>      if (!p || l != part_size) {
>          r = -ENOMEM;
>      }
>      if (p != part) {
>          r = -EBUSY;
>      }
> -    cpu_physical_memory_unmap(p, l, 0, 0);
> +    vhost_memory_unmap(dev->vdev, p, l, 0, 0);
>      return r;
>  }
>  
> @@ -463,21 +491,21 @@ static int vhost_verify_ring_mappings(struct vhost_dev 
> *dev,
>          struct vhost_virtqueue *vq = dev->vqs + i;
>  
>          j = 0;
> -        r = vhost_verify_ring_part_mapping(vq->desc, vq->desc_phys,
> +        r = vhost_verify_ring_part_mapping(dev, vq->desc, vq->desc_phys,
>                                             vq->desc_size, start_addr, size);
>          if (!r) {
>              break;
>          }
>  
>          j++;
> -        r = vhost_verify_ring_part_mapping(vq->avail, vq->avail_phys,
> +        r = vhost_verify_ring_part_mapping(dev, vq->avail, vq->avail_phys,
>                                             vq->avail_size, start_addr, size);
>          if (!r) {
>              break;
>          }
>  
>          j++;
> -        r = vhost_verify_ring_part_mapping(vq->used, vq->used_phys,
> +        r = vhost_verify_ring_part_mapping(dev, vq->used, vq->used_phys,
>                                             vq->used_size, start_addr, size);
>          if (!r) {
>              break;
> @@ -715,13 +743,27 @@ static int vhost_virtqueue_set_addr(struct vhost_dev 
> *dev,
>      return 0;
>  }
>  
> -static int vhost_dev_set_features(struct vhost_dev *dev, bool enable_log)
> +static int vhost_dev_has_iommu(struct vhost_dev *dev)
> +{
> +    VirtIODevice *vdev = dev->vdev;
> +    AddressSpace *dma_as = vdev->dma_as;
> +
> +    return memory_region_is_iommu(dma_as->root) &&
> +           virtio_host_has_feature(vdev, VIRTIO_F_IOMMU_PLATFORM);
> +}
> +
> +static int vhost_dev_set_features(struct vhost_dev *dev,
> +                                  bool enable_log)
>  {
>      uint64_t features = dev->acked_features;
> +    bool has_iommu = vhost_dev_has_iommu(dev);
>      int r;
>      if (enable_log) {
>          features |= 0x1ULL << VHOST_F_LOG_ALL;
>      }
> +    if (has_iommu) {
> +        features |= 0x1ULL << VIRTIO_F_IOMMU_PLATFORM;
> +    }
>      r = dev->vhost_ops->vhost_set_features(dev, features);
>      if (r < 0) {
>          VHOST_OPS_DEBUG("vhost_set_features failed");
> @@ -858,6 +900,56 @@ static int 
> vhost_virtqueue_set_vring_endian_legacy(struct vhost_dev *dev,
>      return -errno;
>  }
>  
> +static int vhost_memory_region_lookup(struct vhost_dev *hdev,
> +                                      uint64_t gpa, uint64_t *uaddr,
> +                                      uint64_t *len)
> +{
> +    int i;
> +
> +    for (i = 0; i < hdev->mem->nregions; i++) {
> +        struct vhost_memory_region *reg = hdev->mem->regions + i;
> +
> +        if (gpa >= reg->guest_phys_addr &&
> +            reg->guest_phys_addr + reg->memory_size > gpa) {
> +            *uaddr = reg->userspace_addr + gpa - reg->guest_phys_addr;
> +            *len = reg->guest_phys_addr + reg->memory_size - gpa;
> +            return 0;
> +        }
> +    }
> +
> +    return -EFAULT;
> +}
> +
> +void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int write)
> +{
> +    IOMMUTLBEntry iotlb;
> +    uint64_t uaddr, len;
> +
> +    rcu_read_lock();
> +
> +    iotlb = address_space_get_iotlb_entry(dev->vdev->dma_as,
> +                                          iova, write);
> +    if (iotlb.target_as != NULL) {
> +        if (vhost_memory_region_lookup(dev, iotlb.translated_addr,
> +                                       &uaddr, &len)) {
> +            error_report("Fail to lookup the translated address "
> +                         "%"PRIx64, iotlb.translated_addr);
> +            goto out;
> +        }
> +
> +        len = MIN(iotlb.addr_mask + 1, len);
> +        iova = iova & ~iotlb.addr_mask;
> +
> +        if (dev->vhost_ops->vhost_update_device_iotlb(dev, iova, uaddr,
> +                                                      len, iotlb.perm)) {
> +            error_report("Fail to update device iotlb");
> +            goto out;
> +        }
> +    }
> +out:
> +    rcu_read_unlock();
> +}
> +
>  static int vhost_virtqueue_start(struct vhost_dev *dev,
>                                  struct VirtIODevice *vdev,
>                                  struct vhost_virtqueue *vq,
> @@ -903,21 +995,21 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
>  
>      vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx);
>      vq->desc_phys = a = virtio_queue_get_desc_addr(vdev, idx);
> -    vq->desc = cpu_physical_memory_map(a, &l, 0);
> +    vq->desc = vhost_memory_map(vdev, a, &l, 0);
>      if (!vq->desc || l != s) {
>          r = -ENOMEM;
>          goto fail_alloc_desc;
>      }
>      vq->avail_size = s = l = virtio_queue_get_avail_size(vdev, idx);
>      vq->avail_phys = a = virtio_queue_get_avail_addr(vdev, idx);
> -    vq->avail = cpu_physical_memory_map(a, &l, 0);
> +    vq->avail = vhost_memory_map(vdev, a, &l, 0);
>      if (!vq->avail || l != s) {
>          r = -ENOMEM;
>          goto fail_alloc_avail;
>      }
>      vq->used_size = s = l = virtio_queue_get_used_size(vdev, idx);
>      vq->used_phys = a = virtio_queue_get_used_addr(vdev, idx);
> -    vq->used = cpu_physical_memory_map(a, &l, 1);
> +    vq->used = vhost_memory_map(vdev, a, &l, 1);
>      if (!vq->used || l != s) {
>          r = -ENOMEM;
>          goto fail_alloc_used;
> @@ -963,14 +1055,14 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
>  fail_vector:
>  fail_kick:
>  fail_alloc:
> -    cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, 
> idx),
> -                              0, 0);
> +    vhost_memory_unmap(vdev, vq->used, virtio_queue_get_used_size(vdev, idx),
> +                       0, 0);
>  fail_alloc_used:
> -    cpu_physical_memory_unmap(vq->avail, virtio_queue_get_avail_size(vdev, 
> idx),
> -                              0, 0);
> +    vhost_memory_unmap(vdev, vq->avail, virtio_queue_get_avail_size(vdev, 
> idx),
> +                       0, 0);
>  fail_alloc_avail:
> -    cpu_physical_memory_unmap(vq->desc, virtio_queue_get_desc_size(vdev, 
> idx),
> -                              0, 0);
> +    vhost_memory_unmap(vdev, vq->desc, virtio_queue_get_desc_size(vdev, idx),
> +                       0, 0);
>  fail_alloc_desc:
>      return r;
>  }
> @@ -1003,12 +1095,12 @@ static void vhost_virtqueue_stop(struct vhost_dev 
> *dev,
>                                                  vhost_vq_index);
>      }
>  
> -    cpu_physical_memory_unmap(vq->used, virtio_queue_get_used_size(vdev, 
> idx),
> -                              1, virtio_queue_get_used_size(vdev, idx));
> -    cpu_physical_memory_unmap(vq->avail, virtio_queue_get_avail_size(vdev, 
> idx),
> -                              0, virtio_queue_get_avail_size(vdev, idx));
> -    cpu_physical_memory_unmap(vq->desc, virtio_queue_get_desc_size(vdev, 
> idx),
> -                              0, virtio_queue_get_desc_size(vdev, idx));
> +    vhost_memory_unmap(vdev, vq->used, virtio_queue_get_used_size(vdev, idx),
> +                       1, virtio_queue_get_used_size(vdev, idx));
> +    vhost_memory_unmap(vdev, vq->avail, virtio_queue_get_avail_size(vdev, 
> idx),
> +                       0, virtio_queue_get_avail_size(vdev, idx));
> +    vhost_memory_unmap(vdev, vq->desc, virtio_queue_get_desc_size(vdev, idx),
> +                       0, virtio_queue_get_desc_size(vdev, idx));
>  }
>  
>  static void vhost_eventfd_add(MemoryListener *listener,
> @@ -1065,6 +1157,9 @@ static int vhost_virtqueue_init(struct vhost_dev *dev,
>          r = -errno;
>          goto fail_call;
>      }
> +
> +    vq->dev = dev;
> +
>      return 0;
>  fail_call:
>      event_notifier_cleanup(&vq->masked_notifier);
> @@ -1076,12 +1171,24 @@ static void vhost_virtqueue_cleanup(struct 
> vhost_virtqueue *vq)
>      event_notifier_cleanup(&vq->masked_notifier);
>  }
>  
> +static void vhost_iommu_unmap_notify(IOMMUNotifier *n, IOMMUTLBEntry *iotlb)
> +{
> +    struct vhost_dev *hdev = container_of(n, struct vhost_dev, n);
> +
> +    if (hdev->vhost_ops->vhost_invalidate_device_iotlb(hdev,
> +                                                       iotlb->iova,
> +                                                       iotlb->addr_mask + 
> 1)) {
> +        error_report("Fail to invalidate device iotlb");
> +    }
> +}
> +
>  int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
>                     VhostBackendType backend_type, uint32_t busyloop_timeout)
>  {
>      uint64_t features;
>      int i, r, n_initialized_vqs = 0;
>  
> +    hdev->vdev = NULL;
>      hdev->migration_blocker = NULL;
>  
>      r = vhost_set_backend_type(hdev, backend_type);
> @@ -1146,6 +1253,9 @@ int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
>          .priority = 10
>      };
>  
> +    hdev->n.notify = vhost_iommu_unmap_notify;
> +    hdev->n.notifier_flags = IOMMU_NOTIFIER_UNMAP;
> +
>      if (hdev->migration_blocker == NULL) {
>          if (!(hdev->features & (0x1ULL << VHOST_F_LOG_ALL))) {
>              error_setg(&hdev->migration_blocker,
> @@ -1341,11 +1451,18 @@ int vhost_dev_start(struct vhost_dev *hdev, 
> VirtIODevice *vdev)
>      assert(hdev->vhost_ops);
>  
>      hdev->started = true;
> +    hdev->vdev = vdev;
>  
>      r = vhost_dev_set_features(hdev, hdev->log_enabled);
>      if (r < 0) {
>          goto fail_features;
>      }
> +
> +    if (vhost_dev_has_iommu(hdev)) {
> +        memory_region_register_iommu_notifier(vdev->dma_as->root,
> +                                              &hdev->n);
> +    }
> +
>      r = hdev->vhost_ops->vhost_set_mem_table(hdev, hdev->mem);
>      if (r < 0) {
>          VHOST_OPS_DEBUG("vhost_set_mem_table failed");
> @@ -1379,6 +1496,16 @@ int vhost_dev_start(struct vhost_dev *hdev, 
> VirtIODevice *vdev)
>          }
>      }
>  
> +    hdev->vhost_ops->vhost_set_iotlb_callback(hdev, true);
> +
> +    if (vhost_dev_has_iommu(hdev)) {
> +        /* Update used ring information for IOTLB to work correctly,
> +         * vhost-kernel code requires for this.*/
> +        for (i = 0; i < hdev->nvqs; ++i) {
> +            struct vhost_virtqueue *vq = hdev->vqs + i;
> +            vhost_device_iotlb_miss(hdev, vq->used_phys, true);
> +        }
> +    }
>      return 0;
>  fail_log:
>      vhost_log_put(hdev, false);
> @@ -1390,6 +1517,7 @@ fail_vq:
>                               hdev->vq_index + i);
>      }
>      i = hdev->nvqs;
> +
>  fail_mem:
>  fail_features:
>  
> @@ -1404,6 +1532,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, 
> VirtIODevice *vdev)
>  
>      /* should only be called after backend is connected */
>      assert(hdev->vhost_ops);
> +    hdev->vhost_ops->vhost_set_iotlb_callback(hdev, false);
>  
>      for (i = 0; i < hdev->nvqs; ++i) {
>          vhost_virtqueue_stop(hdev,
> @@ -1412,8 +1541,13 @@ void vhost_dev_stop(struct vhost_dev *hdev, 
> VirtIODevice *vdev)
>                               hdev->vq_index + i);
>      }
>  
> +    if (vhost_dev_has_iommu(hdev)) {
> +        memory_region_unregister_iommu_notifier(vdev->dma_as->root,
> +                                                &hdev->n);
> +    }
>      vhost_log_put(hdev, true);
>      hdev->started = false;
> +    hdev->vdev = NULL;
>  }
>  
>  int vhost_net_set_backend(struct vhost_dev *hdev,
> diff --git a/include/hw/virtio/vhost-backend.h 
> b/include/hw/virtio/vhost-backend.h
> index 6e90703..236eb85 100644
> --- a/include/hw/virtio/vhost-backend.h
> +++ b/include/hw/virtio/vhost-backend.h
> @@ -11,6 +11,8 @@
>  #ifndef VHOST_BACKEND_H
>  #define VHOST_BACKEND_H
>  
> +#include "exec/memory.h"
> +
>  typedef enum VhostBackendType {
>      VHOST_BACKEND_TYPE_NONE = 0,
>      VHOST_BACKEND_TYPE_KERNEL = 1,
> @@ -76,6 +78,14 @@ typedef bool (*vhost_backend_can_merge_op)(struct 
> vhost_dev *dev,
>  typedef int (*vhost_vsock_set_guest_cid_op)(struct vhost_dev *dev,
>                                              uint64_t guest_cid);
>  typedef int (*vhost_vsock_set_running_op)(struct vhost_dev *dev, int start);
> +typedef void (*vhost_set_iotlb_callback_op)(struct vhost_dev *dev,
> +                                           int enabled);
> +typedef int (*vhost_update_device_iotlb_op)(struct vhost_dev *dev,
> +                                            uint64_t iova, uint64_t uaddr,
> +                                            uint64_t len,
> +                                            IOMMUAccessFlags perm);
> +typedef int (*vhost_invalidate_device_iotlb_op)(struct vhost_dev *dev,
> +                                                uint64_t iova, uint64_t len);
>  
>  typedef struct VhostOps {
>      VhostBackendType backend_type;
> @@ -107,6 +117,9 @@ typedef struct VhostOps {
>      vhost_backend_can_merge_op vhost_backend_can_merge;
>      vhost_vsock_set_guest_cid_op vhost_vsock_set_guest_cid;
>      vhost_vsock_set_running_op vhost_vsock_set_running;
> +    vhost_set_iotlb_callback_op vhost_set_iotlb_callback;
> +    vhost_update_device_iotlb_op vhost_update_device_iotlb;
> +    vhost_invalidate_device_iotlb_op vhost_invalidate_device_iotlb;
>  } VhostOps;
>  
>  extern const VhostOps user_ops;
> diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
> index 1fe5aad..52f633e 100644
> --- a/include/hw/virtio/vhost.h
> +++ b/include/hw/virtio/vhost.h
> @@ -21,6 +21,7 @@ struct vhost_virtqueue {
>      unsigned long long used_phys;
>      unsigned used_size;
>      EventNotifier masked_notifier;
> +    struct vhost_dev *dev;
>  };
>  
>  typedef unsigned long vhost_log_chunk_t;
> @@ -38,6 +39,7 @@ struct vhost_log {
>  
>  struct vhost_memory;
>  struct vhost_dev {
> +    VirtIODevice *vdev;
>      MemoryListener memory_listener;
>      struct vhost_memory *mem;
>      int n_mem_sections;
> @@ -62,6 +64,7 @@ struct vhost_dev {
>      void *opaque;
>      struct vhost_log *log;
>      QLIST_ENTRY(vhost_dev) entry;
> +    IOMMUNotifier n;
>  };
>  
>  int vhost_dev_init(struct vhost_dev *hdev, void *opaque,
> @@ -91,4 +94,5 @@ bool vhost_has_free_slot(void);
>  int vhost_net_set_backend(struct vhost_dev *hdev,
>                            struct vhost_vring_file *file);
>  
> +void vhost_device_iotlb_miss(struct vhost_dev *dev, uint64_t iova, int 
> write);
>  #endif
> diff --git a/net/tap.c b/net/tap.c
> index b6896a7..86071b2 100644
> --- a/net/tap.c
> +++ b/net/tap.c
> @@ -696,6 +696,7 @@ static void net_init_tap_one(const NetdevTapOptions *tap, 
> NetClientState *peer,
>                                   "tap: open vhost char device failed");
>                  return;
>              }
> +            fcntl(vhostfd, F_SETFL, O_NONBLOCK);
>          }
>          options.opaque = (void *)(uintptr_t)vhostfd;
>  
> -- 
> 2.7.4



reply via email to

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