Linux virtualization list
 help / color / mirror / Atom feed
* [PATCH 3/5] update virtio gpu driver: add 3d/virgl support
From: Gerd Hoffmann @ 2015-09-09 11:42 UTC (permalink / raw)
  To: dri-devel
  Cc: Michael S. Tsirkin, David Airlie, open list:ABI/API, open list,
	open list:VIRTIO GPU DRIVER, Dave Airlie
In-Reply-To: <1441798946-26233-1-git-send-email-kraxel@redhat.com>

Add the bits needed for opengl rendering support: query
capabilities, new virtio commands, drm ioctls.

Signed-off-by: Dave Airlie <airlied@redhat.com>
Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/virtio/Makefile        |   3 +-
 drivers/gpu/drm/virtio/virtgpu_drv.c   |  10 +
 drivers/gpu/drm/virtio/virtgpu_drv.h   |  60 ++++
 drivers/gpu/drm/virtio/virtgpu_gem.c   |  41 +++
 drivers/gpu/drm/virtio/virtgpu_ioctl.c | 572 +++++++++++++++++++++++++++++++++
 drivers/gpu/drm/virtio/virtgpu_kms.c   | 135 +++++++-
 drivers/gpu/drm/virtio/virtgpu_ttm.c   |   1 +
 drivers/gpu/drm/virtio/virtgpu_vq.c    | 265 +++++++++++++++
 include/uapi/drm/Kbuild                |   1 +
 include/uapi/drm/virtgpu_drm.h         | 163 ++++++++++
 include/uapi/linux/virtio_gpu.h        | 112 ++++++-
 11 files changed, 1360 insertions(+), 3 deletions(-)
 create mode 100644 drivers/gpu/drm/virtio/virtgpu_ioctl.c
 create mode 100644 include/uapi/drm/virtgpu_drm.h

diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile
index 2ee1602..da7bf19 100644
--- a/drivers/gpu/drm/virtio/Makefile
+++ b/drivers/gpu/drm/virtio/Makefile
@@ -6,6 +6,7 @@ ccflags-y := -Iinclude/drm
 
 virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_drm_bus.o virtgpu_gem.o \
 	virtgpu_fb.o virtgpu_display.o virtgpu_vq.o virtgpu_ttm.o \
-	virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o
+	virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
+	virtgpu_ioctl.o
 
 obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.c b/drivers/gpu/drm/virtio/virtgpu_drv.c
index 7d9610a..957e455 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.c
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.c
@@ -73,6 +73,9 @@ static struct virtio_device_id id_table[] = {
 };
 
 static unsigned int features[] = {
+#ifdef __LITTLE_ENDIAN
+	VIRTIO_GPU_FEATURE_VIRGL,
+#endif
 };
 static struct virtio_driver virtio_gpu_driver = {
 	.feature_table = features,
@@ -114,6 +117,8 @@ static struct drm_driver driver = {
 	.set_busid = drm_virtio_set_busid,
 	.load = virtio_gpu_driver_load,
 	.unload = virtio_gpu_driver_unload,
+	.open = virtio_gpu_driver_open,
+	.postclose = virtio_gpu_driver_postclose,
 
 	.dumb_create = virtio_gpu_mode_dumb_create,
 	.dumb_map_offset = virtio_gpu_mode_dumb_mmap,
@@ -125,8 +130,13 @@ static struct drm_driver driver = {
 #endif
 
 	.gem_free_object = virtio_gpu_gem_free_object,
+	.gem_open_object = virtio_gpu_gem_object_open,
+	.gem_close_object = virtio_gpu_gem_object_close,
 	.fops = &virtio_gpu_driver_fops,
 
+	.ioctls = virtio_gpu_ioctls,
+	.num_ioctls = DRM_VIRTIO_NUM_IOCTLS,
+
 	.name = DRIVER_NAME,
 	.desc = DRIVER_DESC,
 	.date = DRIVER_DATE,
diff --git a/drivers/gpu/drm/virtio/virtgpu_drv.h b/drivers/gpu/drm/virtio/virtgpu_drv.h
index 6d4db2d..2719108 100644
--- a/drivers/gpu/drm/virtio/virtgpu_drv.h
+++ b/drivers/gpu/drm/virtio/virtgpu_drv.h
@@ -146,6 +146,21 @@ struct virtio_gpu_queue {
 	struct work_struct dequeue_work;
 };
 
+struct virtio_gpu_drv_capset {
+	uint32_t id;
+	uint32_t max_version;
+	uint32_t max_size;
+};
+
+struct virtio_gpu_drv_cap_cache {
+	struct list_head head;
+	void *caps_cache;
+	uint32_t id;
+	uint32_t version;
+	uint32_t size;
+	atomic_t is_valid;
+};
+
 struct virtio_gpu_device {
 	struct device *dev;
 	struct drm_device *ddev;
@@ -179,7 +194,13 @@ struct virtio_gpu_device {
 	struct idr	ctx_id_idr;
 	spinlock_t ctx_id_idr_lock;
 
+	bool has_virgl_3d;
+
 	struct work_struct config_changed_work;
+
+	struct virtio_gpu_drv_capset *capsets;
+	uint32_t num_capsets;
+	struct list_head cap_cache;
 };
 
 struct virtio_gpu_fpriv {
@@ -193,6 +214,8 @@ extern struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS];
 /* virtio_kms.c */
 int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags);
 int virtio_gpu_driver_unload(struct drm_device *dev);
+int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file);
+void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file);
 
 /* virtio_gem.c */
 void virtio_gpu_gem_free_object(struct drm_gem_object *gem_obj);
@@ -203,6 +226,10 @@ int virtio_gpu_gem_create(struct drm_file *file,
 			  uint64_t size,
 			  struct drm_gem_object **obj_p,
 			  uint32_t *handle_p);
+int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
+			       struct drm_file *file);
+void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
+				 struct drm_file *file);
 struct virtio_gpu_object *virtio_gpu_alloc_object(struct drm_device *dev,
 						  size_t size, bool kernel,
 						  bool pinned);
@@ -260,10 +287,43 @@ void virtio_gpu_cursor_ping(struct virtio_gpu_device *vgdev,
 int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev);
 void virtio_gpu_cmd_resource_inval_backing(struct virtio_gpu_device *vgdev,
 					   uint32_t resource_id);
+int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx);
+int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+			      int idx, int version,
+			      struct virtio_gpu_drv_cap_cache **cache_p);
+void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
+				   uint32_t nlen, const char *name);
+void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
+				    uint32_t id);
+void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
+					    uint32_t ctx_id,
+					    uint32_t resource_id);
+void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
+					    uint32_t ctx_id,
+					    uint32_t resource_id);
+void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
+			   void *data, uint32_t data_size,
+			   uint32_t ctx_id, struct virtio_gpu_fence **fence);
+void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
+					  uint32_t resource_id, uint32_t ctx_id,
+					  uint64_t offset, uint32_t level,
+					  struct virtio_gpu_box *box,
+					  struct virtio_gpu_fence **fence);
+void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
+					uint32_t resource_id, uint32_t ctx_id,
+					uint64_t offset, uint32_t level,
+					struct virtio_gpu_box *box,
+					struct virtio_gpu_fence **fence);
+void
+virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
+				  struct virtio_gpu_resource_create_3d *rc_3d,
+				  struct virtio_gpu_fence **fence);
 void virtio_gpu_ctrl_ack(struct virtqueue *vq);
 void virtio_gpu_cursor_ack(struct virtqueue *vq);
+void virtio_gpu_fence_ack(struct virtqueue *vq);
 void virtio_gpu_dequeue_ctrl_func(struct work_struct *work);
 void virtio_gpu_dequeue_cursor_func(struct work_struct *work);
