vhost-vdpa: map virtqueue notification area if possible
This patch implements the vq notification mapping support for vhost-vDPA. This is simply done by using mmap()/munmap() for the vhost-vDPA fd during device start/stop. For the device without notification mapping support, we fall back to eventfd based notification gracefully. Reviewed-by: Si-Wei Liu <si-wei.liu@oracle.com> Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
parent
d60c75d28f
commit
d0416d487b
@ -286,12 +286,95 @@ static int vhost_vdpa_init(struct vhost_dev *dev, void *opaque)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void vhost_vdpa_host_notifier_uninit(struct vhost_dev *dev,
|
||||
int queue_index)
|
||||
{
|
||||
size_t page_size = qemu_real_host_page_size;
|
||||
struct vhost_vdpa *v = dev->opaque;
|
||||
VirtIODevice *vdev = dev->vdev;
|
||||
VhostVDPAHostNotifier *n;
|
||||
|
||||
n = &v->notifier[queue_index];
|
||||
|
||||
if (n->addr) {
|
||||
virtio_queue_set_host_notifier_mr(vdev, queue_index, &n->mr, false);
|
||||
object_unparent(OBJECT(&n->mr));
|
||||
munmap(n->addr, page_size);
|
||||
n->addr = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static void vhost_vdpa_host_notifiers_uninit(struct vhost_dev *dev, int n)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
vhost_vdpa_host_notifier_uninit(dev, i);
|
||||
}
|
||||
}
|
||||
|
||||
static int vhost_vdpa_host_notifier_init(struct vhost_dev *dev, int queue_index)
|
||||
{
|
||||
size_t page_size = qemu_real_host_page_size;
|
||||
struct vhost_vdpa *v = dev->opaque;
|
||||
VirtIODevice *vdev = dev->vdev;
|
||||
VhostVDPAHostNotifier *n;
|
||||
int fd = v->device_fd;
|
||||
void *addr;
|
||||
char *name;
|
||||
|
||||
vhost_vdpa_host_notifier_uninit(dev, queue_index);
|
||||
|
||||
n = &v->notifier[queue_index];
|
||||
|
||||
addr = mmap(NULL, page_size, PROT_WRITE, MAP_SHARED, fd,
|
||||
queue_index * page_size);
|
||||
if (addr == MAP_FAILED) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
name = g_strdup_printf("vhost-vdpa/host-notifier@%p mmaps[%d]",
|
||||
v, queue_index);
|
||||
memory_region_init_ram_device_ptr(&n->mr, OBJECT(vdev), name,
|
||||
page_size, addr);
|
||||
g_free(name);
|
||||
|
||||
if (virtio_queue_set_host_notifier_mr(vdev, queue_index, &n->mr, true)) {
|
||||
munmap(addr, page_size);
|
||||
goto err;
|
||||
}
|
||||
n->addr = addr;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
return -1;
|
||||
}
|
||||
|
||||
static void vhost_vdpa_host_notifiers_init(struct vhost_dev *dev)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = dev->vq_index; i < dev->vq_index + dev->nvqs; i++) {
|
||||
if (vhost_vdpa_host_notifier_init(dev, i)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
vhost_vdpa_host_notifiers_uninit(dev, i);
|
||||
return;
|
||||
}
|
||||
|
||||
static int vhost_vdpa_cleanup(struct vhost_dev *dev)
|
||||
{
|
||||
struct vhost_vdpa *v;
|
||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
||||
v = dev->opaque;
|
||||
trace_vhost_vdpa_cleanup(dev, v);
|
||||
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||
memory_listener_unregister(&v->listener);
|
||||
|
||||
dev->opaque = NULL;
|
||||
@ -468,6 +551,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||
if (started) {
|
||||
uint8_t status = 0;
|
||||
memory_listener_register(&v->listener, &address_space_memory);
|
||||
vhost_vdpa_host_notifiers_init(dev);
|
||||
vhost_vdpa_set_vring_ready(dev);
|
||||
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
|
||||
vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status);
|
||||
@ -477,6 +561,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||
vhost_vdpa_reset_device(dev);
|
||||
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
|
||||
VIRTIO_CONFIG_S_DRIVER);
|
||||
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||
memory_listener_unregister(&v->listener);
|
||||
|
||||
return 0;
|
||||
|
@ -14,11 +14,17 @@
|
||||
|
||||
#include "hw/virtio/virtio.h"
|
||||
|
||||
typedef struct VhostVDPAHostNotifier {
|
||||
MemoryRegion mr;
|
||||
void *addr;
|
||||
} VhostVDPAHostNotifier;
|
||||
|
||||
typedef struct vhost_vdpa {
|
||||
int device_fd;
|
||||
uint32_t msg_type;
|
||||
MemoryListener listener;
|
||||
struct vhost_dev *dev;
|
||||
VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
|
||||
} VhostVDPA;
|
||||
|
||||
#endif
|
||||
|
Loading…
Reference in New Issue
Block a user