Skip to content

Commit 2c66de6

Browse files
committed
vdpa-dev: Fix initialisation order to restore VDUSE compatibility
VDUSE requires that virtqueues are first enabled before the DRIVER_OK status flag is set; with the current API of the kernel module, it is impossible to enable the opposite order in our block export code because userspace is not notified when a virtqueue is enabled. This requirement also mathces the normal initialisation order as done by the generic vhost code in QEMU. However, commit 6c48254 accidentally changed the order for vdpa-dev and broke access to VDUSE devices with this. This changes vdpa-dev to use the normal order again and use the standard vhost callback .vhost_set_vring_enable for this. VDUSE devices can be used with vdpa-dev again after this fix. vhost_net intentionally avoided enabling the vrings for vdpa and does this manually later while it does enable them for other vhost backends. Reflect this in the vhost_net code and return early for vdpa, so that the behaviour doesn't change for this device. Cc: [email protected] Fixes: 6c48254 ('vdpa: move vhost_vdpa_set_vring_ready to the caller') Signed-off-by: Kevin Wolf <[email protected]> Message-ID: <[email protected]> Reviewed-by: Eugenio Pérez <[email protected]> Reviewed-by: Stefano Garzarella <[email protected]> Signed-off-by: Kevin Wolf <[email protected]>
1 parent d9e4070 commit 2c66de6

File tree

5 files changed

+45
-9
lines changed

5 files changed

+45
-9
lines changed

hw/net/vhost_net.c

+10
Original file line numberDiff line numberDiff line change
@@ -541,6 +541,16 @@ int vhost_set_vring_enable(NetClientState *nc, int enable)
541541
VHostNetState *net = get_vhost_net(nc);
542542
const VhostOps *vhost_ops = net->dev.vhost_ops;
543543

544+
/*
545+
* vhost-vdpa network devices need to enable dataplane virtqueues after
546+
* DRIVER_OK, so they can recover device state before starting dataplane.
547+
* Because of that, we don't enable virtqueues here and leave it to
548+
* net/vhost-vdpa.c.
549+
*/
550+
if (nc->info->type == NET_CLIENT_DRIVER_VHOST_VDPA) {
551+
return 0;
552+
}
553+
544554
nc->vring_enable = enable;
545555

546556
if (vhost_ops && vhost_ops->vhost_set_vring_enable) {

hw/virtio/trace-events

+1-1
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ vhost_vdpa_set_features(void *dev, uint64_t features) "dev: %p features: 0x%"PRI
4949
vhost_vdpa_get_device_id(void *dev, uint32_t device_id) "dev: %p device_id %"PRIu32
5050
vhost_vdpa_reset_device(void *dev) "dev: %p"
5151
vhost_vdpa_get_vq_index(void *dev, int idx, int vq_idx) "dev: %p idx: %d vq idx: %d"
52-
vhost_vdpa_set_vring_ready(void *dev, unsigned i, int r) "dev: %p, idx: %u, r: %d"
52+
vhost_vdpa_set_vring_enable_one(void *dev, unsigned i, int enable, int r) "dev: %p, idx: %u, enable: %u, r: %d"
5353
vhost_vdpa_dump_config(void *dev, const char *line) "dev: %p %s"
5454
vhost_vdpa_set_config(void *dev, uint32_t offset, uint32_t size, uint32_t flags) "dev: %p offset: %"PRIu32" size: %"PRIu32" flags: 0x%"PRIx32
5555
vhost_vdpa_get_config(void *dev, void *config, uint32_t config_len) "dev: %p config: %p config_len: %"PRIu32

hw/virtio/vdpa-dev.c

+1-4
Original file line numberDiff line numberDiff line change
@@ -253,14 +253,11 @@ static int vhost_vdpa_device_start(VirtIODevice *vdev, Error **errp)
253253

254254
s->dev.acked_features = vdev->guest_features;
255255

256-
ret = vhost_dev_start(&s->dev, vdev, false);
256+
ret = vhost_dev_start(&s->dev, vdev, true);
257257
if (ret < 0) {
258258
error_setg_errno(errp, -ret, "Error starting vhost");
259259
goto err_guest_notifiers;
260260
}
261-
for (i = 0; i < s->dev.nvqs; ++i) {
262-
vhost_vdpa_set_vring_ready(&s->vdpa, i);
263-
}
264261
s->started = true;
265262

266263
/*

hw/virtio/vhost-vdpa.c

+26-3
Original file line numberDiff line numberDiff line change
@@ -896,19 +896,41 @@ static int vhost_vdpa_get_vq_index(struct vhost_dev *dev, int idx)
896896
return idx;
897897
}
898898

899-
int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx)
899+
static int vhost_vdpa_set_vring_enable_one(struct vhost_vdpa *v, unsigned idx,
900+
int enable)
900901
{
901902
struct vhost_dev *dev = v->dev;
902903
struct vhost_vring_state state = {
903904
.index = idx,
904-
.num = 1,
905+
.num = enable,
905906
};
906907
int r = vhost_vdpa_call(dev, VHOST_VDPA_SET_VRING_ENABLE, &state);
907908

908-
trace_vhost_vdpa_set_vring_ready(dev, idx, r);
909+
trace_vhost_vdpa_set_vring_enable_one(dev, idx, enable, r);
909910
return r;
910911
}
911912

913+
static int vhost_vdpa_set_vring_enable(struct vhost_dev *dev, int enable)
914+
{
915+
struct vhost_vdpa *v = dev->opaque;
916+
unsigned int i;
917+
int ret;
918+
919+
for (i = 0; i < dev->nvqs; ++i) {
920+
ret = vhost_vdpa_set_vring_enable_one(v, i, enable);
921+
if (ret < 0) {
922+
return ret;
923+
}
924+
}
925+
926+
return 0;
927+
}
928+
929+
int vhost_vdpa_set_vring_ready(struct vhost_vdpa *v, unsigned idx)
930+
{
931+
return vhost_vdpa_set_vring_enable_one(v, idx, 1);
932+
}
933+
912934
static int vhost_vdpa_set_config_call(struct vhost_dev *dev,
913935
int fd)
914936
{
@@ -1536,6 +1558,7 @@ const VhostOps vdpa_ops = {
15361558
.vhost_set_features = vhost_vdpa_set_features,
15371559
.vhost_reset_device = vhost_vdpa_reset_device,
15381560
.vhost_get_vq_index = vhost_vdpa_get_vq_index,
1561+
.vhost_set_vring_enable = vhost_vdpa_set_vring_enable,
15391562
.vhost_get_config = vhost_vdpa_get_config,
15401563
.vhost_set_config = vhost_vdpa_set_config,
15411564
.vhost_requires_shm_log = NULL,

hw/virtio/vhost.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -1984,7 +1984,13 @@ static int vhost_dev_set_vring_enable(struct vhost_dev *hdev, int enable)
19841984
return hdev->vhost_ops->vhost_set_vring_enable(hdev, enable);
19851985
}
19861986

1987-
/* Host notifiers must be enabled at this point. */
1987+
/*
1988+
* Host notifiers must be enabled at this point.
1989+
*
1990+
* If @vrings is true, this function will enable all vrings before starting the
1991+
* device. If it is false, the vring initialization is left to be done by the
1992+
* caller.
1993+
*/
19881994
int vhost_dev_start(struct vhost_dev *hdev, VirtIODevice *vdev, bool vrings)
19891995
{
19901996
int i, r;

0 commit comments

Comments
 (0)