+void virtio_gpu_dequeue_fence_func(struct work_struct *work);
 
 /* virtio_gpu_display.c */
 int virtio_gpu_framebuffer_init(struct drm_device *dev,
diff --git a/drivers/gpu/drm/virtio/virtgpu_gem.c b/drivers/gpu/drm/virtio/virtgpu_gem.c
index cfa0d27..1feb7ce 100644
--- a/drivers/gpu/drm/virtio/virtgpu_gem.c
+++ b/drivers/gpu/drm/virtio/virtgpu_gem.c
@@ -138,3 +138,44 @@ int virtio_gpu_mode_dumb_mmap(struct drm_file *file_priv,
 	drm_gem_object_unreference_unlocked(gobj);
 	return 0;
 }
+
+int virtio_gpu_gem_object_open(struct drm_gem_object *obj,
+			       struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = obj->dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+	struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
+	int r;
+
+	if (!vgdev->has_virgl_3d)
+		return 0;
+
+	r = virtio_gpu_object_reserve(qobj, false);
+	if (r)
+		return r;
+
+	virtio_gpu_cmd_context_attach_resource(vgdev, vfpriv->ctx_id,
+					       qobj->hw_res_handle);
+	virtio_gpu_object_unreserve(qobj);
+	return 0;
+}
+
+void virtio_gpu_gem_object_close(struct drm_gem_object *obj,
+				 struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = obj->dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+	struct virtio_gpu_object *qobj = gem_to_virtio_gpu_obj(obj);
+	int r;
+
+	if (!vgdev->has_virgl_3d)
+		return;
+
+	r = virtio_gpu_object_reserve(qobj, false);
+	if (r)
+		return;
+
+	virtio_gpu_cmd_context_detach_resource(vgdev, vfpriv->ctx_id,
+						qobj->hw_res_handle);
+	virtio_gpu_object_unreserve(qobj);
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ioctl.c b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
new file mode 100644
index 0000000..d5c9e02
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_ioctl.c
@@ -0,0 +1,572 @@
+/*
+ * Copyright (C) 2015 Red Hat, Inc.
+ * All Rights Reserved.
+ *
+ * Authors:
+ *    Dave Airlie
+ *    Alon Levy
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE COPYRIGHT HOLDER(S) OR AUTHOR(S) BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+
+#include <drm/drmP.h>
+#include "virtgpu_drv.h"
+#include <drm/virtgpu_drm.h>
+#include "ttm/ttm_execbuf_util.h"
+
+static void convert_to_hw_box(struct virtio_gpu_box *dst,
+			      const struct drm_virtgpu_3d_box *src)
+{
+	dst->x = cpu_to_le32(src->x);
+	dst->y = cpu_to_le32(src->y);
+	dst->z = cpu_to_le32(src->z);
+	dst->w = cpu_to_le32(src->w);
+	dst->h = cpu_to_le32(src->h);
+	dst->d = cpu_to_le32(src->d);
+}
+
+static int virtio_gpu_map_ioctl(struct drm_device *dev, void *data,
+				struct drm_file *file_priv)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct drm_virtgpu_map *virtio_gpu_map = data;
+
+	return virtio_gpu_mode_dumb_mmap(file_priv, vgdev->ddev,
+					 virtio_gpu_map->handle,
+					 &virtio_gpu_map->offset);
+}
+
+static int virtio_gpu_object_list_validate(struct ww_acquire_ctx *ticket,
+					   struct list_head *head)
+{
+	struct ttm_validate_buffer *buf;
+	struct ttm_buffer_object *bo;
+	struct virtio_gpu_object *qobj;
+	int ret;
+
+	ret = ttm_eu_reserve_buffers(ticket, head, true, NULL);
+	if (ret != 0)
+		return ret;
+
+	list_for_each_entry(buf, head, head) {
+		bo = buf->bo;
+		qobj = container_of(bo, struct virtio_gpu_object, tbo);
+		ret = ttm_bo_validate(bo, &qobj->placement, false, false);
+		if (ret) {
+			ttm_eu_backoff_reservation(ticket, head);
+			return ret;
+		}
+	}
+	return 0;
+}
+
+static void virtio_gpu_unref_list(struct list_head *head)
+{
+	struct ttm_validate_buffer *buf;
+	struct ttm_buffer_object *bo;
+	struct virtio_gpu_object *qobj;
+	list_for_each_entry(buf, head, head) {
+		bo = buf->bo;
+		qobj = container_of(bo, struct virtio_gpu_object, tbo);
+
+		drm_gem_object_unreference_unlocked(&qobj->gem_base);
+	}
+}
+
+static int virtio_gpu_execbuffer(struct drm_device *dev,
+				 struct drm_virtgpu_execbuffer *exbuf,
+				 struct drm_file *drm_file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv = drm_file->driver_priv;
+	struct drm_gem_object *gobj;
+	struct virtio_gpu_fence *fence;
+	struct virtio_gpu_object *qobj;
+	int ret;
+	uint32_t *bo_handles = NULL;
+	void __user *user_bo_handles = NULL;
+	struct list_head validate_list;
+	struct ttm_validate_buffer *buflist = NULL;
+	struct ttm_validate_buffer cmdbuffer;
+	int i;
+	struct ww_acquire_ctx ticket;
+	void *buf;
+
+	if (vgdev->has_virgl_3d == false)
+		return -ENOSYS;
+
+	memset(&cmdbuffer, 0, sizeof(struct ttm_validate_buffer));
+	INIT_LIST_HEAD(&validate_list);
+	if (exbuf->num_bo_handles) {
+
+		bo_handles = drm_malloc_ab(exbuf->num_bo_handles,
+					   sizeof(uint32_t));
+		buflist = drm_calloc_large(exbuf->num_bo_handles,
+					   sizeof(struct ttm_validate_buffer));
+		if (!bo_handles || !buflist) {
+			drm_free_large(bo_handles);
+			drm_free_large(buflist);
+			return -ENOMEM;
+		}
+
+		user_bo_handles = (void __user *)(uintptr_t)exbuf->bo_handles;
+		if (copy_from_user(bo_handles, user_bo_handles,
+				   exbuf->num_bo_handles * sizeof(uint32_t))) {
+			ret = -EFAULT;
+			drm_free_large(bo_handles);
+			return ret;
+		}
+
+		for (i = 0; i < exbuf->num_bo_handles; i++) {
+			gobj = drm_gem_object_lookup(dev,
+						     drm_file, bo_handles[i]);
+			if (!gobj) {
+				drm_free_large(bo_handles);
+				drm_free_large(buflist);
+				return -ENOENT;
+			}
+
+			qobj = gem_to_virtio_gpu_obj(gobj);
+			buflist[i].bo = &qobj->tbo;
+
+			list_add(&buflist[i].head, &validate_list);
+		}
+		drm_free_large(bo_handles);
+	}
+
+	ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
+	if (ret)
+		goto out_free;
+
+	buf = kmalloc(exbuf->size, GFP_KERNEL);
+	if (!buf) {
+		ret = -ENOMEM;
+		goto out_unresv;
+	}
+	if (copy_from_user(buf, (void __user *)(uintptr_t)exbuf->command,
+			   exbuf->size)) {
+		kfree(buf);
+		ret = -EFAULT;
+		goto out_unresv;
+	}
+	virtio_gpu_cmd_submit(vgdev, buf, exbuf->size,
+			      vfpriv->ctx_id, &fence);
+
+	ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
+
+	/* fence the command bo */
+	virtio_gpu_unref_list(&validate_list);
+	drm_free_large(buflist);
+	fence_put(&fence->f);
+	return 0;
+
+out_unresv:
+	ttm_eu_backoff_reservation(&ticket, &validate_list);
+out_free:
+	virtio_gpu_unref_list(&validate_list);
+	drm_free_large(buflist);
+	return ret;
+}
+
+/*
+ * Usage of execbuffer:
+ * Relocations need to take into account the full VIRTIO_GPUDrawable size.
+ * However, the command as passed from user space must *not* contain the initial
+ * VIRTIO_GPUReleaseInfo struct (first XXX bytes)
+ */
+static int virtio_gpu_execbuffer_ioctl(struct drm_device *dev, void *data,
+				       struct drm_file *file_priv)
+{
+	struct drm_virtgpu_execbuffer *execbuffer = data;
+	return virtio_gpu_execbuffer(dev, execbuffer, file_priv);
+}
+
+
+static int virtio_gpu_getparam_ioctl(struct drm_device *dev, void *data,
+				     struct drm_file *file_priv)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct drm_virtgpu_getparam *param = data;
+	int value;
+
+	switch (param->param) {
+	case VIRTGPU_PARAM_3D_FEATURES:
+		value = vgdev->has_virgl_3d == true ? 1 : 0;
+		break;
+	default:
+		return -EINVAL;
+	}
+	if (copy_to_user((void __user *)(unsigned long)param->value,
+			 &value, sizeof(int))) {
+		return -EFAULT;
+	}
+	return 0;
+}
+
+static int virtio_gpu_resource_create_ioctl(struct drm_device *dev, void *data,
+					    struct drm_file *file_priv)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct drm_virtgpu_resource_create *rc = data;
+	int ret;
+	uint32_t res_id;
+	struct virtio_gpu_object *qobj;
+	struct drm_gem_object *obj;
+	uint32_t handle = 0;
+	uint32_t size;
+	struct list_head validate_list;
+	struct ttm_validate_buffer mainbuf;
+	struct virtio_gpu_fence *fence = NULL;
+	struct ww_acquire_ctx ticket;
+	struct virtio_gpu_resource_create_3d rc_3d;
+
+	if (vgdev->has_virgl_3d == false) {
+		if (rc->depth > 1)
+			return -EINVAL;
+		if (rc->nr_samples > 1)
+			return -EINVAL;
+		if (rc->last_level > 1)
+			return -EINVAL;
+		if (rc->target != 2)
+			return -EINVAL;
+		if (rc->array_size > 1)
+			return -EINVAL;
+	}
+
+	INIT_LIST_HEAD(&validate_list);
+	memset(&mainbuf, 0, sizeof(struct ttm_validate_buffer));
+
+	virtio_gpu_resource_id_get(vgdev, &res_id);
+
+	size = rc->size;
+
+	/* allocate a single page size object */
+	if (size == 0)
+		size = PAGE_SIZE;
+
+	qobj = virtio_gpu_alloc_object(dev, size, false, false);
+	if (IS_ERR(qobj)) {
+		ret = PTR_ERR(qobj);
+		goto fail_id;
+	}
+	obj = &qobj->gem_base;
+
+	if (!vgdev->has_virgl_3d) {
+		virtio_gpu_cmd_create_resource(vgdev, res_id, rc->format,
+					       rc->width, rc->height);
+
+		ret = virtio_gpu_object_attach(vgdev, qobj, res_id, NULL);
+	} else {
+		/* use a gem reference since unref list undoes them */
+		drm_gem_object_reference(&qobj->gem_base);
+		mainbuf.bo = &qobj->tbo;
+		list_add(&mainbuf.head, &validate_list);
+
+		ret = virtio_gpu_object_list_validate(&ticket, &validate_list);
+		if (ret) {
+			DRM_DEBUG("failed to validate\n");
+			goto fail_unref;
+		}
+
+		rc_3d.resource_id = cpu_to_le32(res_id);
+		rc_3d.target = cpu_to_le32(rc->target);
+		rc_3d.format = cpu_to_le32(rc->format);
+		rc_3d.bind = cpu_to_le32(rc->bind);
+		rc_3d.width = cpu_to_le32(rc->width);
+		rc_3d.height = cpu_to_le32(rc->height);
+		rc_3d.depth = cpu_to_le32(rc->depth);
+		rc_3d.array_size = cpu_to_le32(rc->array_size);
+		rc_3d.last_level = cpu_to_le32(rc->last_level);
+		rc_3d.nr_samples = cpu_to_le32(rc->nr_samples);
+		rc_3d.flags = cpu_to_le32(rc->flags);
+
+		virtio_gpu_cmd_resource_create_3d(vgdev, &rc_3d, NULL);
+		ret = virtio_gpu_object_attach(vgdev, qobj, res_id, &fence);
+		if (ret)
+			goto fail_unref;
+		ttm_eu_fence_buffer_objects(&ticket, &validate_list, &fence->f);
+	}
+
+	qobj->hw_res_handle = res_id;
+
+	ret = drm_gem_handle_create(file_priv, obj, &handle);
+	if (ret) {
+
+		drm_gem_object_release(obj);
+		if (vgdev->has_virgl_3d) {
+			virtio_gpu_unref_list(&validate_list);
+			fence_put(&fence->f);
+		}
+		return ret;
+	}
+	drm_gem_object_unreference_unlocked(obj);
+
+	rc->res_handle = res_id; /* similiar to a VM address */
+	rc->bo_handle = handle;
+
+	if (vgdev->has_virgl_3d) {
+		virtio_gpu_unref_list(&validate_list);
+		fence_put(&fence->f);
+	}
+	return 0;
+fail_unref:
+	if (vgdev->has_virgl_3d) {
+		virtio_gpu_unref_list(&validate_list);
+		fence_put(&fence->f);
+	}
+//fail_obj:
+//	drm_gem_object_handle_unreference_unlocked(obj);
+fail_id:
+	virtio_gpu_resource_id_put(vgdev, res_id);
+	return ret;
+}
+
+static int virtio_gpu_resource_info_ioctl(struct drm_device *dev, void *data,
+					  struct drm_file *file_priv)
+{
+	struct drm_virtgpu_resource_info *ri = data;
+	struct drm_gem_object *gobj = NULL;
+	struct virtio_gpu_object *qobj = NULL;
+
+	gobj = drm_gem_object_lookup(dev, file_priv, ri->bo_handle);
+	if (gobj == NULL)
+		return -ENOENT;
+
+	qobj = gem_to_virtio_gpu_obj(gobj);
+
+	ri->size = qobj->gem_base.size;
+	ri->res_handle = qobj->hw_res_handle;
+	drm_gem_object_unreference_unlocked(gobj);
+	return 0;
+}
+
+static int virtio_gpu_transfer_from_host_ioctl(struct drm_device *dev,
+					       void *data,
+					       struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+	struct drm_virtgpu_3d_transfer_from_host *args = data;
+	struct drm_gem_object *gobj = NULL;
+	struct virtio_gpu_object *qobj = NULL;
+	struct virtio_gpu_fence *fence;
+	int ret;
+	u32 offset = args->offset;
+	struct virtio_gpu_box box;
+
+	if (vgdev->has_virgl_3d == false)
+		return -ENOSYS;
+
+	gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+	if (gobj == NULL)
+		return -ENOENT;
+
+	qobj = gem_to_virtio_gpu_obj(gobj);
+
+	ret = virtio_gpu_object_reserve(qobj, false);
+	if (ret)
+		goto out;
+
+	ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
+			      true, false);
+	if (unlikely(ret))
+		goto out_unres;
+
+	convert_to_hw_box(&box, &args->box);
+	virtio_gpu_cmd_transfer_from_host_3d
+		(vgdev, qobj->hw_res_handle,
+		 vfpriv->ctx_id, offset, args->level,
+		 &box, &fence);
+	reservation_object_add_excl_fence(qobj->tbo.resv,
+					  &fence->f);
+
+	fence_put(&fence->f);
+out_unres:
+	virtio_gpu_object_unreserve(qobj);
+out:
+	drm_gem_object_unreference_unlocked(gobj);
+	return ret;
+}
+
+static int virtio_gpu_transfer_to_host_ioctl(struct drm_device *dev, void *data,
+					     struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv = file->driver_priv;
+	struct drm_virtgpu_3d_transfer_to_host *args = data;
+	struct drm_gem_object *gobj = NULL;
+	struct virtio_gpu_object *qobj = NULL;
+	struct virtio_gpu_fence *fence;
+	struct virtio_gpu_box box;
+	int ret;
+	u32 offset = args->offset;
+
+	gobj = drm_gem_object_lookup(dev, file, args->bo_handle);
+	if (gobj == NULL)
+		return -ENOENT;
+
+	qobj = gem_to_virtio_gpu_obj(gobj);
+
+	ret = virtio_gpu_object_reserve(qobj, false);
+	if (ret)
+		goto out;
+
+	ret = ttm_bo_validate(&qobj->tbo, &qobj->placement,
+			      true, false);
+	if (unlikely(ret))
+		goto out_unres;
+
+	convert_to_hw_box(&box, &args->box);
+	if (!vgdev->has_virgl_3d) {
+		virtio_gpu_cmd_transfer_to_host_2d
+			(vgdev, qobj->hw_res_handle, offset,
+			 box.w, box.h, box.x, box.y, NULL);
+	} else {
+		virtio_gpu_cmd_transfer_to_host_3d
+			(vgdev, qobj->hw_res_handle,
+			 vfpriv ? vfpriv->ctx_id : 0, offset,
+			 args->level, &box, &fence);
+		reservation_object_add_excl_fence(qobj->tbo.resv,
+						  &fence->f);
+		fence_put(&fence->f);
+	}
+
+out_unres:
+	virtio_gpu_object_unreserve(qobj);
+out:
+	drm_gem_object_unreference_unlocked(gobj);
+	return ret;
+}
+
+static int virtio_gpu_wait_ioctl(struct drm_device *dev, void *data,
+			    struct drm_file *file)
+{
+	struct drm_virtgpu_3d_wait *args = data;
+	struct drm_gem_object *gobj = NULL;
+	struct virtio_gpu_object *qobj = NULL;
+	int ret;
+	bool nowait = false;
+
+	gobj = drm_gem_object_lookup(dev, file, args->handle);
+	if (gobj == NULL)
+		return -ENOENT;
+
+	qobj = gem_to_virtio_gpu_obj(gobj);
+
+	if (args->flags & VIRTGPU_WAIT_NOWAIT)
+		nowait = true;
+	ret = virtio_gpu_object_wait(qobj, nowait);
+
+	drm_gem_object_unreference_unlocked(gobj);
+	return ret;
+}
+
+static int virtio_gpu_get_caps_ioctl(struct drm_device *dev,
+				void *data, struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct drm_virtgpu_get_caps *args = data;
+	int size;
+	int i;
+	int found_valid = -1;
+	int ret;
+	struct virtio_gpu_drv_cap_cache *cache_ent;
+	void *ptr;
+	if (vgdev->num_capsets == 0)
+		return -ENOSYS;
+
+	spin_lock(&vgdev->display_info_lock);
+	for (i = 0; i < vgdev->num_capsets; i++) {
+		if (vgdev->capsets[i].id == args->cap_set_id) {
+			if (vgdev->capsets[i].max_version >= args->cap_set_ver) {
+				found_valid = i;
+				break;
+			}
+		}
+	}
+
+	if (found_valid == -1) {
+		spin_unlock(&vgdev->display_info_lock);
+		return -EINVAL;
+	}
+
+	size = vgdev->capsets[found_valid].max_size;
+	if (args->size > size) {
+		spin_unlock(&vgdev->display_info_lock);
+		return -EINVAL;
+	}
+
+	list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
+		if (cache_ent->id == args->cap_set_id &&
+		    cache_ent->version == args->cap_set_ver) {
+			ptr = cache_ent->caps_cache;
+			spin_unlock(&vgdev->display_info_lock);
+			goto copy_exit;
+		}
+	}
+	spin_unlock(&vgdev->display_info_lock);
+
+	/* not in cache - need to talk to hw */
+	virtio_gpu_cmd_get_capset(vgdev, found_valid, args->cap_set_ver,
+				  &cache_ent);
+
+	ret = wait_event_timeout(vgdev->resp_wq,
+				 atomic_read(&cache_ent->is_valid), 5 * HZ);
+
+	ptr = cache_ent->caps_cache;
+
+copy_exit:
+	if (copy_to_user((void __user *)(unsigned long)args->addr, ptr, size))
+		return -EFAULT;
+
+	return 0;
+}
+
+struct drm_ioctl_desc virtio_gpu_ioctls[DRM_VIRTIO_NUM_IOCTLS] = {
+	DRM_IOCTL_DEF_DRV(VIRTGPU_MAP, virtio_gpu_map_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_EXECBUFFER, virtio_gpu_execbuffer_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_GETPARAM, virtio_gpu_getparam_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_CREATE,
+			  virtio_gpu_resource_create_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_RESOURCE_INFO, virtio_gpu_resource_info_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	/* make transfer async to the main ring? - no sure, can we
+	   thread these in the underlying GL */
+	DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_FROM_HOST,
+			  virtio_gpu_transfer_from_host_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+	DRM_IOCTL_DEF_DRV(VIRTGPU_TRANSFER_TO_HOST,
+			  virtio_gpu_transfer_to_host_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_WAIT, virtio_gpu_wait_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+
+	DRM_IOCTL_DEF_DRV(VIRTGPU_GET_CAPS, virtio_gpu_get_caps_ioctl,
+			  DRM_AUTH|DRM_UNLOCKED),
+};
diff --git a/drivers/gpu/drm/virtio/virtgpu_kms.c b/drivers/gpu/drm/virtio/virtgpu_kms.c
index 782766c..12a1091 100644
--- a/drivers/gpu/drm/virtio/virtgpu_kms.c
+++ b/drivers/gpu/drm/virtio/virtgpu_kms.c
@@ -52,6 +52,41 @@ static void virtio_gpu_config_changed_work_func(struct work_struct *work)
 		      events_clear, &events_clear);
 }
 
