On 13/02/2020 10:04, Adrian Moreno wrote: > Currently, the log address translation only happens in the vhost-user's > translate_ring_addresses(). However, the IOTLB update handler is not > checking if it was mapped to re-trigger that translation. > > Since the log address mapping could fail, check it on iotlb updates. > Also, check it on vring_translate() so we do not dirty pages if the > logging address is not yet ready. > > Additionally, properly protect the accesses to the iotlb structures. > > Fixes: 657414f3788a ("vhost: protect log addr translation in iotlb updates")
This fixes looks incorrect, it's suspiciously the same name and I couldn't find the commit-id in upstream. > Cc: sta...@dpdk.org > > Signed-off-by: Adrian Moreno <amore...@redhat.com> > --- > lib/librte_vhost/vhost.c | 55 +++++++++++++++++++++++++++++++++ > lib/librte_vhost/vhost.h | 15 +++++++-- > lib/librte_vhost/vhost_user.c | 57 +++++++++++++++-------------------- > 3 files changed, 92 insertions(+), 35 deletions(-) > > diff --git a/lib/librte_vhost/vhost.c b/lib/librte_vhost/vhost.c > index c819a8477..442d896ef 100644 > --- a/lib/librte_vhost/vhost.c > +++ b/lib/librte_vhost/vhost.c > @@ -353,6 +353,56 @@ free_device(struct virtio_net *dev) > rte_free(dev); > } > > +static __rte_always_inline int > +log_translate(struct virtio_net *dev, struct vhost_virtqueue *vq) > +{ > + if (likely(!(vq->ring_addrs.flags & (1 << VHOST_VRING_F_LOG)))) > + return 0; > + > + vq->log_guest_addr = translate_log_addr(dev, vq, > + vq->ring_addrs.log_guest_addr); > + if (vq->log_guest_addr == 0) > + return -1; > + > + return 0; > +} > + > +/* > + * Converts vring log address to GPA > + * If IOMMU is enabled, the log address is IOVA > + * If IOMMU not enabled, the log address is already GPA > + * > + * Caller should have iotlb_lock read-locked > + */ > +uint64_t > +translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, > + uint64_t log_addr) > +{ > + if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { > + const uint64_t exp_size = sizeof(uint64_t); > + uint64_t hva, gpa; > + uint64_t size = exp_size; > + > + hva = vhost_iova_to_vva(dev, vq, log_addr, > + &size, VHOST_ACCESS_RW); > + > + if (size != exp_size) > + return 0; > + > + gpa = hva_to_gpa(dev, hva, exp_size); > + if (!gpa) { > + VHOST_LOG_CONFIG(ERR, > + "VQ: Failed to find GPA for log_addr: 0x%" > PRIx64 " hva: 0x%" PRIx64 "\n", > + log_addr, hva); > + return 0; > + } > + return gpa; > + > + } else > + return log_addr; > +} > + > +/* Caller should have iotlb_lock read-locked */ > static int > vring_translate_split(struct virtio_net *dev, struct vhost_virtqueue *vq) > { > @@ -391,6 +441,7 @@ vring_translate_split(struct virtio_net *dev, struct > vhost_virtqueue *vq) > return 0; > } > > +/* Caller should have iotlb_lock read-locked */ > static int > vring_translate_packed(struct virtio_net *dev, struct vhost_virtqueue *vq) > { > @@ -437,6 +488,10 @@ vring_translate(struct virtio_net *dev, struct > vhost_virtqueue *vq) > if (vring_translate_split(dev, vq) < 0) > return -1; > } > + > + if (log_translate(dev, vq) < 0) > + return -1; > + > vq->access_ok = 1; > > return 0; > diff --git a/lib/librte_vhost/vhost.h b/lib/librte_vhost/vhost.h > index 686ce42a2..2087d1400 100644 > --- a/lib/librte_vhost/vhost.h > +++ b/lib/librte_vhost/vhost.h > @@ -462,14 +462,23 @@ static __rte_always_inline void > vhost_log_cache_used_vring(struct virtio_net *dev, struct vhost_virtqueue > *vq, > uint64_t offset, uint64_t len) > { > - vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, len); > + if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { > + if (unlikely(vq->log_guest_addr == 0)) > + return; > + __vhost_log_cache_write(dev, vq, vq->log_guest_addr + offset, > + len); > + } > } > > static __rte_always_inline void > vhost_log_used_vring(struct virtio_net *dev, struct vhost_virtqueue *vq, > uint64_t offset, uint64_t len) > { > - vhost_log_write(dev, vq->log_guest_addr + offset, len); > + if (unlikely(dev->features & (1ULL << VHOST_F_LOG_ALL))) { > + if (unlikely(vq->log_guest_addr == 0)) > + return; > + __vhost_log_write(dev, vq->log_guest_addr + offset, len); > + } > } > > static __rte_always_inline void > @@ -626,6 +635,8 @@ void *vhost_alloc_copy_ind_table(struct virtio_net *dev, > struct vhost_virtqueue *vq, > uint64_t desc_addr, uint64_t desc_len); > int vring_translate(struct virtio_net *dev, struct vhost_virtqueue *vq); > +uint64_t translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue > *vq, > + uint64_t log_addr); > void vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq); > > static __rte_always_inline uint64_t > diff --git a/lib/librte_vhost/vhost_user.c b/lib/librte_vhost/vhost_user.c > index 69b84a882..5db9f148f 100644 > --- a/lib/librte_vhost/vhost_user.c > +++ b/lib/librte_vhost/vhost_user.c > @@ -656,13 +656,11 @@ ring_addr_to_vva(struct virtio_net *dev, struct > vhost_virtqueue *vq, > { > if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { > uint64_t vva; > - uint64_t req_size = *size; > > - vva = vhost_user_iotlb_cache_find(vq, ra, > + vhost_user_iotlb_rd_lock(vq); > + vva = vhost_iova_to_vva(dev, vq, ra, > size, VHOST_ACCESS_RW); > - if (req_size != *size) > - vhost_user_iotlb_miss(dev, (ra + *size), > - VHOST_ACCESS_RW); > + vhost_user_iotlb_rd_unlock(vq); > > return vva; > } > @@ -670,37 +668,16 @@ ring_addr_to_vva(struct virtio_net *dev, struct > vhost_virtqueue *vq, > return qva_to_vva(dev, ra, size); > } > > -/* > - * Converts vring log address to GPA > - * If IOMMU is enabled, the log address is IOVA > - * If IOMMU not enabled, the log address is already GPA > - */ > static uint64_t > -translate_log_addr(struct virtio_net *dev, struct vhost_virtqueue *vq, > - uint64_t log_addr) > +log_addr_to_gpa(struct virtio_net *dev, struct vhost_virtqueue *vq) > { > - if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM)) { > - const uint64_t exp_size = sizeof(struct vring_used) + > - sizeof(struct vring_used_elem) * vq->size; > - uint64_t hva, gpa; > - uint64_t size = exp_size; > - > - hva = vhost_iova_to_vva(dev, vq, log_addr, > - &size, VHOST_ACCESS_RW); > - if (size != exp_size) > - return 0; > + uint64_t log_gpa; > > - gpa = hva_to_gpa(dev, hva, exp_size); > - if (!gpa) { > - VHOST_LOG_CONFIG(ERR, > - "VQ: Failed to find GPA for log_addr: 0x%" > PRIx64 " hva: 0x%" PRIx64 "\n", > - log_addr, hva); > - return 0; > - } > - return gpa; > + vhost_user_iotlb_rd_lock(vq); > + log_gpa = translate_log_addr(dev, vq, vq->ring_addrs.log_guest_addr); > + vhost_user_iotlb_rd_unlock(vq); > > - } else > - return log_addr; > + return log_gpa; > } > > static struct virtio_net * > @@ -712,7 +689,7 @@ translate_ring_addresses(struct virtio_net *dev, int > vq_index) > > if (addr->flags & (1 << VHOST_VRING_F_LOG)) { > vq->log_guest_addr = > - translate_log_addr(dev, vq, addr->log_guest_addr); > + log_addr_to_gpa(dev, vq); > if (vq->log_guest_addr == 0) { > VHOST_LOG_CONFIG(DEBUG, > "(%d) failed to map log_guest_addr.\n", > @@ -2229,6 +2206,13 @@ is_vring_iotlb_split(struct vhost_virtqueue *vq, > struct vhost_iotlb_msg *imsg) > if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) > return 1; > > + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { > + len = sizeof(uint64_t); > + if (ra->log_guest_addr < end && > + (ra->log_guest_addr + len) > start) > + return 1; > + } > + > return 0; > } > > @@ -2254,6 +2238,13 @@ is_vring_iotlb_packed(struct vhost_virtqueue *vq, > struct vhost_iotlb_msg *imsg) > if (ra->used_user_addr < end && (ra->used_user_addr + len) > start) > return 1; > > + if (ra->flags & (1 << VHOST_VRING_F_LOG)) { > + len = sizeof(uint64_t); > + if (ra->log_guest_addr < end && > + (ra->log_guest_addr + len) > start) > + return 1; > + } > + > return 0; > } > >