From bac6830a925cd102a899a537f261b8bf856186b2 Mon Sep 17 00:00:00 2001 From: Dariusz Stojaczyk Date: Tue, 17 Apr 2018 22:13:35 +0200 Subject: [PATCH] rte_vhost: ensure all range is mapped when translating QVAs This patch ensures that all the address range is mapped when translating addresses from master's addresses (e.g. QEMU host addressess) to process VAs. Change-Id: If141670951064a8d2b4b7343bf4cc9ca93fe2e6d Reported-by: Yongji Xie Signed-off-by: Maxime Coquelin Signed-off-by: Dariusz Stojaczyk Reviewed-on: https://review.gerrithub.io/408721 Reviewed-by: Daniel Verkamp Tested-by: SPDK Automated Test System Reviewed-by: Jim Harris --- lib/vhost/rte_vhost/vhost_user.c | 29 +++++++++++++++++++++-------- 1 file changed, 21 insertions(+), 8 deletions(-) diff --git a/lib/vhost/rte_vhost/vhost_user.c b/lib/vhost/rte_vhost/vhost_user.c index a1f620fa0..0353ffed5 100644 --- a/lib/vhost/rte_vhost/vhost_user.c +++ b/lib/vhost/rte_vhost/vhost_user.c @@ -329,7 +329,7 @@ numa_realloc(struct virtio_net *dev, int index __rte_unused) * used to convert the ring addresses to our address space. */ static uint64_t -qva_to_vva(struct virtio_net *dev, uint64_t qva) +qva_to_vva(struct virtio_net *dev, uint64_t qva, uint64_t *len) { struct rte_vhost_mem_region *reg; uint32_t i; @@ -340,6 +340,10 @@ qva_to_vva(struct virtio_net *dev, uint64_t qva) if (qva >= reg->guest_user_addr && qva < reg->guest_user_addr + reg->size) { + + if (unlikely(*len > reg->guest_user_addr + reg->size - qva)) + *len = reg->guest_user_addr + reg->size - qva; + return qva - reg->guest_user_addr + reg->host_user_addr; } @@ -358,6 +362,7 @@ static int vhost_user_set_vring_addr(struct virtio_net *dev, VhostUserMsg *msg) { struct vhost_virtqueue *vq; + uint64_t len; if (dev->has_new_mem_table) { vhost_setup_mem_table(dev); @@ -378,11 +383,12 @@ vhost_user_set_vring_addr(struct virtio_net *dev, VhostUserMsg *msg) vq = dev->virtqueue[msg->payload.addr.index]; /* The addresses are converted from QEMU virtual to Vhost virtual. */ + len = sizeof(struct vring_desc) * vq->size; vq->desc = (struct vring_desc *)(uintptr_t)qva_to_vva(dev, - msg->payload.addr.desc_user_addr); - if (vq->desc == 0) { + msg->payload.addr.desc_user_addr, &len); + if (vq->desc == 0 || len != sizeof(struct vring_desc) * vq->size) { RTE_LOG(ERR, VHOST_CONFIG, - "(%d) failed to find desc ring address.\n", + "(%d) failed to map desc ring.\n", dev->vid); return -1; } @@ -390,18 +396,25 @@ vhost_user_set_vring_addr(struct virtio_net *dev, VhostUserMsg *msg) dev = numa_realloc(dev, msg->payload.addr.index); vq = dev->virtqueue[msg->payload.addr.index]; + len = sizeof(struct vring_avail) + sizeof(uint16_t) * vq->size; vq->avail = (struct vring_avail *)(uintptr_t)qva_to_vva(dev, - msg->payload.addr.avail_user_addr); - if (vq->avail == 0) { + msg->payload.addr.avail_user_addr, &len); + if (vq->avail == 0 || + len != sizeof(struct vring_avail) + + sizeof(uint16_t) * vq->size) { RTE_LOG(ERR, VHOST_CONFIG, "(%d) failed to find avail ring address.\n", dev->vid); return -1; } + len = sizeof(struct vring_used) + + sizeof(struct vring_used_elem) * vq->size; vq->used = (struct vring_used *)(uintptr_t)qva_to_vva(dev, - msg->payload.addr.used_user_addr); - if (vq->used == 0) { + msg->payload.addr.used_user_addr, &len); + if (vq->used == 0 || len != sizeof(struct vring_used) + + sizeof(struct vring_used_elem) * vq->size) { + RTE_LOG(ERR, VHOST_CONFIG, "(%d) failed to find used ring address.\n", dev->vid);