+static void virtio_gpu_ctx_id_get(struct virtio_gpu_device *vgdev,
+				  uint32_t *resid)
+{
+	int handle;
+
+	idr_preload(GFP_KERNEL);
+	spin_lock(&vgdev->ctx_id_idr_lock);
+	handle = idr_alloc(&vgdev->ctx_id_idr, NULL, 1, 0, 0);
+	spin_unlock(&vgdev->ctx_id_idr_lock);
+	idr_preload_end();
+	*resid = handle;
+}
+
+static void virtio_gpu_ctx_id_put(struct virtio_gpu_device *vgdev, uint32_t id)
+{
+	spin_lock(&vgdev->ctx_id_idr_lock);
+	idr_remove(&vgdev->ctx_id_idr, id);
+	spin_unlock(&vgdev->ctx_id_idr_lock);
+}
+
+static void virtio_gpu_context_create(struct virtio_gpu_device *vgdev,
+				      uint32_t nlen, const char *name,
+				      uint32_t *ctx_id)
+{
+	virtio_gpu_ctx_id_get(vgdev, ctx_id);
+	virtio_gpu_cmd_context_create(vgdev, *ctx_id, nlen, name);
+}
+
+static void virtio_gpu_context_destroy(struct virtio_gpu_device *vgdev,
+				      uint32_t ctx_id)
+{
+	virtio_gpu_cmd_context_destroy(vgdev, ctx_id);
+	virtio_gpu_ctx_id_put(vgdev, ctx_id);
+}
+
 static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
 			       void (*work_func)(struct work_struct *work))
 {
@@ -60,6 +95,36 @@ static void virtio_gpu_init_vq(struct virtio_gpu_queue *vgvq,
 	INIT_WORK(&vgvq->dequeue_work, work_func);
 }
 
+static void virtio_gpu_get_capsets(struct virtio_gpu_device *vgdev,
+				   int num_capsets)
+{
+	int i, ret;
+
+	vgdev->capsets = kcalloc(num_capsets,
+				 sizeof(struct virtio_gpu_drv_capset),
+				 GFP_KERNEL);
+	if (!vgdev->capsets) {
+		DRM_ERROR("failed to allocate cap sets\n");
+		return;
+	}
+	for (i = 0; i < num_capsets; i++) {
+		virtio_gpu_cmd_get_capset_info(vgdev, i);
+		ret = wait_event_timeout(vgdev->resp_wq,
+					 vgdev->capsets[i].id > 0, 5 * HZ);
+		if (ret == 0) {
+			DRM_ERROR("timed out waiting for cap set %d\n", i);
+			kfree(vgdev->capsets);
+			vgdev->capsets = NULL;
+			return;
+		}
+		DRM_INFO("cap set %d: id %d, max-version %d, max-size %d\n",
+			 i, vgdev->capsets[i].id,
+			 vgdev->capsets[i].max_version,
+			 vgdev->capsets[i].max_size);
+	}
+	vgdev->num_capsets = num_capsets;
+}
+
 int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 {
 	static vq_callback_t *callbacks[] = {
@@ -70,7 +135,7 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 	struct virtio_gpu_device *vgdev;
 	/* this will expand later */
 	struct virtqueue *vqs[2];
-	u32 num_scanouts;
+	u32 num_scanouts, num_capsets;
 	int ret;
 
 	if (!virtio_has_feature(dev->virtdev, VIRTIO_F_VERSION_1))
@@ -96,9 +161,17 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 
 	spin_lock_init(&vgdev->fence_drv.lock);
 	INIT_LIST_HEAD(&vgdev->fence_drv.fences);
+	INIT_LIST_HEAD(&vgdev->cap_cache);
 	INIT_WORK(&vgdev->config_changed_work,
 		  virtio_gpu_config_changed_work_func);
 
+#ifdef __LITTLE_ENDIAN
+	if (virtio_has_feature(vgdev->vdev, VIRTIO_GPU_FEATURE_VIRGL))
+		vgdev->has_virgl_3d = true;
+#endif
+	DRM_INFO("virgl 3d acceleration %s\n",
+		 vgdev->has_virgl_3d ? "enabled" : "not available");
+
 	ret = vgdev->vdev->config->find_vqs(vgdev->vdev, 2, vqs,
 					    callbacks, names);
 	if (ret) {
@@ -129,6 +202,11 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 		ret = -EINVAL;
 		goto err_scanouts;
 	}
+	DRM_INFO("number of scanouts: %d\n", num_scanouts);
+
+	virtio_cread(vgdev->vdev, struct virtio_gpu_config,
+		     num_capsets, &num_capsets);
+	DRM_INFO("number of cap sets: %d\n", num_capsets);
 
 	ret = virtio_gpu_modeset_init(vgdev);
 	if (ret)
@@ -137,6 +215,8 @@ int virtio_gpu_driver_load(struct drm_device *dev, unsigned long flags)
 	virtio_device_ready(vgdev->vdev);
 	vgdev->vqs_ready = true;
 
+	if (num_capsets)
+		virtio_gpu_get_capsets(vgdev, num_capsets);
 	virtio_gpu_cmd_get_display_info(vgdev);
 	wait_event_timeout(vgdev->resp_wq, !vgdev->display_info_pending,
 			   5 * HZ);
@@ -157,6 +237,16 @@ err_vqs:
 	return ret;
 }
 
+static void virtio_gpu_cleanup_cap_cache(struct virtio_gpu_device *vgdev)
+{
+	struct virtio_gpu_drv_cap_cache *cache_ent, *tmp;
+
+	list_for_each_entry_safe(cache_ent, tmp, &vgdev->cap_cache, head) {
+		kfree(cache_ent->caps_cache);
+		kfree(cache_ent);
+	}
+}
+
 int virtio_gpu_driver_unload(struct drm_device *dev)
 {
 	struct virtio_gpu_device *vgdev = dev->dev_private;
@@ -170,6 +260,49 @@ int virtio_gpu_driver_unload(struct drm_device *dev)
 	virtio_gpu_modeset_fini(vgdev);
 	virtio_gpu_ttm_fini(vgdev);
 	virtio_gpu_free_vbufs(vgdev);
+	virtio_gpu_cleanup_cap_cache(vgdev);
+	kfree(vgdev->capsets);
 	kfree(vgdev);
 	return 0;
 }
+
+int virtio_gpu_driver_open(struct drm_device *dev, struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv;
+	uint32_t id;
+	char dbgname[64], tmpname[TASK_COMM_LEN];
+
+	/* can't create contexts without 3d renderer */
+	if (!vgdev->has_virgl_3d)
+		return 0;
+
+	get_task_comm(tmpname, current);
+	snprintf(dbgname, sizeof(dbgname), "%s", tmpname);
+	dbgname[63] = 0;
+	/* allocate a virt GPU context for this opener */
+	vfpriv = kzalloc(sizeof(*vfpriv), GFP_KERNEL);
+	if (!vfpriv)
+		return -ENOMEM;
+
+	virtio_gpu_context_create(vgdev, strlen(dbgname), dbgname, &id);
+
+	vfpriv->ctx_id = id;
+	file->driver_priv = vfpriv;
+	return 0;
+}
+
+void virtio_gpu_driver_postclose(struct drm_device *dev, struct drm_file *file)
+{
+	struct virtio_gpu_device *vgdev = dev->dev_private;
+	struct virtio_gpu_fpriv *vfpriv;
+
+	if (!vgdev->has_virgl_3d)
+		return;
+
+	vfpriv = file->driver_priv;
+
+	virtio_gpu_context_destroy(vgdev, vfpriv->ctx_id);
+	kfree(vfpriv);
+	file->driver_priv = NULL;
+}
diff --git a/drivers/gpu/drm/virtio/virtgpu_ttm.c b/drivers/gpu/drm/virtio/virtgpu_ttm.c
index b092d7b..9fd924c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_ttm.c
+++ b/drivers/gpu/drm/virtio/virtgpu_ttm.c
@@ -32,6 +32,7 @@
 #include <ttm/ttm_module.h>
 #include <drm/drmP.h>
 #include <drm/drm.h>
+#include <drm/virtgpu_drm.h>
 #include "virtgpu_drv.h"
 
 #include <linux/delay.h>
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 111ab1a..dea9697 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -586,6 +586,47 @@ static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
 		drm_kms_helper_hotplug_event(vgdev->ddev);
 }
 
+static void virtio_gpu_cmd_get_capset_info_cb(struct virtio_gpu_device *vgdev,
+					      struct virtio_gpu_vbuffer *vbuf)
+{
+	struct virtio_gpu_get_capset_info *cmd =
+		(struct virtio_gpu_get_capset_info *)vbuf->buf;
+	struct virtio_gpu_resp_capset_info *resp =
+		(struct virtio_gpu_resp_capset_info *)vbuf->resp_buf;
+	int i = le32_to_cpu(cmd->capset_index);
+
+	spin_lock(&vgdev->display_info_lock);
+	vgdev->capsets[i].id = le32_to_cpu(resp->capset_id);
+	vgdev->capsets[i].max_version = le32_to_cpu(resp->capset_max_version);
+	vgdev->capsets[i].max_size = le32_to_cpu(resp->capset_max_size);
+	spin_unlock(&vgdev->display_info_lock);
+	wake_up(&vgdev->resp_wq);
+}
+
+static void virtio_gpu_cmd_capset_cb(struct virtio_gpu_device *vgdev,
+				     struct virtio_gpu_vbuffer *vbuf)
+{
+	struct virtio_gpu_get_capset *cmd =
+		(struct virtio_gpu_get_capset *)vbuf->buf;
+	struct virtio_gpu_resp_capset *resp =
+		(struct virtio_gpu_resp_capset *)vbuf->resp_buf;
+	struct virtio_gpu_drv_cap_cache *cache_ent;
+
+	spin_lock(&vgdev->display_info_lock);
+	list_for_each_entry(cache_ent, &vgdev->cap_cache, head) {
+		if (cache_ent->version == le32_to_cpu(cmd->capset_version) &&
+		    cache_ent->id == le32_to_cpu(cmd->capset_id)) {
+			memcpy(cache_ent->caps_cache, resp->capset_data,
+			       cache_ent->size);
+			atomic_set(&cache_ent->is_valid, 1);
+			break;
+		}
+	}
+	spin_unlock(&vgdev->display_info_lock);
+	wake_up(&vgdev->resp_wq);
+}
+
+
 int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
 {
 	struct virtio_gpu_ctrl_hdr *cmd_p;
@@ -609,6 +650,230 @@ int virtio_gpu_cmd_get_display_info(struct virtio_gpu_device *vgdev)
 	return 0;
 }
 
+int virtio_gpu_cmd_get_capset_info(struct virtio_gpu_device *vgdev, int idx)
+{
+	struct virtio_gpu_get_capset_info *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+	void *resp_buf;
+
+	resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset_info),
+			   GFP_KERNEL);
+	if (!resp_buf)
+		return -ENOMEM;
+
+	cmd_p = virtio_gpu_alloc_cmd_resp
+		(vgdev, &virtio_gpu_cmd_get_capset_info_cb, &vbuf,
+		 sizeof(*cmd_p), sizeof(struct virtio_gpu_resp_capset_info),
+		 resp_buf);
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET_INFO);
+	cmd_p->capset_index = cpu_to_le32(idx);
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+	return 0;
+}
+
+int virtio_gpu_cmd_get_capset(struct virtio_gpu_device *vgdev,
+			      int idx, int version,
+			      struct virtio_gpu_drv_cap_cache **cache_p)
+{
+	struct virtio_gpu_get_capset *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+	int max_size = vgdev->capsets[idx].max_size;
+	struct virtio_gpu_drv_cap_cache *cache_ent;
+	void *resp_buf;
+
+	if (idx > vgdev->num_capsets)
+		return -EINVAL;
+
+	if (version > vgdev->capsets[idx].max_version)
+		return -EINVAL;
+
+	cache_ent = kzalloc(sizeof(*cache_ent), GFP_KERNEL);
+	if (!cache_ent)
+		return -ENOMEM;
+
+	cache_ent->caps_cache = kmalloc(max_size, GFP_KERNEL);
+	if (!cache_ent->caps_cache) {
+		kfree(cache_ent);
+		return -ENOMEM;
+	}
+
+	resp_buf = kzalloc(sizeof(struct virtio_gpu_resp_capset) + max_size,
+			   GFP_KERNEL);
+	if (!resp_buf) {
+		kfree(cache_ent->caps_cache);
+		kfree(cache_ent);
+		return -ENOMEM;
+	}
+
+	cache_ent->version = version;
+	cache_ent->id = vgdev->capsets[idx].id;
+	atomic_set(&cache_ent->is_valid, 0);
+	cache_ent->size = max_size;
+	spin_lock(&vgdev->display_info_lock);
+	list_add_tail(&cache_ent->head, &vgdev->cap_cache);
+	spin_unlock(&vgdev->display_info_lock);
+
+	cmd_p = virtio_gpu_alloc_cmd_resp
+		(vgdev, &virtio_gpu_cmd_capset_cb, &vbuf, sizeof(*cmd_p),
+		 sizeof(struct virtio_gpu_resp_capset) + max_size,
+		 resp_buf);
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_GET_CAPSET);
+	cmd_p->capset_id = cpu_to_le32(vgdev->capsets[idx].id);
+	cmd_p->capset_version = cpu_to_le32(version);
+	*cache_p = cache_ent;
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+
+	return 0;
+}
+
+void virtio_gpu_cmd_context_create(struct virtio_gpu_device *vgdev, uint32_t id,
+				   uint32_t nlen, const char *name)
+{
+	struct virtio_gpu_ctx_create *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_CREATE);
+	cmd_p->hdr.ctx_id = cpu_to_le32(id);
+	cmd_p->nlen = cpu_to_le32(nlen);
+	strncpy(cmd_p->debug_name, name, 63);
+	cmd_p->debug_name[63] = 0;
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void virtio_gpu_cmd_context_destroy(struct virtio_gpu_device *vgdev,
+				    uint32_t id)
+{
+	struct virtio_gpu_ctx_destroy *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DESTROY);
+	cmd_p->hdr.ctx_id = cpu_to_le32(id);
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void virtio_gpu_cmd_context_attach_resource(struct virtio_gpu_device *vgdev,
+					    uint32_t ctx_id,
+					    uint32_t resource_id)
+{
+	struct virtio_gpu_ctx_resource *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE);
+	cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+	cmd_p->resource_id = cpu_to_le32(resource_id);
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+
+}
+
+void virtio_gpu_cmd_context_detach_resource(struct virtio_gpu_device *vgdev,
+					    uint32_t ctx_id,
+					    uint32_t resource_id)
+{
+	struct virtio_gpu_ctx_resource *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE);
+	cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+	cmd_p->resource_id = cpu_to_le32(resource_id);
+	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+}
+
+void
+virtio_gpu_cmd_resource_create_3d(struct virtio_gpu_device *vgdev,
+				  struct virtio_gpu_resource_create_3d *rc_3d,
+				  struct virtio_gpu_fence **fence)
+{
+	struct virtio_gpu_resource_create_3d *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	*cmd_p = *rc_3d;
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_3D);
+	cmd_p->hdr.flags = 0;
+
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_transfer_to_host_3d(struct virtio_gpu_device *vgdev,
+					uint32_t resource_id, uint32_t ctx_id,
+					uint64_t offset, uint32_t level,
+					struct virtio_gpu_box *box,
+					struct virtio_gpu_fence **fence)
+{
+	struct virtio_gpu_transfer_host_3d *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D);
+	cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+	cmd_p->resource_id = cpu_to_le32(resource_id);
+	cmd_p->box = *box;
+	cmd_p->offset = cpu_to_le64(offset);
+	cmd_p->level = cpu_to_le32(level);
+
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_transfer_from_host_3d(struct virtio_gpu_device *vgdev,
+					  uint32_t resource_id, uint32_t ctx_id,
+					  uint64_t offset, uint32_t level,
+					  struct virtio_gpu_box *box,
+					  struct virtio_gpu_fence **fence)
+{
+	struct virtio_gpu_transfer_host_3d *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D);
+	cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+	cmd_p->resource_id = cpu_to_le32(resource_id);
+	cmd_p->box = *box;
+	cmd_p->offset = cpu_to_le64(offset);
+	cmd_p->level = cpu_to_le32(level);
+
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
+void virtio_gpu_cmd_submit(struct virtio_gpu_device *vgdev,
+			   void *data, uint32_t data_size,
+			   uint32_t ctx_id, struct virtio_gpu_fence **fence)
+{
+	struct virtio_gpu_cmd_submit *cmd_p;
+	struct virtio_gpu_vbuffer *vbuf;
+
+	cmd_p = virtio_gpu_alloc_cmd(vgdev, &vbuf, sizeof(*cmd_p));
+	memset(cmd_p, 0, sizeof(*cmd_p));
+
+	vbuf->data_buf = data;
+	vbuf->data_size = data_size;
+
+	cmd_p->hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SUBMIT_3D);
+	cmd_p->hdr.ctx_id = cpu_to_le32(ctx_id);
+	cmd_p->size = cpu_to_le32(data_size);
+
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
+}
+
 int virtio_gpu_object_attach(struct virtio_gpu_device *vgdev,
 			     struct virtio_gpu_object *obj,
 			     uint32_t resource_id,
diff --git a/include/uapi/drm/Kbuild b/include/uapi/drm/Kbuild
index 2d9a25d..38d4370 100644
--- a/include/uapi/drm/Kbuild
+++ b/include/uapi/drm/Kbuild
@@ -17,3 +17,4 @@ header-y += tegra_drm.h
 header-y += via_drm.h
 header-y += vmwgfx_drm.h
 header-y += msm_drm.h
+header-y += virtgpu_drm.h
diff --git a/include/uapi/drm/virtgpu_drm.h b/include/uapi/drm/virtgpu_drm.h
new file mode 100644
index 0000000..fcc789e
--- /dev/null
+++ b/include/uapi/drm/virtgpu_drm.h
@@ -0,0 +1,163 @@
+/*
+ * Copyright 2013 Red Hat
+ * All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
+ * THE AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
+ * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
+ * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
+ * OTHER DEALINGS IN THE SOFTWARE.
+ */
+#ifndef VIRTGPU_DRM_H
+#define VIRTGPU_DRM_H
+
+#include <stddef.h>
+#include "drm/drm.h"
+
+/* Please note that modifications to all structs defined here are
+ * subject to backwards-compatibility constraints.
+ *
+ * Do not use pointers, use uint64_t instead for 32 bit / 64 bit user/kernel
+ * compatibility Keep fields aligned to their size
+ */
+
+#define DRM_VIRTGPU_MAP         0x01
+#define DRM_VIRTGPU_EXECBUFFER  0x02
+#define DRM_VIRTGPU_GETPARAM    0x03
+#define DRM_VIRTGPU_RESOURCE_CREATE 0x04
+#define DRM_VIRTGPU_RESOURCE_INFO     0x05
+#define DRM_VIRTGPU_TRANSFER_FROM_HOST 0x06
+#define DRM_VIRTGPU_TRANSFER_TO_HOST 0x07
+#define DRM_VIRTGPU_WAIT     0x08
+#define DRM_VIRTGPU_GET_CAPS  0x09
+
+struct drm_virtgpu_map {
+	uint64_t offset; /* use for mmap system call */
+	uint32_t handle;
+	uint32_t pad;
+};
+
+struct drm_virtgpu_execbuffer {
+	uint32_t		flags;		/* for future use */
+	uint32_t size;
+	uint64_t command; /* void* */
+	uint64_t bo_handles;
+	uint32_t num_bo_handles;
+	uint32_t pad;
+};
+
+#define VIRTGPU_PARAM_3D_FEATURES 1 /* do we have 3D features in the hw */
+
+struct drm_virtgpu_getparam {
+	uint64_t param;
+	uint64_t value;
+};
+
+/* NO_BO flags? NO resource flag? */
+/* resource flag for y_0_top */
+struct drm_virtgpu_resource_create {
+	uint32_t target;
+	uint32_t format;
+	uint32_t bind;
+	uint32_t width;
+	uint32_t height;
+	uint32_t depth;
+	uint32_t array_size;
+	uint32_t last_level;
+	uint32_t nr_samples;
+	uint32_t flags;
+	uint32_t bo_handle; /* if this is set - recreate a new resource attached to this bo ? */
+	uint32_t res_handle;  /* returned by kernel */
+	uint32_t size;        /* validate transfer in the host */
+	uint32_t stride;      /* validate transfer in the host */
+};
+
+struct drm_virtgpu_resource_info {
+	uint32_t bo_handle;
+	uint32_t res_handle;
+	uint32_t size;
+	uint32_t stride;
+};
+
+struct drm_virtgpu_3d_box {
+	uint32_t x, y, z;
+	uint32_t w, h, d;
+};
+
+struct drm_virtgpu_3d_transfer_to_host {
+	uint32_t bo_handle;
+	struct drm_virtgpu_3d_box box;
+	uint32_t level;
+	uint32_t offset;
+};
+
+struct drm_virtgpu_3d_transfer_from_host {
+	uint32_t bo_handle;
+	struct drm_virtgpu_3d_box box;
+	uint32_t level;
+	uint32_t offset;
+};
+
+#define VIRTGPU_WAIT_NOWAIT 1 /* like it */
+struct drm_virtgpu_3d_wait {
+	uint32_t handle; /* 0 is an invalid handle */
+	uint32_t flags;
+};
+
+struct drm_virtgpu_get_caps {
+	uint32_t cap_set_id;
+	uint32_t cap_set_ver;
+	uint64_t addr;
+	uint32_t size;
+	uint32_t pad;
+};
+
+#define DRM_IOCTL_VIRTGPU_MAP \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_MAP, struct drm_virtgpu_map)
+
+#define DRM_IOCTL_VIRTGPU_EXECBUFFER \
+	DRM_IOW(DRM_COMMAND_BASE + DRM_VIRTGPU_EXECBUFFER,\
+		struct drm_virtgpu_execbuffer)
+
+#define DRM_IOCTL_VIRTGPU_GETPARAM \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GETPARAM,\
+		struct drm_virtgpu_getparam)
+
+#define DRM_IOCTL_VIRTGPU_RESOURCE_CREATE			\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_CREATE,	\
+		struct drm_virtgpu_resource_create)
+
+#define DRM_IOCTL_VIRTGPU_RESOURCE_INFO \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_RESOURCE_INFO, \
+		 struct drm_virtgpu_resource_info)
+
+#define DRM_IOCTL_VIRTGPU_TRANSFER_FROM_HOST \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_FROM_HOST,	\
+		struct drm_virtgpu_3d_transfer_from_host)
+
+#define DRM_IOCTL_VIRTGPU_TRANSFER_TO_HOST \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_TRANSFER_TO_HOST,	\
+		struct drm_virtgpu_3d_transfer_to_host)
+
+#define DRM_IOCTL_VIRTGPU_WAIT				\
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_WAIT,	\
+		struct drm_virtgpu_3d_wait)
+
+#define DRM_IOCTL_VIRTGPU_GET_CAPS \
+	DRM_IOWR(DRM_COMMAND_BASE + DRM_VIRTGPU_GET_CAPS, \
+	struct drm_virtgpu_get_caps)
+
+#endif
diff --git a/include/uapi/linux/virtio_gpu.h b/include/uapi/linux/virtio_gpu.h
index 478be52..7f4f9ce 100644
--- a/include/uapi/linux/virtio_gpu.h
+++ b/include/uapi/linux/virtio_gpu.h
@@ -40,6 +40,8 @@
 
 #include <linux/types.h>
 
