|
@@ -616,14 +616,17 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|
|
{
|
|
|
hwaddr s, l, a;
|
|
|
int r;
|
|
|
+ int vhost_vq_index = idx - dev->vq_index;
|
|
|
struct vhost_vring_file file = {
|
|
|
- .index = idx,
|
|
|
+ .index = vhost_vq_index
|
|
|
};
|
|
|
struct vhost_vring_state state = {
|
|
|
- .index = idx,
|
|
|
+ .index = vhost_vq_index
|
|
|
};
|
|
|
struct VirtQueue *vvq = virtio_get_queue(vdev, idx);
|
|
|
|
|
|
+ assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
|
|
|
+
|
|
|
vq->num = state.num = virtio_queue_get_num(vdev, idx);
|
|
|
r = ioctl(dev->control, VHOST_SET_VRING_NUM, &state);
|
|
|
if (r) {
|
|
@@ -666,11 +669,12 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
|
|
|
goto fail_alloc_ring;
|
|
|
}
|
|
|
|
|
|
- r = vhost_virtqueue_set_addr(dev, vq, idx, dev->log_enabled);
|
|
|
+ r = vhost_virtqueue_set_addr(dev, vq, vhost_vq_index, dev->log_enabled);
|
|
|
if (r < 0) {
|
|
|
r = -errno;
|
|
|
goto fail_alloc;
|
|
|
}
|
|
|
+
|
|
|
file.fd = event_notifier_get_fd(virtio_queue_get_host_notifier(vvq));
|
|
|
r = ioctl(dev->control, VHOST_SET_VRING_KICK, &file);
|
|
|
if (r) {
|
|
@@ -706,9 +710,10 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
|
|
|
unsigned idx)
|
|
|
{
|
|
|
struct vhost_vring_state state = {
|
|
|
- .index = idx,
|
|
|
+ .index = idx - dev->vq_index
|
|
|
};
|
|
|
int r;
|
|
|
+ assert(idx >= dev->vq_index && idx < dev->vq_index + dev->nvqs);
|
|
|
r = ioctl(dev->control, VHOST_GET_VRING_BASE, &state);
|
|
|
if (r < 0) {
|
|
|
fprintf(stderr, "vhost VQ %d ring restore failed: %d\n", idx, r);
|
|
@@ -864,7 +869,9 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
}
|
|
|
|
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
|
- r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, true);
|
|
|
+ r = vdev->binding->set_host_notifier(vdev->binding_opaque,
|
|
|
+ hdev->vq_index + i,
|
|
|
+ true);
|
|
|
if (r < 0) {
|
|
|
fprintf(stderr, "vhost VQ %d notifier binding failed: %d\n", i, -r);
|
|
|
goto fail_vq;
|
|
@@ -874,7 +881,9 @@ int vhost_dev_enable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
return 0;
|
|
|
fail_vq:
|
|
|
while (--i >= 0) {
|
|
|
- r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false);
|
|
|
+ r = vdev->binding->set_host_notifier(vdev->binding_opaque,
|
|
|
+ hdev->vq_index + i,
|
|
|
+ false);
|
|
|
if (r < 0) {
|
|
|
fprintf(stderr, "vhost VQ %d notifier cleanup error: %d\n", i, -r);
|
|
|
fflush(stderr);
|
|
@@ -895,7 +904,9 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
int i, r;
|
|
|
|
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
|
- r = vdev->binding->set_host_notifier(vdev->binding_opaque, i, false);
|
|
|
+ r = vdev->binding->set_host_notifier(vdev->binding_opaque,
|
|
|
+ hdev->vq_index + i,
|
|
|
+ false);
|
|
|
if (r < 0) {
|
|
|
fprintf(stderr, "vhost VQ %d notifier cleanup failed: %d\n", i, -r);
|
|
|
fflush(stderr);
|
|
@@ -909,8 +920,9 @@ void vhost_dev_disable_notifiers(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
*/
|
|
|
bool vhost_virtqueue_pending(struct vhost_dev *hdev, int n)
|
|
|
{
|
|
|
- struct vhost_virtqueue *vq = hdev->vqs + n;
|
|
|
+ struct vhost_virtqueue *vq = hdev->vqs + n - hdev->vq_index;
|
|
|
assert(hdev->started);
|
|
|
+ assert(n >= hdev->vq_index && n < hdev->vq_index + hdev->nvqs);
|
|
|
return event_notifier_test_and_clear(&vq->masked_notifier);
|
|
|
}
|
|
|
|
|
@@ -919,15 +931,16 @@ void vhost_virtqueue_mask(struct vhost_dev *hdev, VirtIODevice *vdev, int n,
|
|
|
bool mask)
|
|
|
{
|
|
|
struct VirtQueue *vvq = virtio_get_queue(vdev, n);
|
|
|
- int r;
|
|
|
+ int r, index = n - hdev->vq_index;
|
|
|
|
|
|
assert(hdev->started);
|
|
|
+ assert(n >= hdev->vq_index && n < hdev->vq_index + hdev->nvqs);
|
|
|
|
|
|
struct vhost_vring_file file = {
|
|
|
- .index = n,
|
|
|
+ .index = index
|
|
|
};
|
|
|
if (mask) {
|
|
|
- file.fd = event_notifier_get_fd(&hdev->vqs[n].masked_notifier);
|
|
|
+ file.fd = event_notifier_get_fd(&hdev->vqs[index].masked_notifier);
|
|
|
} else {
|
|
|
file.fd = event_notifier_get_fd(virtio_queue_get_guest_notifier(vvq));
|
|
|
}
|
|
@@ -942,20 +955,6 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
|
|
|
hdev->started = true;
|
|
|
|
|
|
- if (!vdev->binding->set_guest_notifiers) {
|
|
|
- fprintf(stderr, "binding does not support guest notifiers\n");
|
|
|
- r = -ENOSYS;
|
|
|
- goto fail;
|
|
|
- }
|
|
|
-
|
|
|
- r = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
|
|
|
- hdev->nvqs,
|
|
|
- true);
|
|
|
- if (r < 0) {
|
|
|
- fprintf(stderr, "Error binding guest notifier: %d\n", -r);
|
|
|
- goto fail_notifiers;
|
|
|
- }
|
|
|
-
|
|
|
r = vhost_dev_set_features(hdev, hdev->log_enabled);
|
|
|
if (r < 0) {
|
|
|
goto fail_features;
|
|
@@ -967,9 +966,9 @@ int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
}
|
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
|
r = vhost_virtqueue_start(hdev,
|
|
|
- vdev,
|
|
|
- hdev->vqs + i,
|
|
|
- i);
|
|
|
+ vdev,
|
|
|
+ hdev->vqs + i,
|
|
|
+ hdev->vq_index + i);
|
|
|
if (r < 0) {
|
|
|
goto fail_vq;
|
|
|
}
|
|
@@ -992,15 +991,13 @@ fail_log:
|
|
|
fail_vq:
|
|
|
while (--i >= 0) {
|
|
|
vhost_virtqueue_stop(hdev,
|
|
|
- vdev,
|
|
|
- hdev->vqs + i,
|
|
|
- i);
|
|
|
+ vdev,
|
|
|
+ hdev->vqs + i,
|
|
|
+ hdev->vq_index + i);
|
|
|
}
|
|
|
+ i = hdev->nvqs;
|
|
|
fail_mem:
|
|
|
fail_features:
|
|
|
- vdev->binding->set_guest_notifiers(vdev->binding_opaque, hdev->nvqs, false);
|
|
|
-fail_notifiers:
|
|
|
-fail:
|
|
|
|
|
|
hdev->started = false;
|
|
|
return r;
|
|
@@ -1009,29 +1006,22 @@ fail:
|
|
|
/* Host notifiers must be enabled at this point. */
|
|
|
void vhost_dev_stop(struct vhost_dev *hdev, VirtIODevice *vdev)
|
|
|
{
|
|
|
- int i, r;
|
|
|
+ int i;
|
|
|
|
|
|
for (i = 0; i < hdev->nvqs; ++i) {
|
|
|
vhost_virtqueue_stop(hdev,
|
|
|
- vdev,
|
|
|
- hdev->vqs + i,
|
|
|
- i);
|
|
|
+ vdev,
|
|
|
+ hdev->vqs + i,
|
|
|
+ hdev->vq_index + i);
|
|
|
}
|
|
|
for (i = 0; i < hdev->n_mem_sections; ++i) {
|
|
|
vhost_sync_dirty_bitmap(hdev, &hdev->mem_sections[i],
|
|
|
0, (hwaddr)~0x0ull);
|
|
|
}
|
|
|
- r = vdev->binding->set_guest_notifiers(vdev->binding_opaque,
|
|
|
- hdev->nvqs,
|
|
|
- false);
|
|
|
- if (r < 0) {
|
|
|
- fprintf(stderr, "vhost guest notifier cleanup failed: %d\n", r);
|
|
|
- fflush(stderr);
|
|
|
- }
|
|
|
- assert (r >= 0);
|
|
|
|
|
|
hdev->started = false;
|
|
|
g_free(hdev->log);
|
|
|
hdev->log = NULL;
|
|
|
hdev->log_size = 0;
|
|
|
}
|
|
|
+
|