All of lore.kernel.org
 help / color / mirror / Atom feed
From: Lepton Wu <ytht.net@gmail.com>
To: dri-devel@lists.freedesktop.org
Cc: Lepton Wu <ytht.net@gmail.com>
Subject: [PATCH] RFC: drm/virtio: Dummy virtio GPU
Date: Mon, 24 Feb 2020 15:01:55 -0800	[thread overview]
Message-ID: <20200224230155.120894-2-ytht.net@gmail.com> (raw)
In-Reply-To: <20200224230155.120894-1-ytht.net@gmail.com>

The idea here is: if we run the vm headless, we don't really need to
communicate with VMM, and we even don't need any VMM support
for virtio-gpu. Of course, only 2d works. But it's enough for some
use case. And this looks simpler than vkms.

Signed-off-by: Lepton Wu <ytht.net@gmail.com>
---
 drivers/gpu/drm/virtio/Kconfig         |   9 ++
 drivers/gpu/drm/virtio/Makefile        |   3 +
 drivers/gpu/drm/virtio/virtgpu_dummy.c | 161 +++++++++++++++++++++++++
 3 files changed, 173 insertions(+)
 create mode 100644 drivers/gpu/drm/virtio/virtgpu_dummy.c

diff --git a/drivers/gpu/drm/virtio/Kconfig b/drivers/gpu/drm/virtio/Kconfig
index eff3047052d4..9c18aace38ed 100644
--- a/drivers/gpu/drm/virtio/Kconfig
+++ b/drivers/gpu/drm/virtio/Kconfig
@@ -9,3 +9,12 @@ config DRM_VIRTIO_GPU
 	   QEMU based VMMs (like KVM or Xen).
 
 	   If unsure say M.
+
+config DRM_VIRTIO_GPU_DUMMY
+	tristate "Virtio dummy GPU driver"
+	depends on DRM_VIRTIO_GPU
+	help
+	   This add a new virtio GPU device which handles the virtio ring buffers
+	   inline so it doesn't rely on VMM to provide the virtio GPU device.
+	   Currently it only handle VIRTIO_GPU_CMD_GET_DISPLAY_INFO which is enough
+	   for a dummy 2D VGA device.
diff --git a/drivers/gpu/drm/virtio/Makefile b/drivers/gpu/drm/virtio/Makefile
index 92aa2b3d349d..26d8fee1bc41 100644
--- a/drivers/gpu/drm/virtio/Makefile
+++ b/drivers/gpu/drm/virtio/Makefile
@@ -8,4 +8,7 @@ virtio-gpu-y := virtgpu_drv.o virtgpu_kms.o virtgpu_gem.o \
 	virtgpu_fence.o virtgpu_object.o virtgpu_debugfs.o virtgpu_plane.o \
 	virtgpu_ioctl.o virtgpu_prime.o virtgpu_trace_points.o
 
+virtio-gpu-dummy-y := virtgpu_dummy.o
+
 obj-$(CONFIG_DRM_VIRTIO_GPU) += virtio-gpu.o