+#define VIRTIO_GPU_FEATURE_VIRGL 0
+
 enum virtio_gpu_ctrl_type {
 	VIRTIO_GPU_UNDEFINED = 0,
 
@@ -52,6 +54,18 @@ enum virtio_gpu_ctrl_type {
 	VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D,
 	VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING,
 	VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING,
+	VIRTIO_GPU_CMD_GET_CAPSET_INFO,
+	VIRTIO_GPU_CMD_GET_CAPSET,
+
+	/* 3d commands */
+	VIRTIO_GPU_CMD_CTX_CREATE = 0x0200,
+	VIRTIO_GPU_CMD_CTX_DESTROY,
+	VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE,
+	VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE,
+	VIRTIO_GPU_CMD_RESOURCE_CREATE_3D,
+	VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D,
+	VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D,
+	VIRTIO_GPU_CMD_SUBMIT_3D,
 
 	/* cursor commands */
 	VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
@@ -60,6 +74,8 @@ enum virtio_gpu_ctrl_type {
 	/* success responses */
 	VIRTIO_GPU_RESP_OK_NODATA = 0x1100,
 	VIRTIO_GPU_RESP_OK_DISPLAY_INFO,
+	VIRTIO_GPU_RESP_OK_CAPSET_INFO,
+	VIRTIO_GPU_RESP_OK_CAPSET,
 
 	/* error responses */
 	VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
@@ -180,13 +196,107 @@ struct virtio_gpu_resp_display_info {
 	} pmodes[VIRTIO_GPU_MAX_SCANOUTS];
 };
 
+/* data passed in the control vq, 3d related */
+
+struct virtio_gpu_box {
+	__le32 x, y, z;
+	__le32 w, h, d;
+};
+
+/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_3D, VIRTIO_GPU_CMD_TRANSFER_FROM_HOST_3D */
+struct virtio_gpu_transfer_host_3d {
+	struct virtio_gpu_ctrl_hdr hdr;
+	struct virtio_gpu_box box;
+	__le64 offset;
+	__le32 resource_id;
+	__le32 level;
+	__le32 stride;
+	__le32 layer_stride;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_CREATE_3D */
+#define VIRTIO_GPU_RESOURCE_FLAG_Y_0_TOP (1 << 0)
+struct virtio_gpu_resource_create_3d {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 resource_id;
+	__le32 target;
+	__le32 format;
+	__le32 bind;
+	__le32 width;
+	__le32 height;
+	__le32 depth;
+	__le32 array_size;
+	__le32 last_level;
+	__le32 nr_samples;
+	__le32 flags;
+	__le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_CTX_CREATE */
+struct virtio_gpu_ctx_create {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 nlen;
+	__le32 padding;
+	char debug_name[64];
+};
+
+/* VIRTIO_GPU_CMD_CTX_DESTROY */
+struct virtio_gpu_ctx_destroy {
+	struct virtio_gpu_ctrl_hdr hdr;
+};
+
+/* VIRTIO_GPU_CMD_CTX_ATTACH_RESOURCE, VIRTIO_GPU_CMD_CTX_DETACH_RESOURCE */
+struct virtio_gpu_ctx_resource {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 resource_id;
+	__le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_SUBMIT_3D */
+struct virtio_gpu_cmd_submit {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 size;
+	__le32 padding;
+};
+
+#define VIRTIO_GPU_CAPSET_VIRGL 1
+
+/* VIRTIO_GPU_CMD_GET_CAPSET_INFO */
+struct virtio_gpu_get_capset_info {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 capset_index;
+	__le32 padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_CAPSET_INFO */
+struct virtio_gpu_resp_capset_info {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 capset_id;
+	__le32 capset_max_version;
+	__le32 capset_max_size;
+	__le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_GET_CAPSET */
+struct virtio_gpu_get_capset {
+	struct virtio_gpu_ctrl_hdr hdr;
+	__le32 capset_id;
+	__le32 capset_version;
+};
+
+/* VIRTIO_GPU_RESP_OK_CAPSET */
+struct virtio_gpu_resp_capset {
+	struct virtio_gpu_ctrl_hdr hdr;
+	uint8_t capset_data[];
+};
+
 #define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
 
 struct virtio_gpu_config {
 	__u32 events_read;
 	__u32 events_clear;
 	__u32 num_scanouts;
-	__u32 reserved;
+	__u32 num_capsets;
 };
 
 /* simple formats for fbcon/X use */
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 2/5] virtio-gpu: add & use virtio_gpu_queue_fenced_ctrl_buffer
From: Gerd Hoffmann @ 2015-09-09 11:42 UTC (permalink / raw)
  To: dri-devel; +Cc: David Airlie, open list, open list:VIRTIO GPU DRIVER
In-Reply-To: <1441798946-26233-1-git-send-email-kraxel@redhat.com>

Add helper function to handle the submission of fenced control requests.
Make sure we initialize the fence while holding the virtqueue lock, so
requests can't be reordered.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/virtio/virtgpu_fence.c |  2 +-
 drivers/gpu/drm/virtio/virtgpu_vq.c    | 40 +++++++++++++++++++++++++++++-----
 2 files changed, 35 insertions(+), 7 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index 1da6326..793ad9f 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -81,7 +81,7 @@ int virtio_gpu_fence_emit(struct virtio_gpu_device *vgdev,
 	struct virtio_gpu_fence_driver *drv = &vgdev->fence_drv;
 	unsigned long irq_flags;
 
-	*fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_KERNEL);
+	*fence = kmalloc(sizeof(struct virtio_gpu_fence), GFP_ATOMIC);
 	if ((*fence) == NULL)
 		return -ENOMEM;
 
diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index b9275c7..111ab1a 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -347,6 +347,38 @@ static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
 	return rc;
 }
 
+static int virtio_gpu_queue_fenced_ctrl_buffer(struct virtio_gpu_device *vgdev,
+					       struct virtio_gpu_vbuffer *vbuf,
+					       struct virtio_gpu_ctrl_hdr *hdr,
+					       struct virtio_gpu_fence **fence)
+{
+	struct virtqueue *vq = vgdev->ctrlq.vq;
+	int rc;
+
+again:
+	spin_lock(&vgdev->ctrlq.qlock);
+
+	/*
+	 * Make sure we have enouth space in the virtqueue.  If not
+	 * wait here until we have.
+	 *
+	 * Without that virtio_gpu_queue_ctrl_buffer_nolock might have
+	 * to wait for free space, which can result in fence ids being
+	 * submitted out-of-order.
+	 */
+	if (vq->num_free < 3) {
+		spin_unlock(&vgdev->ctrlq.qlock);
+		wait_event(vgdev->ctrlq.ack_queue, vq->num_free >= 3);
+		goto again;
+	}
+
+	if (fence)
+		virtio_gpu_fence_emit(vgdev, hdr, fence);
+	rc = virtio_gpu_queue_ctrl_buffer_nolock(vgdev, vbuf);
+	spin_unlock(&vgdev->ctrlq.qlock);
+	return rc;
+}
+
 static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
 				   struct virtio_gpu_vbuffer *vbuf)
 {
@@ -499,9 +531,7 @@ void virtio_gpu_cmd_transfer_to_host_2d(struct virtio_gpu_device *vgdev,
 	cmd_p->r.x = x;
 	cmd_p->r.y = y;
 
-	if (fence)
-		virtio_gpu_fence_emit(vgdev, &cmd_p->hdr, fence);
-	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
 }
 
 static void
@@ -524,9 +554,7 @@ virtio_gpu_cmd_resource_attach_backing(struct virtio_gpu_device *vgdev,
 	vbuf->data_buf = ents;
 	vbuf->data_size = sizeof(*ents) * nents;
 
-	if (fence)
-		virtio_gpu_fence_emit(vgdev, &cmd_p->hdr, fence);
-	virtio_gpu_queue_ctrl_buffer(vgdev, vbuf);
+	virtio_gpu_queue_fenced_ctrl_buffer(vgdev, vbuf, &cmd_p->hdr, fence);
 }
 
 static void virtio_gpu_cmd_get_display_info_cb(struct virtio_gpu_device *vgdev,
-- 
1.8.3.1

^ permalink raw reply related

* [PATCH 1/5] virtio-gpu: add virtio_gpu_queue_ctrl_buffer_nolock
From: Gerd Hoffmann @ 2015-09-09 11:42 UTC (permalink / raw)
  To: dri-devel; +Cc: David Airlie, open list, open list:VIRTIO GPU DRIVER
In-Reply-To: <1441798946-26233-1-git-send-email-kraxel@redhat.com>

Add virtio_gpu_queue_ctrl_buffer_nolock function, which does the same as
virtio_gpu_queue_ctrl_buffer but does not take the virtqueue lock.  The
caller must hold the lock instead.

Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
---
 drivers/gpu/drm/virtio/virtgpu_vq.c | 17 +++++++++++++----
 1 file changed, 13 insertions(+), 4 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_vq.c b/drivers/gpu/drm/virtio/virtgpu_vq.c
index 1698669f..b9275c7 100644
--- a/drivers/gpu/drm/virtio/virtgpu_vq.c
+++ b/drivers/gpu/drm/virtio/virtgpu_vq.c
@@ -293,8 +293,8 @@ void virtio_gpu_dequeue_cursor_func(struct work_struct *work)
 	wake_up(&vgdev->cursorq.ack_queue);
 }
 
-static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
-					struct virtio_gpu_vbuffer *vbuf)
+static int virtio_gpu_queue_ctrl_buffer_nolock(struct virtio_gpu_device *vgdev,
+					       struct virtio_gpu_vbuffer *vbuf)
 {
 	struct virtqueue *vq = vgdev->ctrlq.vq;
 	struct scatterlist *sgs[3], vcmd, vout, vresp;
@@ -320,7 +320,6 @@ static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
 		incnt++;
 	}
 
-	spin_lock(&vgdev->ctrlq.qlock);
 retry:
 	ret = virtqueue_add_sgs(vq, sgs, outcnt, incnt, vbuf, GFP_ATOMIC);
 	if (ret == -ENOSPC) {
@@ -331,13 +330,23 @@ retry:
 	} else {
 		virtqueue_kick(vq);
 	}
-	spin_unlock(&vgdev->ctrlq.qlock);
 
 	if (!ret)
 		ret = vq->num_free;
 	return ret;
 }
 
+static int virtio_gpu_queue_ctrl_buffer(struct virtio_gpu_device *vgdev,
+					struct virtio_gpu_vbuffer *vbuf)
+{
+	int rc;
+
+	spin_lock(&vgdev->ctrlq.qlock);
+	rc = virtio_gpu_queue_ctrl_buffer_nolock(vgdev, vbuf);
+	spin_unlock(&vgdev->ctrlq.qlock);
+	return rc;
+}
+
 static int virtio_gpu_queue_cursor(struct virtio_gpu_device *vgdev,
 				   struct virtio_gpu_vbuffer *vbuf)
 {
-- 
1.8.3.1

^ permalink raw reply related

* Call for Papers - WorldCIST'15 - Best papers published by ISI/SCI journals
From: Maria Lemos @ 2015-09-09  9:45 UTC (permalink / raw)
  To: virtualization

[-- Attachment #1: Type: text/plain, Size: 7239 bytes --]

*
** Please disseminate by your contacts.
** Thank you!
* 

---------
WorldCIST'16 - 4th World Conference on Information Systems and Technologies 
Recife, PE, Brazil
22th-24th of March 2016
http://www.aisti.eu/worldcist16/
-------------------------------------------


SCOPE

The WorldCist'16 - 4th World Conference on Information Systems and Technologies, to be held at Recife, PE, Brazil, 22 - 24 March 2016, is a global forum for researchers and practitioners to present and discuss the most recent innovations, trends, results, experiences and concerns in the several perspectives of Information Systems and Technologies.

We are pleased to invite you to submit your papers to WorldCist'16. All submissions will be reviewed on the basis of relevance, originality, importance and clarity.


THEMES

Submitted papers should be related with one or more of the main themes proposed for the Conference:

A) Information and Knowledge Management (IKM);
B) Organizational Models and Information Systems (OMIS);
C) Software and Systems Modeling (SSM);
D) Software Systems, Architectures, Applications and Tools (SSAAT);
E) Multimedia Systems and Applications (MSA);
F) Computer Networks, Mobility and Pervasive Systems (CNMPS);
G) Intelligent and Decision Support Systems (IDSS);
H) Big Data Analytics and Applications (BDAA);
I) Human-Computer Interaction (HCI);
J) Health Informatics (HIS);
K) Information Technologies in Education (ITE);
L) Information Technologies in Radiocommunications (ITR).


TYPES OF SUBMISSIONS AND DECISIONS

Four types of papers can be submitted:

- Full paper: Finished or consolidated R&D works, to be included in one of the Conference themes. These papers are assigned a 10-page limit.

- Short paper: Ongoing works with relevant preliminary results, open to discussion. These papers are assigned a 7-page limit.

-Poster paper: Initial work with relevant ideas, open to discussion. These papers are assigned to a 4-page limit.

- Company paper: Companies' papers that show practical experience, R & D, tools, etc., focused on some topics of the conference. These papers are assigned to a 4-page limit.

Submitted papers must comply with the format of Advances in Intelligent Systems and Computing Series (see Instructions for Authors at Springer Website or download a DOC example) be written in English, must not have been published before, not be under review for any other conference or publication and not include any information leading to the authors’ identification. Therefore, the authors’ names, affiliations and bibliographic references should not be included in the version for evaluation by the Program Committee. This information should only be included in the camera-ready version, saved in Word or Latex format and also in PDF format. These files must be accompanied by the Consent to Publication form filled out, in a ZIP file, and uploaded at the conference management system.

All papers will be subjected to a “double-blind review” by at least two members of the Program Committee.

Based on Program Committee evaluation, a paper can be rejected or accepted by the Conference Chairs. In the later case, it can be accepted as the type originally submitted or as another type. Thus, full papers can be accepted as short papers or poster papers only. Similarly, short papers can be accepted as poster papers only. In these cases, the authors will be allowed to maintain the original number of pages in the camera-ready version.

The authors of accepted poster papers must also build and print a poster to be exhibited during the Conference. This poster must follow an A1 or A2 vertical format. The Conference can includes Work Sessions where these posters are presented and orally discussed, with a 5 minute limit per poster.

The authors of accepted full papers will have 15 minutes to present their work in a Conference Work Session; approximately 5 minutes of discussion will follow each presentation. The authors of accepted short papers and company papers will have 11 minutes to present their work in a Conference Work Session; approximately 4 minutes of discussion will follow each presentation.


PUBLICATION AND INDEXING

To ensure that a full paper, short paper, poster paper or company paper is published in the Proceedings, at least one of the authors must be fully registered by the 27th of December 2015, and the paper must comply with the suggested layout and page-limit. Additionally, all recommended changes must be addressed by the authors before they submit the camera-ready version.

No more than one paper per registration will be published in the Conference Proceedings. An extra fee must be paid for publication of additional papers, with a maximum of one additional paper per registration.

Full and short papers will be published in Proceedings by Springer, in a book of Advances in Intelligent Systems and Computing series. Poster and company papers will be published by AISTI.

Published full and short papers will be submitted for indexation by ISI, EI-Compendex, SCOPUS and DBLP, among others, and will be available in the SpringerLink Digital Library.

The authors of the best selected papers will be invited to extend them for publication in international journals indexed by ISI/SCI, SCOPUS and DBLP, among others, such as:

- International Journal of Neural Systems (IF: 6.507)
- Integrated Computer-Aided Engineering (IF: 4.698)
- Computers in Human Behavior (IF: 2.694)
- Journal of Medical Systems (IF: 2.213)
- International Journal of Computer-Supported Collaborative Learning (IF: 1.841)
- Journal of Intelligent & Fuzzy Systems (IF: 1.812)
- Telemedicine and e-Health (IF: 1.668)
- International Journal of Information Management (IF: 1.550)
- Engineering Computations (IF: 1.495)
- Electronic Commerce Research and Applications (IF: 1.482)
- Telematics and Informatics (IF: 1.120)
- Journal of Evaluation in Clinical Practice (IF: 1.084)
- Ethics and Information Technology (IF: 1.021)
- Int. Journal of Computers Communications & Control (IF: 0.746)
- IET Software (IF: 0.595)
- Knowledge Management Research & Practice (IF: 0.554)
- AI Communications (IF: 0.547)
- Computing and Informatics (IF: 0.504)
- Universal Access in the Information Society (IF: 0.475)
- Journal of Global Information Management (IF: 0.424)
- Journal of Software Engineering and Knowledge Engineering (IF: 0.362)
- Journal of Internet Services and Applications (SJR: 0.88)
- Journal of Hospitality and Tourism Technology (SJR: 0.41)
- VINE - The Journal of Information and Knowledge Management Systems (SJR: 0.24)
- International Journal of Online Engineering (SJR: 0.21)
- Int. Journal of Emerging Technologies in Learning (SJR: 0.12)
- Computer Methods in Biomechanics and Biomedical Engineering: Imaging & Visualization


IMPORTANT DATES

Paper Submission: October 31, 2015

Notification of Acceptance: December 13, 2015

Payment of Registration, to ensure the inclusion of an accepted paper in the conference proceedings: December 27, 2015.

Camera-ready Submission: December 31, 2015


-

Maria Lemos
WorldCIST'16
http://www.aisti.eu/worldcist16/





