Commit 23670d8d authored by Dariusz Stojaczyk's avatar Dariusz Stojaczyk Committed by Jim Harris
Browse files

virtio: support dynamic memory registrations



We need to resend SET_MEM_TABLE whenever memory
is hotplugged or hotremoved.

Change-Id: I9bdc975f11b07866122bc49b9cf372071c5370f2
Signed-off-by: default avatarDariusz Stojaczyk <dariuszx.stojaczyk@intel.com>
Reviewed-on: https://review.gerrithub.io/422582


Chandler-Test-Pool: SPDK Automated Test System <sys_sgsw@intel.com>
Reviewed-by: default avatarChangpeng Liu <changpeng.liu@intel.com>
Reviewed-by: default avatarBen Walker <benjamin.walker@intel.com>
Reviewed-by: default avatarJim Harris <james.r.harris@intel.com>
Reviewed-by: default avatarPawel Wodkowski <pawelx.wodkowski@intel.com>
Tested-by: default avatarSPDK CI Jenkins <sys_sgci@intel.com>
parent 89f567a7
Loading
Loading
Loading
Loading
+73 −10
Original line number Diff line number Diff line
@@ -141,6 +141,67 @@ virtio_user_queue_setup(struct virtio_dev *vdev,
	return 0;
}

static int
virtio_user_map_notify(void *cb_ctx, struct spdk_mem_map *map,
		       enum spdk_mem_map_notify_action action,
		       void *vaddr, size_t size)
{
	struct virtio_dev *vdev = cb_ctx;
	struct virtio_user_dev *dev = vdev->ctx;
	uint64_t features;
	int ret;

	/* We have to resend all mappings anyway, so don't bother with any
	 * page tracking.
	 */
	ret = dev->ops->send_request(dev, VHOST_USER_SET_MEM_TABLE, NULL);
	if (ret < 0) {
		return ret;
	}

	/* We have to send SET_VRING_ADDR to make rte_vhost flush a pending
	 * SET_MEM_TABLE...
	 */
	ret = virtio_user_queue_setup(vdev, virtio_user_kick_queue);
	if (ret < 0) {
		return ret;
	}

	/* Since we might want to use that mapping straight away, we have to
	 * make sure the guest has already processed our SET_MEM_TABLE message.
	 * F_REPLY_ACK is just a feature and the host is not obliged to
	 * support it, so we send a simple message that always has a response
	 * and we wait for that response. Messages are always processed in order.
	 */
	return dev->ops->send_request(dev, VHOST_USER_GET_FEATURES, &features);
}

static int
virtio_user_register_mem(struct virtio_dev *vdev)
{
	struct virtio_user_dev *dev = vdev->ctx;
	const struct spdk_mem_map_ops virtio_user_map_ops = {
		.notify_cb = virtio_user_map_notify,
		.are_contiguous = NULL
	};

	dev->mem_map = spdk_mem_map_alloc(0, &virtio_user_map_ops, vdev);
	if (dev->mem_map == NULL) {
		SPDK_ERRLOG("spdk_mem_map_alloc() failed\n");
		return -1;
	}

	return 0;
}

static void
virtio_user_unregister_mem(struct virtio_dev *vdev)
{
	struct virtio_user_dev *dev = vdev->ctx;

	spdk_mem_map_free(&dev->mem_map);
}

static int
virtio_user_start_device(struct virtio_dev *vdev)
{
@@ -177,14 +238,7 @@ virtio_user_start_device(struct virtio_dev *vdev)
		return ret;
	}

	/* share memory regions */
	ret = dev->ops->send_request(dev, VHOST_USER_SET_MEM_TABLE, NULL);
	if (ret < 0) {
		return ret;
	}

	/* kick queues */
	ret = virtio_user_queue_setup(vdev, virtio_user_kick_queue);
	ret = virtio_user_register_mem(vdev);
	if (ret < 0) {
		return ret;
	}
@@ -192,9 +246,18 @@ virtio_user_start_device(struct virtio_dev *vdev)
	return 0;
}

static int virtio_user_stop_device(struct virtio_dev *vdev)
static int
virtio_user_stop_device(struct virtio_dev *vdev)
{
	return virtio_user_queue_setup(vdev, virtio_user_stop_queue);
	int ret;

	ret = virtio_user_queue_setup(vdev, virtio_user_stop_queue);
	/* a queue might fail to stop for various reasons, e.g. socket
	 * connection going down, but this mustn't prevent us from freeing
	 * the mem map.
	 */
	virtio_user_unregister_mem(vdev);
	return ret;
}

static int
+1 −0
Original line number Diff line number Diff line
@@ -90,6 +90,7 @@ struct virtio_user_dev {
	uint64_t	protocol_features;
	struct vring	vrings[SPDK_VIRTIO_MAX_VIRTQUEUES];
	struct virtio_user_backend_ops *ops;
	struct spdk_mem_map *mem_map;
};

struct virtio_user_backend_ops {