Skip to content

Commit

Permalink
vhost: avoid to start/stop virtqueue which is not ready
Browse files Browse the repository at this point in the history
In our Armv8a server, we try to configure the vhost scsi but fail
to boot up the guest (-machine virt-2.10). The guest's boot failure
is very early, even earlier than grub.

There are 3 virtqueues (ctrl, event and cmd) for virtio scsi device,
but ovmf and seabios will only set the physical address for the 3rd
one (cmd). Then in vhost_virtqueue_start(), virtio_queue_get_desc_addr
will be 0 for ctrl and event vq when qemu negotiates with ovmf. So
vhost_memory_map fails with ENOMEM.

This patch just fixs it by early quitting the virtqueue start/stop
when virtio_queue_get_desc_addr is 0.

Btw, after guest kernel starts, all the 3 queues will be initialized
and set address correctly.

Already tested on Arm64 and X86_64 qemu.

Signed-off-by: Jia He <[email protected]>
Reviewed-by: Michael S. Tsirkin <[email protected]>
Signed-off-by: Michael S. Tsirkin <[email protected]>
  • Loading branch information
hejianet authored and mstsirkin committed Mar 1, 2018
1 parent 9e2a2a3 commit fb20fbb
Showing 1 changed file with 17 additions and 1 deletion.
18 changes: 17 additions & 1 deletion hw/virtio/vhost.c
Original file line number Diff line number Diff line change
Expand Up @@ -345,6 +345,10 @@ static int vhost_verify_ring_mappings(struct vhost_dev *dev,
for (i = 0; i < dev->nvqs; ++i) {
struct vhost_virtqueue *vq = dev->vqs + i;

if (vq->desc_phys == 0) {
continue;
}

j = 0;
r = vhost_verify_ring_part_mapping(
vq->desc, vq->desc_phys, vq->desc_size,
Expand Down Expand Up @@ -881,6 +885,11 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
};
struct VirtQueue *vvq = virtio_get_queue(vdev, idx);

a = virtio_queue_get_desc_addr(vdev, idx);
if (a == 0) {
/* Queue might not be ready for start */
return 0;
}

vq->num = state.num = virtio_queue_get_num(vdev, idx);
r = dev->vhost_ops->vhost_set_vring_num(dev, &state);
Expand All @@ -906,7 +915,7 @@ static int vhost_virtqueue_start(struct vhost_dev *dev,
}

vq->desc_size = s = l = virtio_queue_get_desc_size(vdev, idx);
vq->desc_phys = a = virtio_queue_get_desc_addr(vdev, idx);
vq->desc_phys = a;
vq->desc = vhost_memory_map(dev, a, &l, 0);
if (!vq->desc || l != s) {
r = -ENOMEM;
Expand Down Expand Up @@ -989,6 +998,13 @@ static void vhost_virtqueue_stop(struct vhost_dev *dev,
.index = vhost_vq_index,
};
int r;
int a;

a = virtio_queue_get_desc_addr(vdev, idx);
if (a == 0) {
/* Don't stop the virtqueue which might have not been started */
return;
}

r = dev->vhost_ops->vhost_get_vring_base(dev, &state);
if (r < 0) {
Expand Down

0 comments on commit fb20fbb

Please sign in to comment.