[-- Attachment #2: Type: text/plain, Size: 183 bytes --]

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* [PULL] vhost: cleanups and fixes
From: Michael S. Tsirkin @ 2015-09-09  9:15 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: famz, graeme.gregory, kvm, mst, netdev, linux-kernel,
	virtualization, pbonzini, den

The following changes since commit 64291f7db5bd8150a74ad2036f1037e6a0428df2:

  Linux 4.2 (2015-08-30 11:34:09 -0700)

are available in the git repository at:

  git://git.kernel.org/pub/scm/linux/kernel/git/mst/vhost.git tags/for_linus

for you to fetch changes up to 997e120843e82609c8d99a9d5714e6cf91e14cbe:

  virtio_balloon: do not change memory amount visible via /proc/meminfo (2015-09-08 13:32:11 +0300)

----------------------------------------------------------------
virtio: fixes and features 4.3

virtio-mmio can now be auto-loaded through acpi.
virtio blk supports extended partitions.
total memory is better reported when using virtio balloon with auto-deflate.
cache control is re-enabled when using virtio-blk in modern mode.

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

----------------------------------------------------------------
Denis V. Lunev (2):
      virtio_ballon: change stub of release_pages_by_pfn
      virtio_balloon: do not change memory amount visible via /proc/meminfo

Fam Zheng (1):
      virtio-blk: Allow extended partitions

Graeme Gregory (1):
      virtio_mmio: add ACPI probing

Paolo Bonzini (1):
      virtio-blk: use VIRTIO_BLK_F_WCE and VIRTIO_BLK_F_CONFIG_WCE in virtio1

 drivers/block/virtio_blk.c      |  6 +++---
 drivers/virtio/virtio_balloon.c | 16 ++++++++++------
 drivers/virtio/virtio_mmio.c    | 10 ++++++++++
 3 files changed, 23 insertions(+), 9 deletions(-)

^ permalink raw reply

* Re: [opnfv-tech-discuss] rfc: vhost user enhancements for vm2vm communication
From: Claudio Fontana @ 2015-09-09  8:39 UTC (permalink / raw)
  To: Zhang, Yang Z, Michael S. Tsirkin, qemu-devel@nongnu.org,
	virtualization@lists.linux-foundation.org,
	virtio-dev@lists.oasis-open.org,
	opnfv-tech-discuss@lists.opnfv.org
  Cc: Jan Kiszka
In-Reply-To: <A9667DDFB95DB7438FA9D7D576C3D87E0AD9AB0B@SHSMSX104.ccr.corp.intel.com>

On 09.09.2015 08:40, Zhang, Yang Z wrote:
> Claudio Fontana wrote on 2015-09-07:
>> Coming late to the party,
>>
>> On 31.08.2015 16:11, Michael S. Tsirkin wrote:
>>> Hello!
>>> During the KVM forum, we discussed supporting virtio on top
>>> of ivshmem. I have considered it, and came up with an alternative
>>> that has several advantages over that - please see below.
>>> Comments welcome.
>>
>> as Jan mentioned we actually discussed a virtio-shmem device which would
>> incorporate the advantages of ivshmem (so no need for a separate ivshmem
>> device), which would use the well known virtio interface, taking advantage of
>> the new virtio-1 virtqueue layout to split r/w and read-only rings as seen from
>> the two sides, and make use also of BAR0 which has been freed up for use by
>> the device.
> 
> Interesting! Can you elaborate it? 


Yes, I will post a more detailed proposal in the coming days.


>>
>> This way it would be possible to share the rings and the actual memory
>> for the buffers in the PCI bars. The guest VMs could decide to use the
>> shared memory regions directly as prepared by the hypervisor (in the
> 
> "the shared memory regions" here means share another VM's memory or like ivshmem?


It's explicitly about sharing memory between two desired VMs, as set up by the virtualization environment.


>> jailhouse case) or QEMU/KVM, or perform their own validation on the
>> input depending on the use case.
>>
>> Of course the communication between VMs needs in this case to be
>> pre-configured and is quite static (which is actually beneficial in our use case).
> 
> pre-configured means user knows which VMs will talk to each other and configure it when booting guest(i.e. in Qemu command line)?

Yes.

Ciao,

Claudio

> 
>>
>> But still in your proposed solution, each VM needs to be pre-configured to
>> communicate with a specific other VM using a separate device right?
>>
>> But I wonder if we are addressing the same problem.. in your case you are
>> looking at having a shared memory pool for all VMs potentially visible to all VMs
>> (the vhost-user case), while in the virtio-shmem proposal we discussed we
>> were assuming specific different regions for every channel.
>>
>> Ciao,
>>
>> Claudio

^ permalink raw reply

* Re: virtio optimization idea
From: Michael S. Tsirkin @ 2015-09-09  7:33 UTC (permalink / raw)
  To: Xie, Huawei
  Cc: Venkatesan, Venky, Linhaifeng, dev@dpdk.org, virtualization,
	Tetsuya Mukawa, Ouyang, Changchun, Thomas Monjalon,
	Rogers, Gerald
In-Reply-To: <C37D651A908B024F974696C65296B57B2BDB8C06@SHSMSX101.ccr.corp.intel.com>

On Fri, Sep 04, 2015 at 08:25:05AM +0000, Xie, Huawei wrote:
> Hi:
> 
> Recently I have done one virtio optimization proof of concept. The
> optimization includes two parts:
> 1) avail ring set with fixed descriptors
> 2) RX vectorization
> With the optimizations, we could have several times of performance boost
> for purely vhost-virtio throughput.

Thanks!
I'm very happy to see people work on the virtio ring format
optimizations.

I think it's best to analyze each optimization separately,
unless you see a reason why they would only give benefit when applied
together.

Also ideally, we'd need a unit test to show the performance impact.
We've been using the tests in tools/virtio/ under linux,
feel free to enhance these to simulate more workloads, or
to suggest something else entirely.


> Here i will only cover the first part, which is the prerequisite for the
> second part.
> Let us first take RX for example. Currently when we fill the avail ring
> with guest mbuf, we need
> a) allocate one descriptor(for non sg mbuf) from free descriptors
> b) set the idx of the desc into the entry of avail ring
> c) set the addr/len field of the descriptor to point to guest blank mbuf
> data area
> 
> Those operation takes time, and especially step b results in modifed (M)
> state of the cache line for the avail ring in the virtio processing
> core. When vhost processes the avail ring, the cache line transfer from
> virtio processing core to vhost processing core takes pretty much CPU
> cycles.
> To solve this problem, this is the arrangement of RX ring for DPDK
> pmd(for non-mergable case).
>    
>                     avail                      
>                     idx                        
>                     +                          
>                     |                          
> +----+----+---+-------------+------+           
> | 0  | 1  | 2 | ... |  254  | 255  |  avail ring
> +-+--+-+--+-+-+---------+---+--+---+           
>   |    |    |       |   |      |               
>   |    |    |       |   |      |               
>   v    v    v       |   v      v               
> +-+--+-+--+-+-+---------+---+--+---+           
> | 0  | 1  | 2 | ... |  254  | 255  |  desc ring
> +----+----+---+-------------+------+           
>                     |                          
>                     |                          
> +----+----+---+-------------+------+           
> | 0  | 1  | 2 |     |  254  | 255  |  used ring
> +----+----+---+-------------+------+           
>                     |                          
>                     +    
> Avail ring is initialized with fixed descriptor and is never changed,
> i.e, the index value of the nth avail ring entry is always n, which
> means virtio PMD is actually refilling desc ring only, without having to
> change avail ring.
> When vhost fetches avail ring, if not evicted, it is always in its first
> level cache.
> 
> When RX receives packets from used ring, we use the used->idx as the
> desc idx. This requires that vhost processes and returns descs from
> avail ring to used ring in order, which is true for both current dpdk
> vhost and kernel vhost implementation. In my understanding, there is no
> necessity for vhost net to process descriptors OOO. One case could be
> zero copy, for example, if one descriptor doesn't meet zero copy
> requirment, we could directly return it to used ring, earlier than the
> descriptors in front of it.
> To enforce this, i want to use a reserved bit to indicate in order
> processing of descriptors.

So what's the point in changing the idx for the used ring?
You need to communicate the length to the guest anyway, don't you?


> For tx ring, the arrangement is like below. Each transmitted mbuf needs
> a desc for virtio_net_hdr, so actually we have only 128 free slots.

Just fix this one. Support ANY_LAYOUT and then you can put data
linearly. And/or support INDIRECT_DESC and then you can
use an indirect descriptor.


> 
>                            
> ++                                                          
>                            
> ||                                                          
>                            
> ||                                                          
>   
> +-----+-----+-----+--------------+------+------+------+                              
> 
>    |  0  |  1  | ... |  127 || 128  | 129  | ...  | 255  |   avail ring
> with fixed descriptor                
>   
> +--+--+--+--+-----+---+------+---+--+---+------+--+---+                              
> 
>       |     |            |  ||  |      |            
> |                                  
>       v     v            v  ||  v      v            
> v                                  
>   
> +--+--+--+--+-----+---+------+---+--+---+------+--+---+                              
> 
>    | 127 | 128 | ... |  255 || 127  | 128  | ...  | 255  |   desc ring
> for virtio_net_hdr
>   
> +--+--+--+--+-----+---+------+---+--+---+------+--+---+                              
> 
>       |     |            |  ||  |      |            
> |                                  
>       v     v            v  ||  v      v            
> v                                  
>   
> +--+--+--+--+-----+---+------+---+--+---+------+--+---+                              
> 
>    |  0  |  1  | ... |  127 ||  0   |  1   | ...  | 127  |   desc ring
> for tx dat       
>   
> +-----+-----+-----+--------------+------+------+------+                        
> 

This one came out corrupted.

>                      
> /huawei


Please Cc virtio related discussion more widely.
I added the virtualization mailing list.


So what you want to do is avoid changing the avail
ring, isn't it enough to pre-format it and cache
the values in the guest?

Host can then keep using avail ring without changes, it will stay in cache.
Something like the below for guest should do the trick (untested):

Signed-off-by: Michael S. Tsirkin <mst@redhat.com>

diff --git a/drivers/virtio/virtio_ring.c b/drivers/virtio/virtio_ring.c
index 096b857..9363b50 100644
--- a/drivers/virtio/virtio_ring.c
+++ b/drivers/virtio/virtio_ring.c
@@ -91,6 +91,7 @@ struct vring_virtqueue {
 	bool last_add_time_valid;
 	ktime_t last_add_time;
 #endif
+	u16 *avail;
 
 	/* Tokens for callbacks. */
 	void *data[];
@@ -236,7 +237,10 @@ static inline int virtqueue_add(struct virtqueue *_vq,
 	/* Put entry in available array (but don't update avail->idx until they
 	 * do sync). */
 	avail = virtio16_to_cpu(_vq->vdev, vq->vring.avail->idx) & (vq->vring.num - 1);
-	vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head);
+	if (vq->avail[avail] != head) {
+		vq->avail[avail] = head;
+		vq->vring.avail->ring[avail] = cpu_to_virtio16(_vq->vdev, head);
+	}
 
 	/* Descriptors and available array need to be set before we expose the
 	 * new available array entries. */
@@ -724,6 +728,11 @@ struct virtqueue *vring_new_virtqueue(unsigned int index,
 	vq = kmalloc(sizeof(*vq) + sizeof(void *)*num, GFP_KERNEL);
 	if (!vq)
 		return NULL;
+	vq->avail = kzalloc(sizeof (*vq->avail) * num, GFP_KERNEL);
+	if (!va->avail) {
+		kfree(vq);
+		return NULL;
+	}
 
 	vring_init(&vq->vring, num, pages, vring_align);
 	vq->vq.callback = callback;

-- 
MST

^ permalink raw reply related

* Re: rfc: vhost user enhancements for vm2vm communication
From: Michael S. Tsirkin @ 2015-09-09  7:06 UTC (permalink / raw)
  To: Claudio Fontana
  Cc: opnfv-tech-discuss, virtio-dev, Jan Kiszka, qemu-devel,
	virtualization
In-Reply-To: <55ED854A.1080804@huawei.com>

On Mon, Sep 07, 2015 at 02:38:34PM +0200, Claudio Fontana wrote:
> Coming late to the party, 
> 
> On 31.08.2015 16:11, Michael S. Tsirkin wrote:
> > Hello!
> > During the KVM forum, we discussed supporting virtio on top
> > of ivshmem. I have considered it, and came up with an alternative
> > that has several advantages over that - please see below.
> > Comments welcome.
> 
> as Jan mentioned we actually discussed a virtio-shmem device which would incorporate the advantages of ivshmem (so no need for a separate ivshmem device), which would use the well known virtio interface, taking advantage of the new virtio-1 virtqueue layout to split r/w and read-only rings as seen from the two sides, and make use also of BAR0 which has been freed up for use by the device.
> 
> This way it would be possible to share the rings and the actual memory for the buffers in the PCI bars. The guest VMs could decide to use the shared memory regions directly as prepared by the hypervisor (in the jailhouse case) or QEMU/KVM, or perform their own validation on the input depending on the use case.
> 
> Of course the communication between VMs needs in this case to be pre-configured and is quite static (which is actually beneficial in our use case).
> 
> But still in your proposed solution, each VM needs to be pre-configured to communicate with a specific other VM using a separate device right?
> 
> But I wonder if we are addressing the same problem.. in your case you are looking at having a shared memory pool for all VMs potentially visible to all VMs (the vhost-user case), while in the virtio-shmem proposal we discussed we were assuming specific different regions for every channel.
> 
> Ciao,
> 
> Claudio

The problem, as I see it, is to allow inter-vm communication with
polling (to get very low latencies) but polling within VMs only, without
need to run a host thread (which when polling uses up a host CPU).

What was proposed was to simply change virtio to allow
"offset within BAR" instead of PA.
This would allow VM2VM communication if there are only 2 VMs,
but if data needs to be sent to multiple VMs, you
must copy it.

Additionally, it's a single-purpose feature: you can use it from
a userspace PMD but linux will never use it.


My proposal is a superset: don't require that BAR memory is
used, use IOMMU translation tables.
This way, data can be sent to multiple VMs by sharing the same
memory with them all.

It is still possible to put data in some device BAR if that's
what the guest wants to do: just program the IOMMU to limit
virtio to the memory range that is within this BAR.

Another advantage here is that the feature is more generally useful.


> > 
> > -----
> > 
> > Existing solutions to userspace switching between VMs on the
> > same host are vhost-user and ivshmem.
> > 
> > vhost-user works by mapping memory of all VMs being bridged into the
> > switch memory space.
> > 
> > By comparison, ivshmem works by exposing a shared region of memory to all VMs.
> > VMs are required to use this region to store packets. The switch only
> > needs access to this region.
> > 
> > Another difference between vhost-user and ivshmem surfaces when polling
> > is used. With vhost-user, the switch is required to handle
> > data movement between VMs, if using polling, this means that 1 host CPU
> > needs to be sacrificed for this task.
> > 
> > This is easiest to understand when one of the VMs is
> > used with VF pass-through. This can be schematically shown below:
> > 
> > +-- VM1 --------------+            +---VM2-----------+
> > | virtio-pci          +-vhost-user-+ virtio-pci -- VF | -- VFIO -- IOMMU -- NIC
> > +---------------------+            +-----------------+
> > 
> > 
> > With ivshmem in theory communication can happen directly, with two VMs
> > polling the shared memory region.
> > 
> > 
> > I won't spend time listing advantages of vhost-user over ivshmem.
> > Instead, having identified two advantages of ivshmem over vhost-user,
> > below is a proposal to extend vhost-user to gain the advantages
> > of ivshmem.
> > 
> > 
> > 1: virtio in guest can be extended to allow support
> > for IOMMUs. This provides guest with full flexibility
> > about memory which is readable or write able by each device.
> > By setting up a virtio device for each other VM we need to
> > communicate to, guest gets full control of its security, from
> > mapping all memory (like with current vhost-user) to only
> > mapping buffers used for networking (like ivshmem) to
> > transient mappings for the duration of data transfer only.
> > This also allows use of VFIO within guests, for improved
> > security.
> > 
> > vhost user would need to be extended to send the
> > mappings programmed by guest IOMMU.
> > 
> > 2. qemu can be extended to serve as a vhost-user client:
> > remote VM mappings over the vhost-user protocol, and
> > map them into another VM's memory.
> > This mapping can take, for example, the form of
> > a BAR of a pci device, which I'll call here vhost-pci - 
> > with bus address allowed
> > by VM1's IOMMU mappings being translated into
> > offsets within this BAR within VM2's physical
> > memory space.
> > 
> > Since the translation can be a simple one, VM2
> > can perform it within its vhost-pci device driver.
> > 
> > While this setup would be the most useful with polling,
> > VM1's ioeventfd can also be mapped to
> > another VM2's irqfd, and vice versa, such that VMs
> > can trigger interrupts to each other without need
> > for a helper thread on the host.
> > 
> > 
> > The resulting channel might look something like the following:
> > 
> > +-- VM1 --------------+  +---VM2-----------+
> > | virtio-pci -- iommu +--+ vhost-pci -- VF | -- VFIO -- IOMMU -- NIC
> > +---------------------+  +-----------------+
> > 
> > comparing the two diagrams, a vhost-user thread on the host is
> > no longer required, reducing the host CPU utilization when
> > polling is active.  At the same time, VM2 can not access all of VM1's
> > memory - it is limited by the iommu configuration setup by VM1.
> > 
> > 
> > Advantages over ivshmem:
> > 
> > - more flexibility, endpoint VMs do not have to place data at any
> >   specific locations to use the device, in practice this likely
> >   means less data copies.
> > - better standardization/code reuse
> >   virtio changes within guests would be fairly easy to implement
> >   and would also benefit other backends, besides vhost-user
> >   standard hotplug interfaces can be used to add and remove these
> >   channels as VMs are added or removed.
> > - migration support
> >   It's easy to implement since ownership of memory is well defined.
> >   For example, during migration VM2 can notify hypervisor of VM1
> >   by updating dirty bitmap each time is writes into VM1 memory.
> > 
> > Thanks,
> > 
> 
> 
> -- 
> Claudio Fontana
> Server Virtualization Architect
> Huawei Technologies Duesseldorf GmbH
> Riesstraße 25 - 80992 München

^ permalink raw reply

* RE: [opnfv-tech-discuss] rfc: vhost user enhancements for vm2vm communication
From: Zhang, Yang Z @ 2015-09-09  6:40 UTC (permalink / raw)
  To: Claudio Fontana, Michael S. Tsirkin, qemu-devel@nongnu.org,
	virtualization@lists.linux-foundation.org,
	virtio-dev@lists.oasis-open.org,
	opnfv-tech-discuss@lists.opnfv.org
  Cc: Jan Kiszka
In-Reply-To: <55ED854A.1080804@huawei.com>

Claudio Fontana wrote on 2015-09-07:
> Coming late to the party,
> 
> On 31.08.2015 16:11, Michael S. Tsirkin wrote:
>> Hello!
>> During the KVM forum, we discussed supporting virtio on top
>> of ivshmem. I have considered it, and came up with an alternative
>> that has several advantages over that - please see below.
>> Comments welcome.
> 
> as Jan mentioned we actually discussed a virtio-shmem device which would
> incorporate the advantages of ivshmem (so no need for a separate ivshmem
> device), which would use the well known virtio interface, taking advantage of
> the new virtio-1 virtqueue layout to split r/w and read-only rings as seen from
> the two sides, and make use also of BAR0 which has been freed up for use by
> the device.

Interesting! Can you elaborate it? 

> 
> This way it would be possible to share the rings and the actual memory
> for the buffers in the PCI bars. The guest VMs could decide to use the
> shared memory regions directly as prepared by the hypervisor (in the

"the shared memory regions" here means share another VM's memory or like ivshmem?

> jailhouse case) or QEMU/KVM, or perform their own validation on the
> input depending on the use case.
> 
> Of course the communication between VMs needs in this case to be
> pre-configured and is quite static (which is actually beneficial in our use case).

pre-configured means user knows which VMs will talk to each other and configure it when booting guest(i.e. in Qemu command line)?

> 
> But still in your proposed solution, each VM needs to be pre-configured to
> communicate with a specific other VM using a separate device right?
> 
> But I wonder if we are addressing the same problem.. in your case you are
> looking at having a shared memory pool for all VMs potentially visible to all VMs
> (the vhost-user case), while in the virtio-shmem proposal we discussed we
> were assuming specific different regions for every channel.
> 
> Ciao,
> 
> Claudio
> 
> 
>


Best regards,
Yang

^ permalink raw reply

* Re: [PATCH] virtio-blk: use VIRTIO_BLK_F_WCE and VIRTIO_BLK_F_CONFIG_WCE in virtio1
From: Paolo Bonzini @ 2015-09-07 16:15 UTC (permalink / raw)
  To: linux-kernel, kvm
  Cc: Michael S. Tsirkin, open list:VIRTIO CORE, NET AND BLOCK DRIVERS
In-Reply-To: <1440197635-5170-1-git-send-email-pbonzini@redhat.com>



On 22/08/2015 00:53, Paolo Bonzini wrote:
> VIRTIO_BLK_F_CONFIG_WCE is important in order to achieve good performance
> (up to 2x, though more realistically +30-40%) in latency-bound workloads.
> However, it was removed by mistake together with VIRTIO_BLK_F_FLUSH.
> 
> It will be restored in the next revision of the virtio 1.0 standard, so
> do the same in Linux.
> 
> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
> ---
>  drivers/block/virtio_blk.c | 5 ++---
>  1 file changed, 2 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
> index d4d05f064d39..ea2c17c66dfb 100644
> --- a/drivers/block/virtio_blk.c
> +++ b/drivers/block/virtio_blk.c
> @@ -478,8 +478,7 @@ static int virtblk_get_cache_mode(struct virtio_device *vdev)
>  				   struct virtio_blk_config, wce,
>  				   &writeback);
>  	if (err)
> -		writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE) ||
> -		            virtio_has_feature(vdev, VIRTIO_F_VERSION_1);
> +		writeback = virtio_has_feature(vdev, VIRTIO_BLK_F_WCE);
>  
>  	return writeback;
>  }
> @@ -840,7 +839,7 @@ static unsigned int features_legacy[] = {
>  static unsigned int features[] = {
>  	VIRTIO_BLK_F_SEG_MAX, VIRTIO_BLK_F_SIZE_MAX, VIRTIO_BLK_F_GEOMETRY,
>  	VIRTIO_BLK_F_RO, VIRTIO_BLK_F_BLK_SIZE,
> -	VIRTIO_BLK_F_TOPOLOGY,
> +	VIRTIO_BLK_F_WCE, VIRTIO_BLK_F_TOPOLOGY, VIRTIO_BLK_F_CONFIG_WCE,
>  	VIRTIO_BLK_F_MQ,
>  };
>  
> 

Ping?

Paolo

^ permalink raw reply

* Re: [PATCH] virtio-gpu: fix compilation warnings
From: Gerd Hoffmann @ 2015-09-07 13:32 UTC (permalink / raw)
  To: Mike Rapoport; +Cc: David Airlie, linux-kernel, dri-devel, virtualization
In-Reply-To: <1441186241-5458-1-git-send-email-mike.rapoport@gmail.com>

On Mi, 2015-09-02 at 12:30 +0300, Mike Rapoport wrote:
> Update snprintf format in virtgpu_fence.c and virtgpu_debugfs.c to fix the
> following compilation warnings:
> 
> C [M]  drivers/gpu/drm/virtio/virtgpu_fence.o
> drivers/gpu/drm/virtio/virtgpu_fence.c: In function ‘virtio_timeline_value_str’ :
> drivers/gpu/drm/virtio/virtgpu_fence.c:64:2: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘long long int’ [-Wformat=]
>   snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
>   ^
>   CC [M]  drivers/gpu/drm/virtio/virtgpu_debugfs.o
> drivers/gpu/drm/virtio/virtgpu_debugfs.c: In function ‘virtio_gpu_debugfs_irq_info’:
> drivers/gpu/drm/virtio/virtgpu_debugfs.c:39:6: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘long long int’ [-Wformat=]
>       vgdev->fence_drv.sync_seq);

