All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] Implement a virtio GPU transport
@ 2010-10-06 15:59 Ian Molton
  2010-10-10 15:11 ` Avi Kivity
  0 siblings, 1 reply; 64+ messages in thread
From: Ian Molton @ 2010-10-06 15:59 UTC (permalink / raw)
  To: linux-kernel

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

This patch implements a virtio-based transport for use by a virtualised 
OpenGL passthrough implementation.

The libGL and qemu-gl code to support this patch are available here:

http://gitorious.org/vm-gl-accel/qemu-gl
http://gitorious.org/vm-gl-accel/qemu-libgl


Comments please!

[-- Attachment #2: kernel_gl.patch --]
[-- Type: text/x-patch, Size: 8738 bytes --]

diff --git a/drivers/gpu/Makefile b/drivers/gpu/Makefile
index 30879df..35699a0 100644
--- a/drivers/gpu/Makefile
+++ b/drivers/gpu/Makefile
@@ -1 +1 @@
-obj-y			+= drm/ vga/
+obj-y			+= drm/ vga/ misc/
diff --git a/drivers/gpu/misc/Kconfig b/drivers/gpu/misc/Kconfig
new file mode 100644
index 0000000..50043d3
--- /dev/null
+++ b/drivers/gpu/misc/Kconfig
@@ -0,0 +1,8 @@
+config VIRTIOGL
+        tristate "Virtio userspace memory transport"
+        depends on VIRTIO_PCI
+        default n
+        help
+          A Driver to facilitate transferring data from userspace to a
+          hypervisor (eg. qemu)
+
diff --git a/drivers/gpu/misc/Makefile b/drivers/gpu/misc/Makefile
new file mode 100644
index 0000000..d9ab333
--- /dev/null
+++ b/drivers/gpu/misc/Makefile
@@ -0,0 +1 @@
+obj-$(CONFIG_VIRTIOGL)          += virtio-gl.o
diff --git a/drivers/gpu/misc/virtio-gl.c b/drivers/gpu/misc/virtio-gl.c
new file mode 100644
index 0000000..8882bda
--- /dev/null
+++ b/drivers/gpu/misc/virtio-gl.c
@@ -0,0 +1,312 @@
+/*
+ * Copyright (C) 2010 Intel Corporation
+ *
+ * Author: Ian Molton <ian.molton@collabora.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/fs.h>
+#include <linux/dma-mapping.h>
+#include <linux/sched.h>
+#include <linux/slab.h>
+#include <linux/miscdevice.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+
+#define DEVICE_NAME "glmem"
+
+/* Define to use debugging checksums on transfers */
+#undef DEBUG_GLIO
+
+struct virtio_gl_data {
+	char *buffer;
+	int pages;
+	unsigned int pid;
+};
+
+struct virtio_gl_header {
+	int pid;
+	int buf_size;
+	int r_buf_size;
+#ifdef DEBUG_GLIO
+	int sum;
+#endif
+	char buffer;
+} __packed;
+
+#define to_virtio_gl_data(a)   ((struct virtio_gl_data *)(a)->private_data)
+
+#ifdef DEBUG_GLIO
+#define SIZE_OUT_HEADER (sizeof(int)*4)
+#define SIZE_IN_HEADER (sizeof(int)*2)
+#else
+#define SIZE_OUT_HEADER (sizeof(int)*3)
+#define SIZE_IN_HEADER sizeof(int)
+#endif
+
+static struct virtqueue *vq;
+
+
+/* This is videobuf_vmalloc_to_sg() from videobuf-dma-sg.c with
+ * some modifications
+ */
+static struct scatterlist *vmalloc_to_sg(struct scatterlist *sg_list,
+				unsigned char *virt, unsigned int pages)
+{
+	struct page *pg;
+
+	/* unaligned */
+	BUG_ON((ulong)virt & ~PAGE_MASK);
+
+	/* Fill with elements for the data */
+	while (pages) {
+		pg = vmalloc_to_page(virt);
+		if (!pg)
+			goto err;
+
+		sg_set_page(sg_list, pg, PAGE_SIZE, 0);
+		virt += PAGE_SIZE;
+		sg_list++;
+		pages--;
+	}
+
+	return sg_list;
+
+err:
+	kfree(sg_list);
+	return NULL;
+}
+
+static int put_data(struct virtio_gl_data *gldata)
+{
+	struct scatterlist *sg, *sg_list;
+	unsigned int count, ret, o_page, i_page, sg_entries;
+	struct virtio_gl_header *header =
+				(struct virtio_gl_header *)gldata->buffer;
+
+	ret = header->buf_size;
+
+	o_page = (header->buf_size + PAGE_SIZE-1) >> PAGE_SHIFT;
+	i_page = (header->r_buf_size + PAGE_SIZE-1) >> PAGE_SHIFT;
+
+	header->pid = gldata->pid;
+
+	if ((o_page && i_page) &&
+		(o_page > gldata->pages || i_page > gldata->pages)) {
+		i_page = 0;
+	}
+
+	if (o_page > gldata->pages)
+		o_page = gldata->pages;
+
+	if (i_page > gldata->pages)
+		i_page = gldata->pages;
+
+	if (!o_page)
+		o_page = 1;
+
+	sg_entries = o_page + i_page;
+
+	sg_list = kcalloc(sg_entries, sizeof(struct scatterlist), GFP_KERNEL);
+
+	if (!sg_list) {
+		ret = -EIO;
+		goto out;
+	}
+
+	sg_init_table(sg_list, sg_entries);
+
+	sg = vmalloc_to_sg(sg_list, gldata->buffer, o_page);
+	sg = vmalloc_to_sg(sg, gldata->buffer, i_page);
+
+	if (!sg) {
+		ret = -EIO;
+		goto out_free;
+	}
+
+	/* Transfer data */
+	if (virtqueue_add_buf(vq, sg_list, o_page, i_page, (void *)1) >= 0) {
+		virtqueue_kick(vq);
+		/* Chill out until it's done with the buffer. */
+		while (!virtqueue_get_buf(vq, &count))
+			cpu_relax();
+	}
+
+out_free:
+	kfree(sg_list);
+out:
+	return ret;
+}
+
+static void free_buffer(struct virtio_gl_data *gldata)
+{
+	if (gldata->buffer) {
+		vfree(gldata->buffer);
+		gldata->buffer = NULL;
+	}
+}
+
+static int glmem_open(struct inode *inode, struct file *file)
+{
+	struct virtio_gl_data *gldata = kzalloc(sizeof(struct virtio_gl_data),
+						GFP_KERNEL);
+
+	if (!gldata)
+		return -ENXIO;
+
+	gldata->pid = pid_nr(task_pid(current));
+
+	file->private_data = gldata;
+
+	return 0;
+}
+
+static int glmem_mmap(struct file *filp, struct vm_area_struct *vma)
+{
+	struct virtio_gl_data *gldata = to_virtio_gl_data(filp);
+	int pages = (vma->vm_end - vma->vm_start) / PAGE_SIZE;
+
+	/* Set a reasonable limit */
+	if (pages > 16)
+		return -ENOMEM;
+
+	/* for now, just allow one buffer to be mmap()ed. */
+	if (gldata->buffer)
+		return -EIO;
+
+	gldata->buffer = vmalloc_user(pages*PAGE_SIZE);
+
+	if (!gldata->buffer)
+		return -ENOMEM;
+
+	gldata->pages = pages;
+
+	if (remap_vmalloc_range(vma, gldata->buffer, 0) < 0) {
+		vfree(gldata->buffer);
+		return -EIO;
+	}
+
+	vma->vm_flags |= VM_DONTEXPAND;
+
+	return 0;
+}
+
+static int glmem_fsync(struct file *filp, int datasync)
+{
+	struct virtio_gl_data *gldata = to_virtio_gl_data(filp);
+
+	put_data(gldata);
+
+	return 0;
+}
+
+static int glmem_release(struct inode *inode, struct file *file)
+{
+	struct virtio_gl_data *gldata = to_virtio_gl_data(file);
+
+	if (gldata && gldata->buffer) {
+		struct virtio_gl_header *header =
+				(struct virtio_gl_header *)gldata->buffer;
+
+		/* Make sure the host hears about the process ending / dying */
+		header->pid = gldata->pid;
+		header->buf_size = SIZE_OUT_HEADER + 2;
+		header->r_buf_size = SIZE_IN_HEADER;
+		*(short *)(&header->buffer) = -1;
+
+		put_data(gldata);
+		free_buffer(gldata);
+	}
+
+	kfree(gldata);
+
+	return 0;
+}
+
+static const struct file_operations glmem_fops = {
+	.owner		= THIS_MODULE,
+	.open		= glmem_open,
+	.mmap		= glmem_mmap,
+	.fsync		= glmem_fsync,
+	.release	= glmem_release,
+};
+
+static struct miscdevice glmem_dev = {
+	MISC_DYNAMIC_MINOR,
+	DEVICE_NAME,
+	&glmem_fops
+};
+
+static int glmem_probe(struct virtio_device *vdev)
+{
+	int ret;
+
+	/* We expect a single virtqueue. */
+	vq = virtio_find_single_vq(vdev, NULL, "output");
+	if (IS_ERR(vq))
+		return PTR_ERR(vq);
+
+	ret = misc_register(&glmem_dev);
+	if (ret) {
+		printk(KERN_ERR "glmem: cannot register glmem_dev as misc");
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void __devexit glmem_remove(struct virtio_device *vdev)
+{
+	vdev->config->reset(vdev);
+	misc_deregister(&glmem_dev);
+	vdev->config->del_vqs(vdev);
+}
+
+static struct virtio_device_id id_table[] = {
+	{ VIRTIO_ID_GL, VIRTIO_DEV_ANY_ID },
+	{ 0 },
+};
+
+static struct virtio_driver virtio_gl_driver = {
+	.driver	= {
+		.name =  KBUILD_MODNAME,
+		.owner = THIS_MODULE,
+	},
+	.id_table =     id_table,
+	.probe =        glmem_probe,
+	.remove =       __devexit_p(glmem_remove),
+};
+
+static int __init glmem_init(void)
+{
+	return register_virtio_driver(&virtio_gl_driver);
+}
+
+static void __exit glmem_exit(void)
+{
+	unregister_virtio_driver(&virtio_gl_driver);
+}
+
+module_init(glmem_init);
+module_exit(glmem_exit);
+
+MODULE_DEVICE_TABLE(virtio, id_table);
+MODULE_DESCRIPTION("Virtio gl passthrough driver");
+MODULE_LICENSE("GPL v2");
+
diff --git a/drivers/video/Kconfig b/drivers/video/Kconfig
index 3d94a14..9a9a6cc 100644
--- a/drivers/video/Kconfig
+++ b/drivers/video/Kconfig
@@ -16,6 +16,7 @@ source "drivers/char/agp/Kconfig"
 source "drivers/gpu/vga/Kconfig"
 
 source "drivers/gpu/drm/Kconfig"
+source "drivers/gpu/misc/Kconfig"
 
 config VGASTATE
        tristate
diff --git a/include/linux/virtio_ids.h b/include/linux/virtio_ids.h
index 06660c0..663b496 100644
--- a/include/linux/virtio_ids.h
+++ b/include/linux/virtio_ids.h
@@ -12,6 +12,7 @@
 #define VIRTIO_ID_CONSOLE	3 /* virtio console */
 #define VIRTIO_ID_RNG		4 /* virtio ring */
 #define VIRTIO_ID_BALLOON	5 /* virtio balloon */
+#define VIRTIO_ID_GL		6 /* virtio usermem */
 #define VIRTIO_ID_9P		9 /* 9p virtio console */
 
 #endif /* _LINUX_VIRTIO_IDS_H */

^ permalink raw reply related	[flat|nested] 64+ messages in thread

end of thread, other threads:[~2010-11-12 13:22 UTC | newest]

Thread overview: 64+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2010-10-06 15:59 [PATCH] Implement a virtio GPU transport Ian Molton
2010-10-10 15:11 ` Avi Kivity
2010-10-19 10:31   ` Ian Molton
2010-10-19 10:31     ` [Qemu-devel] " Ian Molton
2010-10-19 10:39     ` Avi Kivity
2010-10-19 10:39       ` [Qemu-devel] " Avi Kivity
2010-10-27 13:00       ` Ian Molton
2010-10-27 13:00         ` Ian Molton
2010-10-28  9:27         ` Avi Kivity
2010-10-28  9:27           ` Avi Kivity
2010-10-28 11:54           ` Ian Molton
2010-10-28 11:54             ` Ian Molton
2010-10-28 14:24             ` Avi Kivity
2010-10-28 14:24               ` Avi Kivity
2010-10-28 14:43               ` Anthony Liguori
2010-10-28 14:43                 ` Anthony Liguori
2010-10-28 19:50                 ` Ian Molton
2010-10-28 19:50                   ` Ian Molton
2010-10-28 20:14                   ` Anthony Liguori
2010-10-28 20:14                     ` Anthony Liguori
2010-10-28 21:41                     ` Ian Molton
2010-10-28 21:41                       ` Ian Molton
2010-10-28 19:52               ` Ian Molton
2010-11-01 10:42                 ` Avi Kivity
2010-11-01 13:21                   ` Anthony Liguori
2010-11-01 13:21                     ` Anthony Liguori
2010-11-01 15:49                     ` Ian Molton
2010-11-01 15:49                       ` Ian Molton
2010-11-01 15:57                       ` Anthony Liguori
2010-11-01 15:57                         ` Anthony Liguori
2010-11-03 17:49                         ` Ian Molton
2010-11-03 17:49                           ` Ian Molton
2010-11-01 15:50                   ` Ian Molton
2010-10-29 11:18         ` Rusty Russell
2010-10-29 11:18           ` Rusty Russell
2010-10-29 11:49           ` Ed Tomlinson
2010-10-29 11:49             ` Ed Tomlinson
2010-10-29 11:49             ` Ed Tomlinson
2010-10-29 13:05           ` Anthony Liguori
2010-10-29 13:05             ` Anthony Liguori
2010-11-01 11:53             ` Alon Levy
2010-11-01 11:53               ` Alon Levy
2010-11-01 13:28               ` Anthony Liguori
2010-11-01 13:28                 ` Anthony Liguori
2010-11-03 18:03                 ` Ian Molton
2010-11-03 18:03                   ` Ian Molton
2010-11-03 18:17                   ` Anthony Liguori
2010-11-03 18:17                     ` Anthony Liguori
2010-11-05 18:05                     ` Ian Molton
2010-11-05 18:05                       ` Ian Molton
2010-11-10 17:22                       ` Ian Molton
2010-11-10 17:22                         ` Ian Molton
2010-11-10 17:47                         ` Anthony Liguori
2010-11-10 17:47                           ` Anthony Liguori
2010-11-12 12:14                           ` Ian Molton
2010-11-12 12:14                             ` Ian Molton
2010-11-12 13:21                             ` Anthony Liguori
2010-11-12 13:21                               ` Anthony Liguori
2010-11-04  9:13                   ` Alon Levy
2010-11-04  9:13                     ` Alon Levy
2010-11-05 17:57                     ` Ian Molton
2010-11-05 17:57                       ` Ian Molton
2010-11-03 17:50           ` Ian Molton
2010-11-03 17:50             ` Ian Molton

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.