vhost: add support for configure interrupt

Add functions to support configure interrupt.
The configure interrupt process will start in vhost_dev_start
and stop in vhost_dev_stop.

Also add the functions to support vhost_config_pending and
vhost_config_mask.

Signed-off-by: Cindy Lu <lulu@redhat.com>
Message-Id: <20221222070451.936503-8-lulu@redhat.com>
Acked-by: Jason Wang <jasowang@redhat.com>
Reviewed-by: Michael S. Tsirkin <mst@redhat.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
This commit is contained in:
Cindy Lu 2022-12-22 15:04:48 +08:00 committed by Michael S. Tsirkin
parent 7d847d0c9b
commit f9a09ca3ea
2 changed files with 81 additions and 1 deletions

View file

@ -1640,7 +1640,68 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n); file.index = hdev->vhost_ops->vhost_get_vq_index(hdev, n);
r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file); r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file);
if (r < 0) { if (r < 0) {
VHOST_OPS_DEBUG(r, "vhost_set_vring_call failed"); error_report("vhost_set_vring_call failed %d", -r);
}
}
bool vhost_config_pending(struct vhost_dev *hdev)
{
assert(hdev->vhost_ops);
if ((hdev->started == false) ||
(hdev->vhost_ops->vhost_set_config_call == NULL)) {
return false;
}
EventNotifier *notifier =
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier;
return event_notifier_test_and_clear(notifier);
}
void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask)
{
int fd;
int r;
EventNotifier *notifier =
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier;
EventNotifier *config_notifier = &vdev->config_notifier;
assert(hdev->vhost_ops);
if ((hdev->started == false) ||
(hdev->vhost_ops->vhost_set_config_call == NULL)) {
return;
}
if (mask) {
assert(vdev->use_guest_notifier_mask);
fd = event_notifier_get_fd(notifier);
} else {
fd = event_notifier_get_fd(config_notifier);
}
r = hdev->vhost_ops->vhost_set_config_call(hdev, fd);
if (r < 0) {
error_report("vhost_set_config_call failed %d", -r);
}
}
static void vhost_stop_config_intr(struct vhost_dev *dev)
{
int fd = -1;
assert(dev->vhost_ops);
if (dev->vhost_ops->vhost_set_config_call) {
dev->vhost_ops->vhost_set_config_call(dev, fd);
}
}
static void vhost_start_config_intr(struct vhost_dev *dev)
{
int r;
assert(dev->vhost_ops);
int fd = event_notifier_get_fd(&dev->vdev->config_notifier);
if (dev->vhost_ops->vhost_set_config_call) {
r = dev->vhost_ops->vhost_set_config_call(dev, fd);
if (!r) {
event_notifier_set(&dev->vdev->config_notifier);
}
} }
} }
@ -1880,6 +1941,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
} }
} }
r = event_notifier_init(
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier, 0);
if (r < 0) {
return r;
}
event_notifier_test_and_clear(
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
if (!vdev->use_guest_notifier_mask) {
vhost_config_mask(hdev, vdev, true);
}
if (hdev->log_enabled) { if (hdev->log_enabled) {
uint64_t log_base; uint64_t log_base;
@ -1918,6 +1989,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
vhost_device_iotlb_miss(hdev, vq->used_phys, true); vhost_device_iotlb_miss(hdev, vq->used_phys, true);
} }
} }
vhost_start_config_intr(hdev);
return 0; return 0;
fail_start: fail_start:
if (vrings) { if (vrings) {
@ -1947,6 +2019,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
/* should only be called after backend is connected */ /* should only be called after backend is connected */
assert(hdev->vhost_ops); assert(hdev->vhost_ops);
event_notifier_test_and_clear(
&hdev->vqs[VHOST_QUEUE_NUM_CONFIG_INR].masked_config_notifier);
event_notifier_test_and_clear(&vdev->config_notifier);
trace_vhost_dev_stop(hdev, vdev->name, vrings); trace_vhost_dev_stop(hdev, vdev->name, vrings);
@ -1969,6 +2044,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
} }
memory_listener_unregister(&hdev->iommu_listener); memory_listener_unregister(&hdev->iommu_listener);
} }
vhost_stop_config_intr(hdev);
vhost_log_put(hdev, true); vhost_log_put(hdev, true);
hdev->started = false; hdev->started = false;
vdev->vhost_started = false; vdev->vhost_started = false;

View file

@ -33,6 +33,7 @@ struct vhost_virtqueue {
unsigned used_size; unsigned used_size;
EventNotifier masked_notifier; EventNotifier masked_notifier;
EventNotifier error_notifier; EventNotifier error_notifier;
EventNotifier masked_config_notifier;
struct vhost_dev *dev; struct vhost_dev *dev;
}; };
@ -41,6 +42,7 @@ typedef unsigned long vhost_log_chunk_t;
#define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t)) #define VHOST_LOG_BITS (8 * sizeof(vhost_log_chunk_t))
#define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS) #define VHOST_LOG_CHUNK (VHOST_LOG_PAGE * VHOST_LOG_BITS)
#define VHOST_INVALID_FEATURE_BIT (0xff) #define VHOST_INVALID_FEATURE_BIT (0xff)
#define VHOST_QUEUE_NUM_CONFIG_INR 0
struct vhost_log { struct vhost_log {
unsigned long long size; unsigned long long size;
@ -187,6 +189,8 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
* Disable direct notifications to vhost device. * Disable direct notifications to vhost device.
*/ */
void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev); void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev);
bool vhost_config_pending(struct vhost_dev *hdev);
void vhost_config_mask(struct vhost_dev *hdev, VirtIODevice *vdev, bool mask);
/** /**
* vhost_dev_is_started() - report status of vhost device * vhost_dev_is_started() - report status of vhost device