vhost: Add Shadow VirtQueue kick forwarding capabilities

At this mode no buffer forwarding will be performed in SVQ mode: Qemu
will just forward the guest's kicks to the device.

Host memory notifiers regions are left out for simplicity, and they will
not be addressed in this series.

Signed-off-by: Eugenio Pérez <eperezma@redhat.com>
Acked-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Jason Wang <jasowang@redhat.com>
This commit is contained in:
Eugenio Pérez 2022-03-14 18:34:42 +01:00 committed by Jason Wang
parent 10857ec0ad
commit dff4426fa6
4 changed files with 215 additions and 2 deletions

View file

@ -11,6 +11,59 @@
#include "hw/virtio/vhost-shadow-virtqueue.h"
#include "qemu/error-report.h"
#include "qemu/main-loop.h"
#include "linux-headers/linux/vhost.h"
/**
* Forward guest notifications.
*
* @n: guest kick event notifier, the one that guest set to notify svq.
*/
static void vhost_handle_guest_kick(EventNotifier *n)
{
VhostShadowVirtqueue *svq = container_of(n, VhostShadowVirtqueue, svq_kick);
event_notifier_test_and_clear(n);
event_notifier_set(&svq->hdev_kick);
}
/**
* Set a new file descriptor for the guest to kick the SVQ and notify for avail
*
* @svq: The svq
* @svq_kick_fd: The svq kick fd
*
* Note that the SVQ will never close the old file descriptor.
*/
void vhost_svq_set_svq_kick_fd(VhostShadowVirtqueue *svq, int svq_kick_fd)
{
EventNotifier *svq_kick = &svq->svq_kick;
bool poll_stop = VHOST_FILE_UNBIND != event_notifier_get_fd(svq_kick);
bool poll_start = svq_kick_fd != VHOST_FILE_UNBIND;
if (poll_stop) {
event_notifier_set_handler(svq_kick, NULL);
}
/*
* event_notifier_set_handler already checks for guest's notifications if
* they arrive at the new file descriptor in the switch, so there is no
* need to explicitly check for them.
*/
if (poll_start) {
event_notifier_init_fd(svq_kick, svq_kick_fd);
event_notifier_set(svq_kick);
event_notifier_set_handler(svq_kick, vhost_handle_guest_kick);
}
}
/**
* Stop the shadow virtqueue operation.
* @svq: Shadow Virtqueue
*/
void vhost_svq_stop(VhostShadowVirtqueue *svq)
{
event_notifier_set_handler(&svq->svq_kick, NULL);
}
/**
* Creates vhost shadow virtqueue, and instructs the vhost device to use the
@ -39,6 +92,7 @@ VhostShadowVirtqueue *vhost_svq_new(void)
goto err_init_hdev_call;
}
event_notifier_init_fd(&svq->svq_kick, VHOST_FILE_UNBIND);
return g_steal_pointer(&svq);
err_init_hdev_call:
@ -56,6 +110,7 @@ err_init_hdev_kick:
void vhost_svq_free(gpointer pvq)
{
VhostShadowVirtqueue *vq = pvq;
vhost_svq_stop(vq);
event_notifier_cleanup(&vq->hdev_kick);
event_notifier_cleanup(&vq->hdev_call);
g_free(vq);