Skip to content

Commit

Permalink
vhost: translate incoming log address to GPA
Browse files Browse the repository at this point in the history
When IOMMU is enabled the incoming log address is in IOVA space. In that
case, look in IOTLB table and translate the resulting HVA to GPA.

If IOMMU is not enabled, the incoming log address is already a GPA so no
transformation is needed.

Fixes: 69c90e9 ("vhost: enable IOMMU support")
Cc: stable@dpdk.org

Signed-off-by: Adrian Moreno <amorenoz@redhat.com>
Reviewed-by: Maxime Coquelin <maxime.coquelin@redhat.com>
  • Loading branch information
amorenoz authored and Ferruh Yigit committed Oct 23, 2019
1 parent a44c4e1 commit fbda9f1
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 1 deletion.
1 change: 1 addition & 0 deletions lib/librte_vhost/vhost.c
Expand Up @@ -382,6 +382,7 @@ vring_invalidate(struct virtio_net *dev, struct vhost_virtqueue *vq)
vq->desc = NULL;
vq->avail = NULL;
vq->used = NULL;
vq->log_guest_addr = 0;

if (dev->features & (1ULL << VIRTIO_F_IOMMU_PLATFORM))
vhost_user_iotlb_wr_unlock(vq);
Expand Down
20 changes: 20 additions & 0 deletions lib/librte_vhost/vhost.h
Expand Up @@ -447,6 +447,26 @@ gpa_to_hpa(struct virtio_net *dev, uint64_t gpa, uint64_t size)
return 0;
}

static __rte_always_inline uint64_t
hva_to_gpa(struct virtio_net *dev, uint64_t vva, uint64_t len)
{
struct rte_vhost_mem_region *r;
uint32_t i;

if (unlikely(!dev || !dev->mem))
return 0;

for (i = 0; i < dev->mem->nregions; i++) {
r = &dev->mem->regions[i];

if (vva >= r->host_user_addr &&
vva + len < r->host_user_addr + r->size) {
return r->guest_phys_addr + vva - r->host_user_addr;
}
}
return 0;
}

static __rte_always_inline struct virtio_net *
get_device(int vid)
{
Expand Down
42 changes: 41 additions & 1 deletion lib/librte_vhost/vhost_user.c
Expand Up @@ -575,6 +575,39 @@ 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)
{
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;

gpa = hva_to_gpa(dev, hva, exp_size);
if (!gpa) {
RTE_LOG(ERR, VHOST_CONFIG,
"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;
}

static struct virtio_net *
translate_ring_addresses(struct virtio_net *dev, int vq_index)
{
Expand Down Expand Up @@ -682,7 +715,14 @@ translate_ring_addresses(struct virtio_net *dev, int vq_index)
vq->last_avail_idx = vq->used->idx;
}

vq->log_guest_addr = addr->log_guest_addr;
vq->log_guest_addr =
translate_log_addr(dev, vq, addr->log_guest_addr);
if (vq->log_guest_addr == 0) {
RTE_LOG(DEBUG, VHOST_CONFIG,
"(%d) failed to map log_guest_addr .\n",
dev->vid);
return dev;
}
vq->access_ok = 1;

VHOST_LOG_DEBUG(VHOST_CONFIG, "(%d) mapped address desc: %p\n",
Expand Down

0 comments on commit fbda9f1

Please sign in to comment.