+obj-$(CONFIG_DRM_VIRTIO_GPU_DUMMY) += virtio-gpu-dummy.o
diff --git a/drivers/gpu/drm/virtio/virtgpu_dummy.c b/drivers/gpu/drm/virtio/virtgpu_dummy.c
new file mode 100644
index 000000000000..8c2eb6fea47c
--- /dev/null
+++ b/drivers/gpu/drm/virtio/virtgpu_dummy.c
@@ -0,0 +1,161 @@
+#include <linux/module.h>
+#include <linux/virtio.h>
+#include <linux/virtio_ids.h>
+#include <linux/virtio_config.h>
+#include <linux/virtio_ring.h>
+#include <linux/virtio_gpu.h>
+
+#include "virtgpu_drv.h"
+
+static int virtgpu_dummy_width = 1024;
+static int virtgpu_dummy_height = 768;
+
+MODULE_PARM_DESC(width, "Dummy VGA width");
+module_param_named(width, virtgpu_dummy_width, int, 0400);
+MODULE_PARM_DESC(height, "Dummy VGA height");
+module_param_named(height, virtgpu_dummy_height, int, 0400);
+
+static struct bus_type dummy_bus = {
+	.name = "",
+};
+
+static struct dummy_gpu {
+	struct device *root;
+	struct virtio_device vdev;
+	unsigned char status;
+} dummy;
+
+static u64 dummy_get_features(struct virtio_device *vdev)
+{
+	return 1ULL << VIRTIO_F_VERSION_1;
+}
+
+static int dummy_finalize_features(struct virtio_device *vdev)
+{
+	return 0;
+}
+
+static void dummy_get(struct virtio_device *vdev, unsigned int offset,
+		      void *buf, unsigned len)
+{
+	static struct virtio_gpu_config config = {
+		.num_scanouts = 1,
+	};
+	BUG_ON(offset + len > sizeof(config));
+	memcpy(buf, (char *)&config + offset, len);
+}
+
+static u8 dummy_get_status(struct virtio_device *vdev)
+{
+	struct dummy_gpu*  gpu = container_of(vdev, struct dummy_gpu, vdev);
+	return gpu->status;
+}
+
+static void dummy_set_status(struct virtio_device *vdev, u8 status)
+{
+	struct dummy_gpu*  gpu = container_of(vdev, struct dummy_gpu, vdev);
+	BUG_ON(!status);
+	gpu->status = status;
+}
+
+void process_cmd(struct vring_desc *desc, int idx)
+{
+	// FIXME, use chain to get resp buffer addr
+	char *buf = __va(desc[idx].addr);
+	struct virtio_gpu_vbuffer *vbuf =
+	    (struct virtio_gpu_vbuffer *)(buf - sizeof(*vbuf));
+	struct virtio_gpu_ctrl_hdr *cmd_p = (struct virtio_gpu_ctrl_hdr *)buf;
+	struct virtio_gpu_resp_display_info *resp;
+	BUG_ON(vbuf->buf != buf);
+	if (cmd_p->type != cpu_to_le32(VIRTIO_GPU_CMD_GET_DISPLAY_INFO))
+		return;
+	BUG_ON(vbuf->resp_size != sizeof(struct virtio_gpu_resp_display_info));
+	resp = (struct virtio_gpu_resp_display_info *)vbuf->resp_buf;
+	resp->pmodes[0].r.width = virtgpu_dummy_width;
+	resp->pmodes[0].r.height = virtgpu_dummy_height;
+	resp->pmodes[0].enabled = 1;
+}
+
+static bool dummy_notify(struct virtqueue *vq)
+{
+	struct vring *r = (struct vring *)(vq + 1);
+	int used, avail;
+	// FIXME, handle multiple avail and also fix for big endian.
+	used = r->used->idx & (r->num - 1);
+	avail = (r->avail->idx - 1) & (r->num - 1);
+	r->used->ring[used].id = r->avail->ring[avail];
+	r->used->idx++;
+	if (!strcmp(vq->name, "control"))
+		process_cmd(r->desc, r->avail->ring[avail]);
+	vq->callback(vq);
+	return true;
+}
+
+static int dummy_find_vqs(struct virtio_device *vdev, unsigned nvqs,
+			  struct virtqueue *vqs[],
+			  vq_callback_t * callbacks[],
+			  const char *const names[],
+			  const bool *ctx, struct irq_affinity *desc)
+{
+	int i, j;
+	for (i = 0; i < nvqs; ++i) {
+		vqs[i] = vring_create_virtqueue(i, 256, SMP_CACHE_BYTES, vdev,
+						true, false, false,
+						dummy_notify, callbacks[i],
+						names[i]);
+		if (!vqs[i])
+			goto err;
+	}
+	return 0;
+err:
+	for (j = 0; j < i; ++j) {
+		vring_del_virtqueue(vqs[j]);
+		vqs[j] = NULL;
+	}
+	return -ENOMEM;
+}
+
+static void dummy_reset(struct virtio_device *vdev)
+{
+}
+
+static const struct virtio_config_ops dummy_vq_ops = {
+	.get_features = dummy_get_features,
+	.finalize_features = dummy_finalize_features,
+	.get = dummy_get,
+	.get_status = dummy_get_status,
+	.set_status = dummy_set_status,
+	.reset = dummy_reset,
+	.find_vqs = dummy_find_vqs,
+};
+
+static int __init virtio_gpu_dummy_init(void)
+{
+	int ret;
+	struct device * root = root_device_register("dummy");
+	if (PTR_ERR_OR_ZERO(root))
+		return PTR_ERR(root);
+	root->bus = &dummy_bus;
+	dummy.vdev.dev.parent = root;
+	dummy.vdev.id.device = VIRTIO_ID_GPU;
+	dummy.vdev.config = &dummy_vq_ops;
+	ret = register_virtio_device(&dummy.vdev);
+	if (ret) {
+		pr_err("Failed to register virtio device %d", ret);
+		root_device_unregister(root);
+		return ret;
+	}
+	dummy.root = root;
+	return 0;
+}
+
+static void virtio_gpu_dummy_exit(void)
+{
+	if (!dummy.root)
+		return;
+	unregister_virtio_device(&dummy.vdev);
+	root_device_unregister(dummy.root);
+}
+
+module_init(virtio_gpu_dummy_init);
+module_exit(virtio_gpu_dummy_exit);
-- 
2.25.0.265.gbab2e86ba0-goog

_______________________________________________
dri-devel mailing list
dri-devel@lists.freedesktop.org
https://lists.freedesktop.org/mailman/listinfo/dri-devel

  reply	other threads:[~2020-02-25  8:53 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-02-24 23:01 RFC: drm/virtio: Dummy virtio GPU Lepton Wu
2020-02-24 23:01 ` Lepton Wu [this message]
2020-02-25 10:29 ` Gerd Hoffmann
2020-02-25 18:33   ` lepton
2020-02-26  7:15     ` Gerd Hoffmann
     [not found]       ` <CALqoU4z7GYNu3DWRQcK=boGFZ=n7yHLEhEeOgXHZQ=17DMrjzQ@mail.gmail.com>
     [not found]         ` <20200226153845.nyyq4quatznhetio@sirius.home.kraxel.org>
     [not found]           ` <CALqoU4ztV6KGZDYdd2-fUY2+bJgie3-RhrgoC8B9anqTUO06zQ@mail.gmail.com>
     [not found]             ` <20200327082000.vhjs2wixv4ouxuj4@sirius.home.kraxel.org>
2020-04-15  1:48               ` lepton

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200224230155.120894-2-ytht.net@gmail.com \
    --to=ytht.net@gmail.com \
    --cc=dri-devel@lists.freedesktop.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.