Doesn't fly.  I assume this removes the warnings for 32bit builds, but
with the patch applied I get warnings on 64bit builds ...

cheers,
  Gerd


_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Claudio Fontana @ 2015-09-07 12:38 UTC (permalink / raw)
  To: Michael S. Tsirkin, qemu-devel, virtualization, virtio-dev,
	opnfv-tech-discuss
  Cc: Jan Kiszka
In-Reply-To: <20150831160655-mutt-send-email-mst@redhat.com>

Coming late to the party, 

On 31.08.2015 16:11, Michael S. Tsirkin wrote:
> Hello!
> During the KVM forum, we discussed supporting virtio on top
> of ivshmem. I have considered it, and came up with an alternative
> that has several advantages over that - please see below.
> Comments welcome.

as Jan mentioned we actually discussed a virtio-shmem device which would incorporate the advantages of ivshmem (so no need for a separate ivshmem device), which would use the well known virtio interface, taking advantage of the new virtio-1 virtqueue layout to split r/w and read-only rings as seen from the two sides, and make use also of BAR0 which has been freed up for use by the device.

This way it would be possible to share the rings and the actual memory for the buffers in the PCI bars. The guest VMs could decide to use the shared memory regions directly as prepared by the hypervisor (in the jailhouse case) or QEMU/KVM, or perform their own validation on the input depending on the use case.

Of course the communication between VMs needs in this case to be pre-configured and is quite static (which is actually beneficial in our use case).

But still in your proposed solution, each VM needs to be pre-configured to communicate with a specific other VM using a separate device right?

But I wonder if we are addressing the same problem.. in your case you are looking at having a shared memory pool for all VMs potentially visible to all VMs (the vhost-user case), while in the virtio-shmem proposal we discussed we were assuming specific different regions for every channel.

Ciao,

Claudio

> 
> -----
> 
> Existing solutions to userspace switching between VMs on the
> same host are vhost-user and ivshmem.
> 
> vhost-user works by mapping memory of all VMs being bridged into the
> switch memory space.
> 
> By comparison, ivshmem works by exposing a shared region of memory to all VMs.
> VMs are required to use this region to store packets. The switch only
> needs access to this region.
> 
> Another difference between vhost-user and ivshmem surfaces when polling
> is used. With vhost-user, the switch is required to handle
> data movement between VMs, if using polling, this means that 1 host CPU
> needs to be sacrificed for this task.
> 
> This is easiest to understand when one of the VMs is
> used with VF pass-through. This can be schematically shown below:
> 
> +-- VM1 --------------+            +---VM2-----------+
> | virtio-pci          +-vhost-user-+ virtio-pci -- VF | -- VFIO -- IOMMU -- NIC
> +---------------------+            +-----------------+
> 
> 
> With ivshmem in theory communication can happen directly, with two VMs
> polling the shared memory region.
> 
> 
> I won't spend time listing advantages of vhost-user over ivshmem.
> Instead, having identified two advantages of ivshmem over vhost-user,
> below is a proposal to extend vhost-user to gain the advantages
> of ivshmem.
> 
> 
> 1: virtio in guest can be extended to allow support
> for IOMMUs. This provides guest with full flexibility
> about memory which is readable or write able by each device.
> By setting up a virtio device for each other VM we need to
> communicate to, guest gets full control of its security, from
> mapping all memory (like with current vhost-user) to only
> mapping buffers used for networking (like ivshmem) to
> transient mappings for the duration of data transfer only.
> This also allows use of VFIO within guests, for improved
> security.
> 
> vhost user would need to be extended to send the
> mappings programmed by guest IOMMU.
> 
> 2. qemu can be extended to serve as a vhost-user client:
> remote VM mappings over the vhost-user protocol, and
> map them into another VM's memory.
> This mapping can take, for example, the form of
> a BAR of a pci device, which I'll call here vhost-pci - 
> with bus address allowed
> by VM1's IOMMU mappings being translated into
> offsets within this BAR within VM2's physical
> memory space.
> 
> Since the translation can be a simple one, VM2
> can perform it within its vhost-pci device driver.
> 
> While this setup would be the most useful with polling,
> VM1's ioeventfd can also be mapped to
> another VM2's irqfd, and vice versa, such that VMs
> can trigger interrupts to each other without need
> for a helper thread on the host.
> 
> 
> The resulting channel might look something like the following:
> 
> +-- VM1 --------------+  +---VM2-----------+
> | virtio-pci -- iommu +--+ vhost-pci -- VF | -- VFIO -- IOMMU -- NIC
> +---------------------+  +-----------------+
> 
> comparing the two diagrams, a vhost-user thread on the host is
> no longer required, reducing the host CPU utilization when
> polling is active.  At the same time, VM2 can not access all of VM1's
> memory - it is limited by the iommu configuration setup by VM1.
> 
> 
> Advantages over ivshmem:
> 
> - more flexibility, endpoint VMs do not have to place data at any
>   specific locations to use the device, in practice this likely
>   means less data copies.
> - better standardization/code reuse
>   virtio changes within guests would be fairly easy to implement
>   and would also benefit other backends, besides vhost-user
>   standard hotplug interfaces can be used to add and remove these
>   channels as VMs are added or removed.
> - migration support
>   It's easy to implement since ownership of memory is well defined.
>   For example, during migration VM2 can notify hypervisor of VM1
>   by updating dirty bitmap each time is writes into VM1 memory.
> 
> Thanks,
> 


-- 
Claudio Fontana
Server Virtualization Architect
Huawei Technologies Duesseldorf GmbH
Riesstraße 25 - 80992 München

^ permalink raw reply

* [PATCH v7] pci: quirk to skip msi disable on shutdown
From: Michael S. Tsirkin @ 2015-09-06 15:32 UTC (permalink / raw)
  To: linux-kernel
  Cc: Fam Zheng, linux-pci, Ulrich Obergfell, virtualization,
	Yinghai Lu, Eric W. Biederman, Bjorn Helgaas

On some hypervisors, virtio devices tend to generate spurious interrupts
when switching between MSI and non-MSI mode.  Normally, either MSI or
non-MSI is used and all is well, but during shutdown, linux disables MSI
which then causes an "irq %d: nobody cared" message, with irq being
subsequently disabled.

Since bus mastering is already disabled at this point, disabling MSI
isn't actually useful for spec compliant devices: MSI interrupts are
in-bus memory writes so disabling Bus Master (which is already done)
disables these as well: after some research, it appears to be there for
the benefit of devices that ignore the bus master bit.

As it's not clear how common this kind of bug is, this patch simply adds
a quirk, to be set by devices that wish to skip disabling msi on
shutdown, relying on bus master instead.

We set this quirk in virtio core.

Reported-by: Fam Zheng <famz@redhat.com>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: Yinghai Lu <yhlu.kernel.send@gmail.com>
Cc: Ulrich Obergfell <uobergfe@redhat.com>
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: "Eric W. Biederman" <ebiederm@xmission.com>
Signed-off-by: Michael S. Tsirkin <mst@redhat.com>
---


changes from v6:
	limit changes to virtio only
changes from v5:
        rebased on top of pci/msi
        fixed commit log, including comments by Bjorn
        and adding explanation to address comments/questions by Eric
        dropped stable Cc, this patch does not seem to qualify for stable
changes from v4:
        Yijing Wang <wangyijing@huawei.com> noted that
        early fixups rely on pci_msi_off.
        Split out the functionality and move off the
        required part to run early during pci_device_setup.
Changes from v3:
        fix a copy-and-paste error in
          pci: drop some duplicate code
        other patches are unchanged
        drop Cc stable for now
Changes from v2:
        move code from probe to device enumeration
        add patches to unexport pci_msi_off


 include/linux/pci.h                | 2 ++
 drivers/pci/pci-driver.c           | 6 ++++--
 drivers/virtio/virtio_pci_common.c | 4 ++++
 3 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/include/linux/pci.h b/include/linux/pci.h
