171 lines
5.6 KiB
Diff
171 lines
5.6 KiB
Diff
|
|
From 9823b7bb536cea50c9750320436511fd60b797cd Mon Sep 17 00:00:00 2001
|
||
|
|
From: fangyi <eric.fangyi@huawei.com>
|
||
|
|
Date: Thu, 16 Nov 2023 09:54:52 +0800
|
||
|
|
Subject: [PATCH] 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>
|
||
|
|
Signed-off-by: fangyi <eric.fangyi@huawei.com>
|
||
|
|
---
|
||
|
|
hw/virtio/vhost.c | 76 +++++++++++++++++++++++++++++++++++++++
|
||
|
|
include/hw/virtio/vhost.h | 4 +++
|
||
|
|
2 files changed, 80 insertions(+)
|
||
|
|
|
||
|
|
diff --git a/hw/virtio/vhost.c b/hw/virtio/vhost.c
|
||
|
|
index 2d11e3c2f8..c3f375f276 100644
|
||
|
|
--- a/hw/virtio/vhost.c
|
||
|
|
+++ b/hw/virtio/vhost.c
|
||
|
|
@@ -1588,6 +1588,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)
|
||
|
|
{
|
||
|
|
@@ -1800,6 +1861,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;
|
||
|
|
|
||
|
|
@@ -1833,6 +1904,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);
|
||
|
|
@@ -1858,6 +1930,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);
|
||
|
|
@@ -1875,6 +1950,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;
|
||
|
|
diff --git a/include/hw/virtio/vhost.h b/include/hw/virtio/vhost.h
|
||
|
|
index 86f36f0106..2ae5c3bfd8 100644
|
||
|
|
--- a/include/hw/virtio/vhost.h
|
||
|
|
+++ b/include/hw/virtio/vhost.h
|
||
|
|
@@ -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.
|
||
|
|
--
|
||
|
|
2.27.0
|
||
|
|
|