|
@@ -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);
|
|
|
r = hdev->vhost_ops->vhost_set_vring_call(hdev, &file);
|
|
|
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) {
|
|
|
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_start_config_intr(hdev);
|
|
|
return 0;
|
|
|
fail_start:
|
|
|
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 */
|
|
|
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);
|
|
|
|
|
@@ -1969,6 +2044,7 @@ void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
|
|
|
}
|
|
|
memory_listener_unregister(&hdev->iommu_listener);
|
|
|
}
|
|
|
+ vhost_stop_config_intr(hdev);
|
|
|
vhost_log_put(hdev, true);
|
|
|
hdev->started = false;
|
|
|
vdev->vhost_started = false;
|