index 860c751..80f3494 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -180,6 +180,8 @@ enum pci_dev_flags {
 	PCI_DEV_FLAGS_NO_BUS_RESET = (__force pci_dev_flags_t) (1 << 6),
 	/* Do not use PM reset even if device advertises NoSoftRst- */
 	PCI_DEV_FLAGS_NO_PM_RESET = (__force pci_dev_flags_t) (1 << 7),
+	/* Do not disable MSI on shutdown, disable bus master instead */
+	PCI_DEV_FLAGS_NO_MSI_SHUTDOWN = (__force pci_dev_flags_t) (1 << 8),
 };
 
 enum pci_irq_reroute_variant {
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3cb2210..59d9e40 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -450,8 +450,10 @@ static void pci_device_shutdown(struct device *dev)
 
 	if (drv && drv->shutdown)
 		drv->shutdown(pci_dev);
-	pci_msi_shutdown(pci_dev);
-	pci_msix_shutdown(pci_dev);
+	if (!(pci_dev->dev_flags & PCI_DEV_FLAGS_NO_MSI_SHUTDOWN)) {
+		pci_msi_shutdown(pci_dev);
+		pci_msix_shutdown(pci_dev);
+	}
 
 #ifdef CONFIG_KEXEC
 	/*
diff --git a/drivers/virtio/virtio_pci_common.c b/drivers/virtio/virtio_pci_common.c
index 78f804a..26f46c3 100644
--- a/drivers/virtio/virtio_pci_common.c
+++ b/drivers/virtio/virtio_pci_common.c
@@ -528,6 +528,8 @@ static int virtio_pci_probe(struct pci_dev *pci_dev,
 	if (rc)
 		goto err_register;
 
+	pci_dev->dev_flags |= PCI_DEV_FLAGS_NO_MSI_SHUTDOWN;
+
 	return 0;
 
 err_register:
@@ -546,6 +548,8 @@ static void virtio_pci_remove(struct pci_dev *pci_dev)
 {
 	struct virtio_pci_device *vp_dev = pci_get_drvdata(pci_dev);
 
+	pci_dev->dev_flags &= ~PCI_DEV_FLAGS_NO_MSI_SHUTDOWN;
+
 	unregister_virtio_device(&vp_dev->vdev);
 
 	if (vp_dev->ioaddr)
-- 
MST

^ permalink raw reply related

* [PATCH v2] virtio-blk: Allow extended partitions
From: Fam Zheng @ 2015-09-06  9:05 UTC (permalink / raw)
  To: linux-kernel; +Cc: pbonzini, virtualization, kvm, Michael S. Tsirkin

This will allow up to DISK_MAX_PARTS (256) partitions, with for example
GPT in the guest. Otherwise, the partition scan code will only discover
the first 15 partitions.

Signed-off-by: Fam Zheng <famz@redhat.com>
---
 drivers/block/virtio_blk.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/drivers/block/virtio_blk.c b/drivers/block/virtio_blk.c
index d4d05f0..38ea01b 100644
--- a/drivers/block/virtio_blk.c
+++ b/drivers/block/virtio_blk.c
@@ -657,6 +657,7 @@ static int virtblk_probe(struct virtio_device *vdev)
 	vblk->disk->private_data = vblk;
 	vblk->disk->fops = &virtblk_fops;
 	vblk->disk->driverfs_dev = &vdev->dev;
+	vblk->disk->flags |= GENHD_FL_EXT_DEVT;
 	vblk->index = index;
 
 	/* configure queue flush support */
-- 
2.4.3

^ permalink raw reply related

* Re: rfc: vhost user enhancements for vm2vm communication
From: Jan Kiszka @ 2015-09-03 10:25 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtio-dev, Claudio.Fontana, qemu-devel, virtualization,
	Varun Sethi, opnfv-tech-discuss
In-Reply-To: <20150903112343-mutt-send-email-mst@redhat.com>

On 2015-09-03 10:37, Michael S. Tsirkin wrote:
> On Thu, Sep 03, 2015 at 10:21:28AM +0200, Jan Kiszka wrote:
>> On 2015-09-03 10:08, Michael S. Tsirkin wrote:
>>>
>>> IOW if you wish, you actually can create a shared memory device,
>>> make it accessible to the IOMMU and place some or all
>>> data there.
>>>
>>
>> Actually, that could also be something more sophisticated, including
>> virtio-net, IF that device will be able to express its DMA window
>> restrictions (a bit like 32-bit PCI devices being restricted to <4G
>> addresses or ISA devices <1M).
>>
>> Jan
> 
> Actually, it's the bus restriction, not the device restriction.
> 
> So if you want to use bounce buffers in the name of security or
> real-time requirements, you should be able to do this if virtio uses the
> DMA API.

Bounce buffer will only be the simplest option (though fine for low-rate
traffic that we also have in mind, like virtual consoles). Given
properly-sized regions, even if fixed, and the right communication
stacks, you can directly allocate application buffers in those regions
and avoid most to all copying.

In any case, if we manage to address this variation along with your
proposal, that would help tremendously.

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Michael S. Tsirkin @ 2015-09-03  8:37 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: virtio-dev, Claudio.Fontana, qemu-devel, virtualization,
	Varun Sethi, opnfv-tech-discuss
In-Reply-To: <55E80308.7070206@siemens.com>

On Thu, Sep 03, 2015 at 10:21:28AM +0200, Jan Kiszka wrote:
> On 2015-09-03 10:08, Michael S. Tsirkin wrote:
> > On Tue, Sep 01, 2015 at 06:28:28PM +0200, Jan Kiszka wrote:
> >> On 2015-09-01 18:02, Michael S. Tsirkin wrote:
> >>> On Tue, Sep 01, 2015 at 05:34:37PM +0200, Jan Kiszka wrote:
> >>>> On 2015-09-01 16:34, Michael S. Tsirkin wrote:
> >>>>> On Tue, Sep 01, 2015 at 04:09:44PM +0200, Jan Kiszka wrote:
> >>>>>> On 2015-09-01 11:24, Michael S. Tsirkin wrote:
> >>>>>>> On Tue, Sep 01, 2015 at 11:11:52AM +0200, Jan Kiszka wrote:
> >>>>>>>> On 2015-09-01 10:01, Michael S. Tsirkin wrote:
> >>>>>>>>> On Tue, Sep 01, 2015 at 09:35:21AM +0200, Jan Kiszka wrote:
> >>>>>>>>>> Leaving all the implementation and interface details aside, this
> >>>>>>>>>> discussion is first of all about two fundamentally different approaches:
> >>>>>>>>>> static shared memory windows vs. dynamically remapped shared windows (a
> >>>>>>>>>> third one would be copying in the hypervisor, but I suppose we all agree
> >>>>>>>>>> that the whole exercise is about avoiding that). Which way do we want or
> >>>>>>>>>> have to go?
> >>>>>>>>>>
> >>>>>>>>>> Jan
> >>>>>>>>>
> >>>>>>>>> Dynamic is a superset of static: you can always make it static if you
> >>>>>>>>> wish. Static has the advantage of simplicity, but that's lost once you
> >>>>>>>>> realize you need to invent interfaces to make it work.  Since we can use
> >>>>>>>>> existing IOMMU interfaces for the dynamic one, what's the disadvantage?
> >>>>>>>>
> >>>>>>>> Complexity. Having to emulate even more of an IOMMU in the hypervisor
> >>>>>>>> (we already have to do a bit for VT-d IR in Jailhouse) and doing this
> >>>>>>>> per platform (AMD IOMMU, ARM SMMU, ...) is out of scope for us. In that
> >>>>>>>> sense, generic grant tables would be more appealing.
> >>>>>>>
> >>>>>>> That's not how we do things for KVM, PV features need to be
> >>>>>>> modular and interchangeable with emulation.
> >>>>>>
> >>>>>> I know, and we may have to make some compromise for Jailhouse if that
> >>>>>> brings us valuable standardization and broad guest support. But we will
> >>>>>> surely not support an arbitrary amount of IOMMU models for that reason.
> >>>>>>
> >>>>>>>
> >>>>>>> If you just want something that's cross-platform and easy to
> >>>>>>> implement, just build a PV IOMMU. Maybe use virtio for this.
> >>>>>>
> >>>>>> That is likely required to keep the complexity manageable and to allow
> >>>>>> static preconfiguration.
> >>>>>
> >>>>> Real IOMMU allow static configuration just fine. This is exactly
> >>>>> what VFIO uses.
> >>>>
> >>>> Please specify more precisely which feature in which IOMMU you are
> >>>> referring to. Also, given that you refer to VFIO, I suspect we have
> >>>> different thing in mind. I'm talking about an IOMMU device model, like
> >>>> the one we have in QEMU now for VT-d. That one is not at all
> >>>> preconfigured by the host for VFIO.
> >>>
> >>> I really just mean that VFIO creates a mostly static IOMMU configuration.
> >>>
> >>> It's configured by the guest, not the host.
> >>
> >> OK, that resolves my confusion.
> >>
> >>>
> >>> I don't see host control over configuration as being particularly important.
> >>
> >> We do, see below.
> >>
> >>>
> >>>
> >>>>>
> >>>>>> Well, we could declare our virtio-shmem device to be an IOMMU device
> >>>>>> that controls access of a remote VM to RAM of the one that owns the
> >>>>>> device. In the static case, this access may at most be enabled/disabled
> >>>>>> but not moved around. The static regions would have to be discoverable
> >>>>>> for the VM (register read-back), and the guest's firmware will likely
> >>>>>> have to declare those ranges reserved to the guest OS.
> >>>>>> In the dynamic case, the guest would be able to create an alternative
> >>>>>> mapping.
> >>>>>
> >>>>>
> >>>>> I don't think we want a special device just to support the
> >>>>> static case. It might be a bit less code to write, but
> >>>>> eventually it should be up to the guest.
> >>>>> Fundamentally, it's policy that host has no business
> >>>>> dictating.
> >>>>
> >>>> "A bit less" is to be validated, and I doubt its just "a bit". But if
> >>>> KVM and its guests will also support some PV-IOMMU that we can reuse for
> >>>> our scenarios, than that is fine. KVM would not have to mandate support
> >>>> for it while we would, that's all.
> >>>
> >>> Someone will have to do this work.
> >>>
> >>>>>
> >>>>>> We would probably have to define a generic page table structure
> >>>>>> for that. Or do you rather have some MPU-like control structure in mind,
> >>>>>> more similar to the memory region descriptions vhost is already using?
> >>>>>
> >>>>> I don't care much. Page tables use less memory if a lot of memory needs
> >>>>> to be covered. OTOH if you want to use virtio (e.g. to allow command
> >>>>> batching) that likely means commands to manipulate the IOMMU, and
> >>>>> maintaining it all on the host. You decide.
> >>>>
> >>>> I don't care very much about the dynamic case as we won't support it
> >>>> anyway. However, if the configuration concept used for it is applicable
> >>>> to static mode as well, then we could reuse it. But preconfiguration
> >>>> will required register-based region description, I suspect.
> >>>
> >>> I don't know what you mean by preconfiguration exactly.
> >>>
> >>> Do you want the host to configure the IOMMU? Why not let the
> >>> guest do this?
> >>
> >> We simply freeze GPA-to-HPA mappings during runtime. Avoids having to
> >> validate and synchronize guest-triggered changes.
> > 
> > Fine, but this assumes guest does very specific things, right?
> > E.g. should guest reconfigure device's BAR, you would have
> > to change GPA to HPA mappings?
> > 
> 
> Yes, that's why we only support size exploration, not reallocation.
> 
> > 
> >>>>>
> >>>>>> Also not yet clear to me are how the vhost-pci device and the
> >>>>>> translations it will have to do should look like for VM2.
> >>>>>
> >>>>> I think we can use vhost-pci BAR + VM1 bus address as the
> >>>>> VM2 physical address. In other words, all memory exposed to
> >>>>> virtio-pci by VM1 through it's IOMMU is mapped into BAR of
> >>>>> vhost-pci.
> >>>>>
> >>>>> Bus addresses can be validated to make sure they fit
> >>>>> in the BAR.
> >>>>
> >>>> Sounds simple but may become challenging for VMs that have many of such
> >>>> devices (in order to connect to many possibly large VMs).
> >>>
> >>> You don't need to be able to map all guest memory if you know
> >>> guest won't try to allow device access to all of it.
> >>> It's a question of how good is the bus address allocator.
> >>
> >> But those BARs need to allocate a guest-physical address range as large
> >> as the other guest's RAM is, possibly even larger if that RAM is not
> >> contiguous, and you can't put other resources into potential holes
> >> because VM2 does not know where those holes will be.
> > 
> > No - only the RAM that you want addressable by VM2.
> 
> That's in the hand of VM1, not VM2 or the hypervisor, in case of
> reconfigurable mapping. It's indeed a non-issue in our static case.
> 
> > 
> > IOW if you wish, you actually can create a shared memory device,
> > make it accessible to the IOMMU and place some or all
> > data there.
> > 
> 
> Actually, that could also be something more sophisticated, including
> virtio-net, IF that device will be able to express its DMA window
> restrictions (a bit like 32-bit PCI devices being restricted to <4G
> addresses or ISA devices <1M).
> 
> Jan

Actually, it's the bus restriction, not the device restriction.

So if you want to use bounce buffers in the name of security or
real-time requirements, you should be able to do this if virtio uses the
DMA API.


> -- 
> Siemens AG, Corporate Technology, CT RTC ITP SES-DE
> Corporate Competence Center Embedded Linux

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Jan Kiszka @ 2015-09-03  8:21 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtio-dev, Claudio.Fontana, qemu-devel, virtualization,
	Varun Sethi, opnfv-tech-discuss
In-Reply-To: <20150903105304-mutt-send-email-mst@redhat.com>

On 2015-09-03 10:08, Michael S. Tsirkin wrote:
> On Tue, Sep 01, 2015 at 06:28:28PM +0200, Jan Kiszka wrote:
>> On 2015-09-01 18:02, Michael S. Tsirkin wrote:
>>> On Tue, Sep 01, 2015 at 05:34:37PM +0200, Jan Kiszka wrote:
>>>> On 2015-09-01 16:34, Michael S. Tsirkin wrote:
>>>>> On Tue, Sep 01, 2015 at 04:09:44PM +0200, Jan Kiszka wrote:
>>>>>> On 2015-09-01 11:24, Michael S. Tsirkin wrote:
>>>>>>> On Tue, Sep 01, 2015 at 11:11:52AM +0200, Jan Kiszka wrote:
>>>>>>>> On 2015-09-01 10:01, Michael S. Tsirkin wrote:
>>>>>>>>> On Tue, Sep 01, 2015 at 09:35:21AM +0200, Jan Kiszka wrote:
>>>>>>>>>> Leaving all the implementation and interface details aside, this
>>>>>>>>>> discussion is first of all about two fundamentally different approaches:
>>>>>>>>>> static shared memory windows vs. dynamically remapped shared windows (a
>>>>>>>>>> third one would be copying in the hypervisor, but I suppose we all agree
>>>>>>>>>> that the whole exercise is about avoiding that). Which way do we want or
>>>>>>>>>> have to go?
>>>>>>>>>>
>>>>>>>>>> Jan
>>>>>>>>>
>>>>>>>>> Dynamic is a superset of static: you can always make it static if you
>>>>>>>>> wish. Static has the advantage of simplicity, but that's lost once you
>>>>>>>>> realize you need to invent interfaces to make it work.  Since we can use
>>>>>>>>> existing IOMMU interfaces for the dynamic one, what's the disadvantage?
>>>>>>>>
>>>>>>>> Complexity. Having to emulate even more of an IOMMU in the hypervisor
>>>>>>>> (we already have to do a bit for VT-d IR in Jailhouse) and doing this
>>>>>>>> per platform (AMD IOMMU, ARM SMMU, ...) is out of scope for us. In that
>>>>>>>> sense, generic grant tables would be more appealing.
>>>>>>>
>>>>>>> That's not how we do things for KVM, PV features need to be
>>>>>>> modular and interchangeable with emulation.
>>>>>>
>>>>>> I know, and we may have to make some compromise for Jailhouse if that
>>>>>> brings us valuable standardization and broad guest support. But we will
>>>>>> surely not support an arbitrary amount of IOMMU models for that reason.
>>>>>>
>>>>>>>
>>>>>>> If you just want something that's cross-platform and easy to
>>>>>>> implement, just build a PV IOMMU. Maybe use virtio for this.
>>>>>>
>>>>>> That is likely required to keep the complexity manageable and to allow
>>>>>> static preconfiguration.
>>>>>
>>>>> Real IOMMU allow static configuration just fine. This is exactly
>>>>> what VFIO uses.
>>>>
>>>> Please specify more precisely which feature in which IOMMU you are
>>>> referring to. Also, given that you refer to VFIO, I suspect we have
>>>> different thing in mind. I'm talking about an IOMMU device model, like
>>>> the one we have in QEMU now for VT-d. That one is not at all
>>>> preconfigured by the host for VFIO.
>>>
>>> I really just mean that VFIO creates a mostly static IOMMU configuration.
>>>
>>> It's configured by the guest, not the host.
>>
>> OK, that resolves my confusion.
>>
>>>
>>> I don't see host control over configuration as being particularly important.
>>
>> We do, see below.
>>
>>>
>>>
>>>>>
>>>>>> Well, we could declare our virtio-shmem device to be an IOMMU device
>>>>>> that controls access of a remote VM to RAM of the one that owns the
>>>>>> device. In the static case, this access may at most be enabled/disabled
>>>>>> but not moved around. The static regions would have to be discoverable
>>>>>> for the VM (register read-back), and the guest's firmware will likely
>>>>>> have to declare those ranges reserved to the guest OS.
>>>>>> In the dynamic case, the guest would be able to create an alternative
>>>>>> mapping.
>>>>>
>>>>>
>>>>> I don't think we want a special device just to support the
>>>>> static case. It might be a bit less code to write, but
>>>>> eventually it should be up to the guest.
>>>>> Fundamentally, it's policy that host has no business
>>>>> dictating.
>>>>
>>>> "A bit less" is to be validated, and I doubt its just "a bit". But if
>>>> KVM and its guests will also support some PV-IOMMU that we can reuse for
>>>> our scenarios, than that is fine. KVM would not have to mandate support
>>>> for it while we would, that's all.
>>>
>>> Someone will have to do this work.
>>>
>>>>>
>>>>>> We would probably have to define a generic page table structure
>>>>>> for that. Or do you rather have some MPU-like control structure in mind,
>>>>>> more similar to the memory region descriptions vhost is already using?
>>>>>
>>>>> I don't care much. Page tables use less memory if a lot of memory needs
>>>>> to be covered. OTOH if you want to use virtio (e.g. to allow command
>>>>> batching) that likely means commands to manipulate the IOMMU, and
>>>>> maintaining it all on the host. You decide.
>>>>
>>>> I don't care very much about the dynamic case as we won't support it
>>>> anyway. However, if the configuration concept used for it is applicable
>>>> to static mode as well, then we could reuse it. But preconfiguration
>>>> will required register-based region description, I suspect.
>>>
>>> I don't know what you mean by preconfiguration exactly.
>>>
>>> Do you want the host to configure the IOMMU? Why not let the
>>> guest do this?
>>
>> We simply freeze GPA-to-HPA mappings during runtime. Avoids having to
>> validate and synchronize guest-triggered changes.
> 
> Fine, but this assumes guest does very specific things, right?
> E.g. should guest reconfigure device's BAR, you would have
> to change GPA to HPA mappings?
> 

Yes, that's why we only support size exploration, not reallocation.

> 
>>>>>
>>>>>> Also not yet clear to me are how the vhost-pci device and the
>>>>>> translations it will have to do should look like for VM2.
>>>>>
>>>>> I think we can use vhost-pci BAR + VM1 bus address as the
>>>>> VM2 physical address. In other words, all memory exposed to
>>>>> virtio-pci by VM1 through it's IOMMU is mapped into BAR of
>>>>> vhost-pci.
>>>>>
>>>>> Bus addresses can be validated to make sure they fit
>>>>> in the BAR.
>>>>
>>>> Sounds simple but may become challenging for VMs that have many of such
>>>> devices (in order to connect to many possibly large VMs).
>>>
>>> You don't need to be able to map all guest memory if you know
>>> guest won't try to allow device access to all of it.
>>> It's a question of how good is the bus address allocator.
>>
>> But those BARs need to allocate a guest-physical address range as large
>> as the other guest's RAM is, possibly even larger if that RAM is not
>> contiguous, and you can't put other resources into potential holes
>> because VM2 does not know where those holes will be.
> 
> No - only the RAM that you want addressable by VM2.

That's in the hand of VM1, not VM2 or the hypervisor, in case of
reconfigurable mapping. It's indeed a non-issue in our static case.

> 
> IOW if you wish, you actually can create a shared memory device,
> make it accessible to the IOMMU and place some or all
> data there.
> 

Actually, that could also be something more sophisticated, including
virtio-net, IF that device will be able to express its DMA window
restrictions (a bit like 32-bit PCI devices being restricted to <4G
addresses or ISA devices <1M).

Jan

-- 
Siemens AG, Corporate Technology, CT RTC ITP SES-DE
Corporate Competence Center Embedded Linux

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Michael S. Tsirkin @ 2015-09-03  8:09 UTC (permalink / raw)
  To: Nakajima, Jun
  Cc: virtio-dev, Jan Kiszka, Claudio.Fontana, qemu-devel,
	Linux Virtualization, Igor Mammedov, Varun Sethi,
	opnfv-tech-discuss
In-Reply-To: <CAL54oT1km9+wFBLfPzjW=sLCdfNg+yh=whFsE_f+udTHkSOs_g@mail.gmail.com>

On Wed, Sep 02, 2015 at 09:45:45PM -0700, Nakajima, Jun wrote:
> BTW, can you please take a look at the following URL to see my
> understanding is correct? Our engineers are saying that they are not
> really sure if they understood your proposal (especially around
> IOMMU), and I drew a figure, adding notes...
> 
> https://wiki.opnfv.org/vm2vm_mst
> 
> Thanks,

I think you got it right, thanks for putting this together!

> -- 
> Jun
> Intel Open Source Technology Center

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Michael S. Tsirkin @ 2015-09-03  8:08 UTC (permalink / raw)
  To: Jan Kiszka
  Cc: virtio-dev, Claudio.Fontana, qemu-devel, virtualization,
	Varun Sethi, opnfv-tech-discuss
In-Reply-To: <55E5D22C.6020108@siemens.com>

On Tue, Sep 01, 2015 at 06:28:28PM +0200, Jan Kiszka wrote:
> On 2015-09-01 18:02, Michael S. Tsirkin wrote:
> > On Tue, Sep 01, 2015 at 05:34:37PM +0200, Jan Kiszka wrote:
> >> On 2015-09-01 16:34, Michael S. Tsirkin wrote:
> >>> On Tue, Sep 01, 2015 at 04:09:44PM +0200, Jan Kiszka wrote:
> >>>> On 2015-09-01 11:24, Michael S. Tsirkin wrote:
> >>>>> On Tue, Sep 01, 2015 at 11:11:52AM +0200, Jan Kiszka wrote:
> >>>>>> On 2015-09-01 10:01, Michael S. Tsirkin wrote:
> >>>>>>> On Tue, Sep 01, 2015 at 09:35:21AM +0200, Jan Kiszka wrote:
> >>>>>>>> Leaving all the implementation and interface details aside, this
> >>>>>>>> discussion is first of all about two fundamentally different approaches:
> >>>>>>>> static shared memory windows vs. dynamically remapped shared windows (a
> >>>>>>>> third one would be copying in the hypervisor, but I suppose we all agree
> >>>>>>>> that the whole exercise is about avoiding that). Which way do we want or
> >>>>>>>> have to go?
> >>>>>>>>
> >>>>>>>> Jan
> >>>>>>>
> >>>>>>> Dynamic is a superset of static: you can always make it static if you
> >>>>>>> wish. Static has the advantage of simplicity, but that's lost once you
> >>>>>>> realize you need to invent interfaces to make it work.  Since we can use
> >>>>>>> existing IOMMU interfaces for the dynamic one, what's the disadvantage?
> >>>>>>
> >>>>>> Complexity. Having to emulate even more of an IOMMU in the hypervisor
> >>>>>> (we already have to do a bit for VT-d IR in Jailhouse) and doing this
> >>>>>> per platform (AMD IOMMU, ARM SMMU, ...) is out of scope for us. In that
> >>>>>> sense, generic grant tables would be more appealing.
> >>>>>
> >>>>> That's not how we do things for KVM, PV features need to be
> >>>>> modular and interchangeable with emulation.
> >>>>
> >>>> I know, and we may have to make some compromise for Jailhouse if that
> >>>> brings us valuable standardization and broad guest support. But we will
> >>>> surely not support an arbitrary amount of IOMMU models for that reason.
> >>>>
> >>>>>
> >>>>> If you just want something that's cross-platform and easy to
> >>>>> implement, just build a PV IOMMU. Maybe use virtio for this.
> >>>>
> >>>> That is likely required to keep the complexity manageable and to allow
> >>>> static preconfiguration.
> >>>
> >>> Real IOMMU allow static configuration just fine. This is exactly
> >>> what VFIO uses.
> >>
> >> Please specify more precisely which feature in which IOMMU you are
> >> referring to. Also, given that you refer to VFIO, I suspect we have
> >> different thing in mind. I'm talking about an IOMMU device model, like
> >> the one we have in QEMU now for VT-d. That one is not at all
> >> preconfigured by the host for VFIO.
> > 
> > I really just mean that VFIO creates a mostly static IOMMU configuration.
> > 
> > It's configured by the guest, not the host.
> 
> OK, that resolves my confusion.
> 
> > 
> > I don't see host control over configuration as being particularly important.
> 
> We do, see below.
> 
> > 
> > 
> >>>
> >>>> Well, we could declare our virtio-shmem device to be an IOMMU device
> >>>> that controls access of a remote VM to RAM of the one that owns the
> >>>> device. In the static case, this access may at most be enabled/disabled
> >>>> but not moved around. The static regions would have to be discoverable
> >>>> for the VM (register read-back), and the guest's firmware will likely
> >>>> have to declare those ranges reserved to the guest OS.
> >>>> In the dynamic case, the guest would be able to create an alternative
> >>>> mapping.
> >>>
> >>>
> >>> I don't think we want a special device just to support the
> >>> static case. It might be a bit less code to write, but
> >>> eventually it should be up to the guest.
> >>> Fundamentally, it's policy that host has no business
> >>> dictating.
> >>
> >> "A bit less" is to be validated, and I doubt its just "a bit". But if
> >> KVM and its guests will also support some PV-IOMMU that we can reuse for
> >> our scenarios, than that is fine. KVM would not have to mandate support
> >> for it while we would, that's all.
> > 
> > Someone will have to do this work.
> > 
> >>>
> >>>> We would probably have to define a generic page table structure
> >>>> for that. Or do you rather have some MPU-like control structure in mind,
> >>>> more similar to the memory region descriptions vhost is already using?
> >>>
> >>> I don't care much. Page tables use less memory if a lot of memory needs
> >>> to be covered. OTOH if you want to use virtio (e.g. to allow command
> >>> batching) that likely means commands to manipulate the IOMMU, and
> >>> maintaining it all on the host. You decide.
> >>
> >> I don't care very much about the dynamic case as we won't support it
> >> anyway. However, if the configuration concept used for it is applicable
> >> to static mode as well, then we could reuse it. But preconfiguration
> >> will required register-based region description, I suspect.
> > 
> > I don't know what you mean by preconfiguration exactly.
> > 
> > Do you want the host to configure the IOMMU? Why not let the
> > guest do this?
> 
> We simply freeze GPA-to-HPA mappings during runtime. Avoids having to
> validate and synchronize guest-triggered changes.

Fine, but this assumes guest does very specific things, right?
E.g. should guest reconfigure device's BAR, you would have
to change GPA to HPA mappings?


> >>>
> >>>> Also not yet clear to me are how the vhost-pci device and the
> >>>> translations it will have to do should look like for VM2.
> >>>
> >>> I think we can use vhost-pci BAR + VM1 bus address as the
> >>> VM2 physical address. In other words, all memory exposed to
> >>> virtio-pci by VM1 through it's IOMMU is mapped into BAR of
> >>> vhost-pci.
> >>>
> >>> Bus addresses can be validated to make sure they fit
> >>> in the BAR.
> >>
> >> Sounds simple but may become challenging for VMs that have many of such
> >> devices (in order to connect to many possibly large VMs).
> > 
> > You don't need to be able to map all guest memory if you know
> > guest won't try to allow device access to all of it.
> > It's a question of how good is the bus address allocator.
> 
> But those BARs need to allocate a guest-physical address range as large
> as the other guest's RAM is, possibly even larger if that RAM is not
> contiguous, and you can't put other resources into potential holes
> because VM2 does not know where those holes will be.

No - only the RAM that you want addressable by VM2.

IOW if you wish, you actually can create a shared memory device,
make it accessible to the IOMMU and place some or all
data there.




> > 
> >>>
> >>>
> >>> One issue to consider is that VM1 can trick VM2 into writing
> >>> into bus address that isn't mapped in the IOMMU, or
> >>> is mapped read-only.
> >>> We probably would have to teach KVM to handle this somehow,
> >>> e.g. exit to QEMU, or even just ignore. Maybe notify guest
> >>> e.g. by setting a bit in the config space of the device,
> >>> to avoid easy DOS.
> >>
> >> Well, that would be trivial for VM1 to check if there are only one or
> >> two memory windows. Relying on the hypervisor to handle it may be
> >> unacceptable for real-time VMs.
> >>
> >> Jan
> > 
> > Why? real-time != fast. I doubt you can avoid vm exits completely.
> 
> We can, one property of Jailhouse (on x86, ARM is waiting for GICv4).
> 
> Real-time == deterministic. And if you have such vm exits potentially in
> your code path, you have them always - for worst-case analysis. One may
> argue about probability in certain scenarios, but if the triggering side
> is malicious, probability may become 1.
> 
> Jan

You are doing a special hypervisor anyway, I think you could
detect that setup is done, and freeze
the configuration.

If afterwards a VM attempts to modify mappings, you can
say it's malicious and ignore it, or kill it, or whatever.



> -- 
> Siemens AG, Corporate Technology, CT RTC ITP SES-DE
> Corporate Competence Center Embedded Linux

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Nakajima, Jun @ 2015-09-03  4:45 UTC (permalink / raw)
  To: Michael S. Tsirkin
  Cc: virtio-dev, Jan Kiszka, Claudio.Fontana, qemu-devel,
	Linux Virtualization, Igor Mammedov, Varun Sethi,
	opnfv-tech-discuss
In-Reply-To: <20150902151438-mutt-send-email-mst@redhat.com>

BTW, can you please take a look at the following URL to see my
understanding is correct? Our engineers are saying that they are not
really sure if they understood your proposal (especially around
IOMMU), and I drew a figure, adding notes...

https://wiki.opnfv.org/vm2vm_mst

Thanks,
-- 
Jun
Intel Open Source Technology Center

^ permalink raw reply

* Re: rfc: vhost user enhancements for vm2vm communication
From: Michael S. Tsirkin @ 2015-09-02 12:15 UTC (permalink / raw)
  To: Nakajima, Jun
  Cc: virtio-dev, Jan Kiszka, Claudio.Fontana, qemu-devel,
	Linux Virtualization, Igor Mammedov, Varun Sethi,
	opnfv-tech-discuss
In-Reply-To: <CAL54oT1pcDv0xHoBshvWurePLYK2+eCgfzODh9KZj3Pe_5FB9Q@mail.gmail.com>

On Tue, Sep 01, 2015 at 05:01:07PM -0700, Nakajima, Jun wrote:
> On Tue, Sep 1, 2015 at 9:28 AM, Jan Kiszka <jan.kiszka@siemens.com> wrote:
> > On 2015-09-01 18:02, Michael S. Tsirkin wrote:
> ...
> >> You don't need to be able to map all guest memory if you know
> >> guest won't try to allow device access to all of it.
> >> It's a question of how good is the bus address allocator.
> >
> > But those BARs need to allocate a guest-physical address range as large
> > as the other guest's RAM is, possibly even larger if that RAM is not
> > contiguous, and you can't put other resources into potential holes
> > because VM2 does not know where those holes will be.
> >
> 
> I think you can allocate such guest-physical address ranges
> efficiently if each BAR sets the base of each memory region reported
> by VHOST_SET_MEM_TABLE, for example.  The issue is that we would need
> to 8 (VHOST_MEMORY_MAX_NREGIONS) of them vs. 6 (defined by PCI-SIG).

Besides, 8 is not even a limit: we merged a patch that allows makeing it
larger.

> -- 
> Jun
> Intel Open Source Technology Center

^ permalink raw reply

* Re: udev PATH_ID for virtio devices
From: Tom Gundersen @ 2015-09-02 12:14 UTC (permalink / raw)
  To: Michael S. Tsirkin; +Cc: Kay Sievers, Harald Hoyer, virtualization
In-Reply-To: <20150902150631-mutt-send-email-mst@redhat.com>

On Wed, Sep 2, 2015 at 2:09 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> On Wed, Sep 02, 2015 at 01:53:33PM +0200, Tom Gundersen wrote:
>> On Tue, Aug 25, 2015 at 1:58 PM, Kay Sievers <kay@vrfy.org> wrote:
>> > On Tue, Aug 25, 2015 at 1:52 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> >> On Tue, Aug 25, 2015 at 01:46:49PM +0200, Kay Sievers wrote:
>> >>> On Tue, Aug 25, 2015 at 1:43 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> >>> > On Mon, Aug 24, 2015 at 06:10:01PM +0200, Tom Gundersen wrote:
>> >
>> >>> >> 1) if there is a guarantee now and in the future (even if only
>> >>> >> restricted to netdevs) that no virtio bus will have a direct sibling
>> >>> >> bus (i.e., with the same parent device); or
>> >>> >
>> >>> > I think this is the case. The virtio bus is an artifact.
>> >>> > There's always a single one behind each pci device.
>> >>> > Is this sufficient?
>> >>>
>> >>> I *think* is not good enough for udev to offer such functionality.
>> >>>
>> >>> We need an authoritative answer that this cannot happen with today's
>> >>> code, and also that there are no plans to ever make multiple virtio
>> >>> devices per parent device.
>> >
>> >> But if virtio will make such a promise, will that be sufficient?
>> >
>> > Sure.
>>
>> Any chance we could get such a guarantee? Anything else needed from
>> our side? I have a pending patch that would be nice to get out, which
>> would depend on such a guarantee.
>>
>> Cheers,
>>
>> Tom
>
> I thought about this. The virtio spec makes it explicit for pci,
> ccw and mmio devices. I think we can make this promise - if we
> wanted to have many such buses, we can always make it something else,
> not a virtio bus.
>
> So please just check the type of the bus - if it's virtio,
> you can assume there is no sibling.

