vhost: defer setting up new mem table
There is an issue when QEMU sets new memory table just after guest OS starts booting. Then, if guest OS tries to issue any I/O to device (e.g. using BIOS INT13h - EDD) it will get stuck because previous addresses of mmaped memory might change. To fix this issue, defer using the new mem table until after we receive the first SET_VRING_ADDR message. SET_VRING_ADDR will be sent by QEMU when guest OS virtio (e.g. virtio-scsi) driver starts initialization. At this point it is safe to invalidate the old mem tables because there will be no more outstanding IO at this point. Change-Id: I24772be87a8b6c8781868b9b7773317761499748 Signed-off-by: Jim Harris <james.r.harris@intel.com> Signed-off-by: Dariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
This commit is contained in:
parent
fab374a7c6
commit
8457b98cf2
@ -47,6 +47,7 @@
|
|||||||
#include <rte_ether.h>
|
#include <rte_ether.h>
|
||||||
|
|
||||||
#include "rte_vhost.h"
|
#include "rte_vhost.h"
|
||||||
|
#include "vhost_user.h"
|
||||||
|
|
||||||
/* Used to indicate that the device is running on a data core */
|
/* Used to indicate that the device is running on a data core */
|
||||||
#define VIRTIO_DEV_RUNNING 1
|
#define VIRTIO_DEV_RUNNING 1
|
||||||
@ -196,6 +197,9 @@ struct virtio_net {
|
|||||||
uint32_t nr_guest_pages;
|
uint32_t nr_guest_pages;
|
||||||
uint32_t max_guest_pages;
|
uint32_t max_guest_pages;
|
||||||
struct guest_page *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;
|
} __rte_cache_aligned;
|
||||||
|
|
||||||
|
|
||||||
|
@ -323,6 +323,8 @@ qva_to_vva(struct virtio_net *dev, uint64_t qva)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int vhost_setup_mem_table(struct virtio_net *dev);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The virtio device sends us the desc, used and avail ring addresses.
|
* The virtio device sends us the desc, used and avail ring addresses.
|
||||||
* This function then converts these to our address space.
|
* This function then converts these to our address space.
|
||||||
@ -332,6 +334,12 @@ vhost_user_set_vring_addr(struct virtio_net *dev, struct vhost_vring_addr *addr)
|
|||||||
{
|
{
|
||||||
struct vhost_virtqueue *vq;
|
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)
|
if (dev->mem == NULL)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
@ -499,7 +507,30 @@ dump_guest_pages(struct virtio_net *dev)
|
|||||||
static int
|
static int
|
||||||
vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
|
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 rte_vhost_mem_region *reg;
|
struct rte_vhost_mem_region *reg;
|
||||||
void *mmap_addr;
|
void *mmap_addr;
|
||||||
uint64_t mmap_size;
|
uint64_t mmap_size;
|
||||||
@ -532,7 +563,7 @@ vhost_user_set_mem_table(struct virtio_net *dev, struct VhostUserMsg *pmsg)
|
|||||||
dev->mem->nregions = memory.nregions;
|
dev->mem->nregions = memory.nregions;
|
||||||
|
|
||||||
for (i = 0; i < memory.nregions; i++) {
|
for (i = 0; i < memory.nregions; i++) {
|
||||||
fd = pmsg->fds[i];
|
fd = dev->mem_table_fds[i];
|
||||||
reg = &dev->mem->regions[i];
|
reg = &dev->mem->regions[i];
|
||||||
|
|
||||||
reg->guest_phys_addr = memory.regions[i].guest_phys_addr;
|
reg->guest_phys_addr = memory.regions[i].guest_phys_addr;
|
||||||
|
Loading…
Reference in New Issue
Block a user