diff --git a/lib/vhost/rte_vhost/vhost.h b/lib/vhost/rte_vhost/vhost.h index 0c297d4bf..79eca56f0 100644 --- a/lib/vhost/rte_vhost/vhost.h +++ b/lib/vhost/rte_vhost/vhost.h @@ -43,6 +43,7 @@ #include #include "rte_virtio_net.h" +#include "vhost_user.h" /* Used to indicate that the device is running on a data core */ #define VIRTIO_DEV_RUNNING 1 @@ -171,6 +172,9 @@ struct virtio_net { uint32_t nr_guest_pages; uint32_t max_guest_pages; struct guest_page *guest_pages; + int has_new_mem_table; + struct VhostUserMemory mem_table; + int mem_table_fds[VHOST_MEMORY_MAX_NREGIONS]; } __rte_cache_aligned; /** diff --git a/lib/vhost/rte_vhost/vhost_user.c b/lib/vhost/rte_vhost/vhost_user.c index cdf202a7a..55149a610 100644 --- a/lib/vhost/rte_vhost/vhost_user.c +++ b/lib/vhost/rte_vhost/vhost_user.c @@ -317,6 +317,8 @@ qva_to_vva(struct virtio_net *dev, uint64_t qva) return 0; } +static int vhost_setup_mem_table(struct virtio_net *dev); + /* * The virtio device sends us the desc, used and avail ring addresses. * This function then converts these to our address space. @@ -326,6 +328,12 @@ vhost_user_set_vring_addr(struct virtio_net *dev, VhostUserMsg *msg) { struct vhost_virtqueue *vq; + if (dev->has_new_mem_table) { + vhost_setup_mem_table(dev); + dev->has_new_mem_table = 0; + } + + if (dev->mem == NULL) return -1; @@ -492,7 +500,30 @@ dump_guest_pages(struct virtio_net *dev) static int vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg) { - struct VhostUserMemory memory = pmsg->payload.memory; + uint32_t i; + + if (dev->has_new_mem_table) { + /* + * The previous mem table was not consumed, so close the + * file descriptors from that mem table before copying + * the new one. + */ + for (i = 0; i < dev->mem_table.nregions; i++) { + close(dev->mem_table_fds[i]); + } + } + + memcpy(&dev->mem_table, &pmsg->payload.memory, sizeof(dev->mem_table)); + memcpy(dev->mem_table_fds, pmsg->fds, sizeof(dev->mem_table_fds)); + dev->has_new_mem_table = 1; + + return 0; +} + +static int +vhost_setup_mem_table(struct virtio_net *dev) +{ + struct VhostUserMemory memory = dev->mem_table; struct virtio_memory_region *reg; void *mmap_addr; uint64_t mmap_size; @@ -501,12 +532,6 @@ vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg) uint32_t i; int fd; - /* Remove from the data plane. */ - if (dev->flags & VIRTIO_DEV_RUNNING) { - dev->flags &= ~VIRTIO_DEV_RUNNING; - notify_ops->destroy_device(dev->vid); - } - if (dev->mem) { free_mem_region(dev); rte_free(dev->mem); @@ -531,7 +556,7 @@ vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg) dev->mem->nregions = memory.nregions; for (i = 0; i < memory.nregions; i++) { - fd = pmsg->fds[i]; + fd = dev->mem_table_fds[i]; reg = &dev->mem->regions[i]; reg->guest_phys_addr = memory.regions[i].guest_phys_addr;