mirror of https://github.com/xemu-project/xemu.git
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;
|
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)
|
static int vhost_vdpa_cleanup(struct vhost_dev *dev)
|
||||||
{
|
{
|
||||||
struct vhost_vdpa *v;
|
struct vhost_vdpa *v;
|
||||||
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
assert(dev->vhost_ops->backend_type == VHOST_BACKEND_TYPE_VDPA);
|
||||||
v = dev->opaque;
|
v = dev->opaque;
|
||||||
trace_vhost_vdpa_cleanup(dev, v);
|
trace_vhost_vdpa_cleanup(dev, v);
|
||||||
|
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||||
memory_listener_unregister(&v->listener);
|
memory_listener_unregister(&v->listener);
|
||||||
|
|
||||||
dev->opaque = NULL;
|
dev->opaque = NULL;
|
||||||
|
@ -468,6 +551,7 @@ static int vhost_vdpa_dev_start(struct vhost_dev *dev, bool started)
|
||||||
if (started) {
|
if (started) {
|
||||||
uint8_t status = 0;
|
uint8_t status = 0;
|
||||||
memory_listener_register(&v->listener, &address_space_memory);
|
memory_listener_register(&v->listener, &address_space_memory);
|
||||||
|
vhost_vdpa_host_notifiers_init(dev);
|
||||||
vhost_vdpa_set_vring_ready(dev);
|
vhost_vdpa_set_vring_ready(dev);
|
||||||
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
|
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_DRIVER_OK);
|
||||||
vhost_vdpa_call(dev, VHOST_VDPA_GET_STATUS, &status);
|
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_reset_device(dev);
|
||||||
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
|
vhost_vdpa_add_status(dev, VIRTIO_CONFIG_S_ACKNOWLEDGE |
|
||||||
VIRTIO_CONFIG_S_DRIVER);
|
VIRTIO_CONFIG_S_DRIVER);
|
||||||
|
vhost_vdpa_host_notifiers_uninit(dev, dev->nvqs);
|
||||||
memory_listener_unregister(&v->listener);
|
memory_listener_unregister(&v->listener);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -14,11 +14,17 @@
|
||||||
|
|
||||||
#include "hw/virtio/virtio.h"
|
#include "hw/virtio/virtio.h"
|
||||||
|
|
||||||
|
typedef struct VhostVDPAHostNotifier {
|
||||||
|
MemoryRegion mr;
|
||||||
|
void *addr;
|
||||||
|
} VhostVDPAHostNotifier;
|
||||||
|
|
||||||
typedef struct vhost_vdpa {
|
typedef struct vhost_vdpa {
|
||||||
int device_fd;
|
int device_fd;
|
||||||
uint32_t msg_type;
|
uint32_t msg_type;
|
||||||
MemoryListener listener;
|
MemoryListener listener;
|
||||||
struct vhost_dev *dev;
|
struct vhost_dev *dev;
|
||||||
|
VhostVDPAHostNotifier notifier[VIRTIO_QUEUE_MAX];
|
||||||
} VhostVDPA;
|
} VhostVDPA;
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
Loading…
Reference in New Issue