Skip to content

Commit

Permalink
vdpa/virtio: Fix virtio_vdpa_virtq_doorbell_relay_disable crash
Browse files Browse the repository at this point in the history
When MSIX configured less then queue number, quit testpmd in VM,
cause vDPA crash.

	Mellanox#3  0x00007fbc8421b489 in _int_free () from /lib64/libc.so.6
	Mellanox#4  0x0000000001a471c5 in virtio_vdpa_virtq_doorbell_relay_disable (vq_idx=vq_idx@entry=11, priv=<optimized out>, priv=<optimized out>) at ../drivers/vdpa/virtio/virtio_vdpa.c:349
	Mellanox#5  0x0000000001a47275 in virtio_vdpa_virtq_disable () at ../drivers/vdpa/virtio/virtio_vdpa.c:413
	Mellanox#6  0x0000000001a47a5a in virtio_vdpa_vring_state_set () at ../drivers/vdpa/virtio/virtio_vdpa.c:588
	Mellanox#7  0x00000000005ad8af in vhost_user_notify_queue_state (dev=0x17ffcd000, index=11, enable=0) at ../lib/vhost/vhost_user.c:283
	Mellanox#8  0x00000000005b0414 in vhost_user_msg_handler (vid=<optimized out>, fd=<optimized out>) at ../lib/vhost/vhost_user.c:3164
	Mellanox#9  0x00000000012f812f in vhost_user_read_cb () at ../lib/vhost/socket.c:310

When callfd == -1, virtio_pci_dev_interrupt_enable is skipped. But in
virtio_vdpa_virtq_disable, no such check to skip virtio_pci_dev_interrupt_disable.
virtio_vdpa_virtq_disable return error without changing queue state to disable.
Double free is caused by this wrong queue state.

The fix is to add/check vector_enable variable for virtio_pci_dev_interrupt_disable.
And remove error return in virtio_vdpa_virtq_disable.

RM: 3587409
Signed-off-by: Yajun Wu <yajunw@nvidia.com>
  • Loading branch information
yajwu committed Sep 11, 2023
1 parent 2bd0e06 commit 74c0ba3
Show file tree
Hide file tree
Showing 2 changed files with 17 additions and 16 deletions.
32 changes: 16 additions & 16 deletions drivers/vdpa/virtio/virtio_vdpa.c
Original file line number Diff line number Diff line change
Expand Up @@ -408,36 +408,30 @@ virtio_vdpa_virtq_doorbell_relay_enable(struct virtio_vdpa_priv *priv, int vq_id
static int
virtio_vdpa_virtq_disable(struct virtio_vdpa_priv *priv, int vq_idx)
{
struct rte_vhost_vring vq;
int ret;

ret = virtio_vdpa_virtq_doorbell_relay_disable(priv, vq_idx);
if (ret) {
DRV_LOG(ERR, "%s doorbell relay disable failed ret:%d",
priv->vdev->device->name, ret);
return ret;
}

priv->configured ? virtio_pci_dev_queue_del(priv->vpdev, vq_idx) :
virtio_pci_dev_state_queue_del(priv->vpdev, vq_idx, priv->state_mz->addr);

ret = priv->configured ? virtio_pci_dev_interrupt_disable(priv->vpdev, vq_idx + 1) :
virtio_pci_dev_state_interrupt_disable(priv->vpdev, vq_idx + 1, priv->state_mz->addr);
if (ret) {
DRV_LOG(ERR, "%s virtq %d interrupt disabel failed",
priv->vdev->device->name, vq_idx);
return ret;
}
priv->vrings[vq_idx]->notifier_state = VIRTIO_VDPA_NOTIFIER_STATE_DISABLED;
priv->vrings[vq_idx]->enable = false;

if (priv->configured) {
struct rte_vhost_vring vq;
virtio_pci_dev_queue_del(priv->vpdev, vq_idx);

if (priv->vrings[vq_idx]->vector_enable) {
ret = virtio_pci_dev_interrupt_disable(priv->vpdev, vq_idx + 1);
}
if (ret) {
DRV_LOG(ERR, "%s virtq %d interrupt disabel failed",
priv->vdev->device->name, vq_idx);
}
ret = rte_vhost_get_vhost_vring(priv->vid, vq_idx, &vq);
if (ret) {
DRV_LOG(ERR, "%s virtq %d fail to get hardware idx",
priv->vdev->device->name, vq_idx);
return ret;
}

DRV_LOG(INFO, "%s virtq %d set hardware idx:%d",
Expand All @@ -446,9 +440,13 @@ virtio_vdpa_virtq_disable(struct virtio_vdpa_priv *priv, int vq_idx)
if (ret) {
DRV_LOG(ERR, "%s virtq %d fail to set hardware idx",
priv->vdev->device->name, vq_idx);
return ret;
}
} else {
virtio_pci_dev_state_queue_del(priv->vpdev, vq_idx, priv->state_mz->addr);
virtio_pci_dev_state_interrupt_disable(priv->vpdev, vq_idx + 1, priv->state_mz->addr);
}

priv->vrings[vq_idx]->enable = false;
return 0;
}

Expand Down Expand Up @@ -483,6 +481,8 @@ virtio_vdpa_virtq_enable(struct virtio_vdpa_priv *priv, int vq_idx)
priv->vdev->device->name, ret);
return ret;
}
if (priv->configured)
priv->vrings[vq_idx]->vector_enable = true;
} else {
DRV_LOG(DEBUG, "%s virtq %d call fd is -1, interrupt is disabled",
priv->vdev->device->name, vq_idx);
Expand Down
1 change: 1 addition & 0 deletions drivers/vdpa/virtio/virtio_vdpa.h
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ struct virtio_vdpa_vring_info {
uint16_t index;
uint8_t notifier_state;
bool enable;
bool vector_enable;
struct rte_intr_handle *intr_handle;
struct virtio_vdpa_priv *priv;
};
Expand Down

0 comments on commit 74c0ba3

Please sign in to comment.