Thanks! Will do.

Cheers,

Tom

^ permalink raw reply

* Re: udev PATH_ID for virtio devices
From: Michael S. Tsirkin @ 2015-09-02 12:09 UTC (permalink / raw)
  To: Tom Gundersen; +Cc: Kay Sievers, Harald Hoyer, virtualization
In-Reply-To: <CAG-2HqU29JvRWmq4WJFDRcYzG=dBKuqMGtDu2eSt8gZc6eqppQ@mail.gmail.com>

On Wed, Sep 02, 2015 at 01:53:33PM +0200, Tom Gundersen wrote:
> On Tue, Aug 25, 2015 at 1:58 PM, Kay Sievers <kay@vrfy.org> wrote:
> > On Tue, Aug 25, 2015 at 1:52 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> >> On Tue, Aug 25, 2015 at 01:46:49PM +0200, Kay Sievers wrote:
> >>> On Tue, Aug 25, 2015 at 1:43 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
> >>> > On Mon, Aug 24, 2015 at 06:10:01PM +0200, Tom Gundersen wrote:
> >
> >>> >> 1) if there is a guarantee now and in the future (even if only
> >>> >> restricted to netdevs) that no virtio bus will have a direct sibling
> >>> >> bus (i.e., with the same parent device); or
> >>> >
> >>> > I think this is the case. The virtio bus is an artifact.
> >>> > There's always a single one behind each pci device.
> >>> > Is this sufficient?
> >>>
> >>> I *think* is not good enough for udev to offer such functionality.
> >>>
> >>> We need an authoritative answer that this cannot happen with today's
> >>> code, and also that there are no plans to ever make multiple virtio
> >>> devices per parent device.
> >
> >> But if virtio will make such a promise, will that be sufficient?
> >
> > Sure.
> 
> Any chance we could get such a guarantee? Anything else needed from
> our side? I have a pending patch that would be nice to get out, which
> would depend on such a guarantee.
> 
> Cheers,
> 
> Tom

I thought about this. The virtio spec makes it explicit for pci,
ccw and mmio devices. I think we can make this promise - if we
wanted to have many such buses, we can always make it something else,
not a virtio bus.

So please just check the type of the bus - if it's virtio,
you can assume there is no sibling.

-- 
MST

^ permalink raw reply

* Re: udev PATH_ID for virtio devices
From: Tom Gundersen @ 2015-09-02 11:53 UTC (permalink / raw)
  To: Kay Sievers; +Cc: virtualization, Harald Hoyer, Michael S. Tsirkin
In-Reply-To: <CAPXgP137A=CdmggtVPUZXbnpTbU9Tewq-sOjg9T8ohYktct1kQ@mail.gmail.com>

On Tue, Aug 25, 2015 at 1:58 PM, Kay Sievers <kay@vrfy.org> wrote:
> On Tue, Aug 25, 2015 at 1:52 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>> On Tue, Aug 25, 2015 at 01:46:49PM +0200, Kay Sievers wrote:
>>> On Tue, Aug 25, 2015 at 1:43 PM, Michael S. Tsirkin <mst@redhat.com> wrote:
>>> > On Mon, Aug 24, 2015 at 06:10:01PM +0200, Tom Gundersen wrote:
>
>>> >> 1) if there is a guarantee now and in the future (even if only
>>> >> restricted to netdevs) that no virtio bus will have a direct sibling
>>> >> bus (i.e., with the same parent device); or
>>> >
>>> > I think this is the case. The virtio bus is an artifact.
>>> > There's always a single one behind each pci device.
>>> > Is this sufficient?
>>>
>>> I *think* is not good enough for udev to offer such functionality.
>>>
>>> We need an authoritative answer that this cannot happen with today's
>>> code, and also that there are no plans to ever make multiple virtio
>>> devices per parent device.
>
>> But if virtio will make such a promise, will that be sufficient?
>
> Sure.

Any chance we could get such a guarantee? Anything else needed from
our side? I have a pending patch that would be nice to get out, which
would depend on such a guarantee.

Cheers,

Tom

^ permalink raw reply

* [PATCH] virtio-gpu: fix compilation warnings
From: Mike Rapoport @ 2015-09-02  9:30 UTC (permalink / raw)
  To: David Airlie; +Cc: linux-kernel, Mike Rapoport, dri-devel, virtualization

Update snprintf format in virtgpu_fence.c and virtgpu_debugfs.c to fix the
following compilation warnings:

C [M]  drivers/gpu/drm/virtio/virtgpu_fence.o
drivers/gpu/drm/virtio/virtgpu_fence.c: In function ‘virtio_timeline_value_str’ :
drivers/gpu/drm/virtio/virtgpu_fence.c:64:2: warning: format ‘%lu’ expects argument of type ‘long unsigned int’, but argument 4 has type ‘long long int’ [-Wformat=]
  snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
  ^
  CC [M]  drivers/gpu/drm/virtio/virtgpu_debugfs.o
drivers/gpu/drm/virtio/virtgpu_debugfs.c: In function ‘virtio_gpu_debugfs_irq_info’:
drivers/gpu/drm/virtio/virtgpu_debugfs.c:39:6: warning: format ‘%ld’ expects argument of type ‘long int’, but argument 3 has type ‘long long int’ [-Wformat=]
      vgdev->fence_drv.sync_seq);
      ^

Signed-off-by: Mike Rapoport <mike.rapoport@gmail.com>
---
 drivers/gpu/drm/virtio/virtgpu_debugfs.c | 2 +-
 drivers/gpu/drm/virtio/virtgpu_fence.c   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/drivers/gpu/drm/virtio/virtgpu_debugfs.c b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
index db8b491..d87b27c 100644
--- a/drivers/gpu/drm/virtio/virtgpu_debugfs.c
+++ b/drivers/gpu/drm/virtio/virtgpu_debugfs.c
@@ -34,7 +34,7 @@ virtio_gpu_debugfs_irq_info(struct seq_file *m, void *data)
 	struct drm_info_node *node = (struct drm_info_node *) m->private;
 	struct virtio_gpu_device *vgdev = node->minor->dev->dev_private;
 
-	seq_printf(m, "fence %ld %lld\n",
+	seq_printf(m, "fence %lld %lld\n",
 		   atomic64_read(&vgdev->fence_drv.last_seq),
 		   vgdev->fence_drv.sync_seq);
 	return 0;
diff --git a/drivers/gpu/drm/virtio/virtgpu_fence.c b/drivers/gpu/drm/virtio/virtgpu_fence.c
index 1da6326..98dd385 100644
--- a/drivers/gpu/drm/virtio/virtgpu_fence.c
+++ b/drivers/gpu/drm/virtio/virtgpu_fence.c
@@ -61,7 +61,7 @@ static void virtio_timeline_value_str(struct fence *f, char *str, int size)
 {
 	struct virtio_gpu_fence *fence = to_virtio_fence(f);
 
-	snprintf(str, size, "%lu", atomic64_read(&fence->drv->last_seq));
+	snprintf(str, size, "%llu", atomic64_read(&fence->drv->last_seq));
 }
 
 static const struct fence_ops virtio_fence_ops = {
-- 
1.8.3.1

_______________________________________________
Virtualization mailing list
Virtualization@lists.linux-foundation.org
https://lists.linuxfoundation.org/mailman/listinfo/virtualization

^ permalink raw reply related


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox