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, for masked_config_notifier, we only
use the notifier saved in vq 0.

Signed-off-by: Cindy Lu <lulu@redhat.com>
Message-Id: <20211104164827.21911-8-lulu@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 2021-11-05 00:48:24 +08:00 committed by Michael S. Tsirkin
parent 081f864f56
commit f7220a7ce2
2 changed files with 80 additions and 0 deletions

View File

@ -1561,6 +1561,67 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
}
}
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) {
VHOST_OPS_DEBUG("vhost_set_config_call failed");
}
}
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);
}
}
}
uint64_t vhost_get_features(struct vhost_dev *hdev, const int *feature_bits,
uint64_t features)
{
@ -1773,6 +1834,16 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
}
}
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) {
uint64_t log_base;
@ -1806,6 +1877,7 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
vhost_device_iotlb_miss(hdev, vq->used_phys, true);
}
}
vhost_start_config_intr(hdev);
return 0;
fail_log:
vhost_log_put(hdev, false);
@ -1831,6 +1903,9 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
/* should only be called after backend is connected */
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);
if (hdev->vhost_ops->vhost_dev_start) {
hdev->vhost_ops->vhost_dev_start(hdev, false);
@ -1848,6 +1923,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
}
memory_listener_unregister(&hdev->iommu_listener);
}
vhost_stop_config_intr(hdev);
vhost_log_put(hdev, true);
hdev->started = false;
hdev->vdev = NULL;

View File

@ -29,6 +29,7 @@ struct vhost_virtqueue {
unsigned long long used_phys;
unsigned used_size;
EventNotifier masked_notifier;
EventNotifier masked_config_notifier;
struct vhost_dev *dev;
};
@ -37,6 +38,7 @@ typedef unsigned long 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_INVALID_FEATURE_BIT (0xff)
#define VHOST_QUEUE_NUM_CONFIG_INR 0
struct vhost_log {
unsigned long long size;
@ -116,6 +118,8 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev);
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev);
int vhost_dev_enable_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);
/* Test and clear masked event pending status.
* Should be called after unmask to avoid losing events.