[RFC PATCH] virtio: Add driver for virtio gpu
Daniel Palmer
daniel at thingy.jp
Sat May 23 07:50:00 CEST 2026
Add a basic driver for virtio gpu. This allows for a video on
qemu virt machines.
Signed-off-by: Daniel Palmer <daniel at thingy.jp>
---
Since the m68k virtio stuff is now in next I thought I'd send this.
This patch is based on next.
This is a very simple driver for virtio gpu that works just enough
to create a framebuffer that u-boot can use.
I've been playing with this on m68k and its shown that some of the
framebuffer code has some endian issues.
I think this is useful for testing the framebuffer code on other
arches like arm, riscv and so on.
Open to comments, ideas etc.
drivers/virtio/Kconfig | 19 ++
drivers/virtio/Makefile | 1 +
drivers/virtio/virtio-uclass.c | 1 +
drivers/virtio/virtio_gpu.c | 284 ++++++++++++++++++++
drivers/virtio/virtio_gpu.h | 461 +++++++++++++++++++++++++++++++++
include/virtio.h | 10 +-
6 files changed, 772 insertions(+), 4 deletions(-)
create mode 100644 drivers/virtio/virtio_gpu.c
create mode 100644 drivers/virtio/virtio_gpu.h
diff --git a/drivers/virtio/Kconfig b/drivers/virtio/Kconfig
index 512ac376f185..d554346a2772 100644
--- a/drivers/virtio/Kconfig
+++ b/drivers/virtio/Kconfig
@@ -77,4 +77,23 @@ config VIRTIO_RNG
help
This is the virtual random number generator driver. It can be used
with QEMU based targets.
+
+config VIRTIO_GPU
+ bool "virtio gpu driver"
+ depends on VIDEO
+ depends on VIRTIO
+ help
+ This is the virtual GPU driver. It can be used
+ with QEMU based targets.
+
+if VIRTIO_GPU
+config VIRTIO_DEFAULT_WIDTH
+ int "default width"
+ default 1024
+
+config VIRTIO_DEFAULT_HEIGHT
+ int "default height"
+ default 768
+endif
+
endmenu
diff --git a/drivers/virtio/Makefile b/drivers/virtio/Makefile
index 4c63a6c69043..c830fb6e6049 100644
--- a/drivers/virtio/Makefile
+++ b/drivers/virtio/Makefile
@@ -11,3 +11,4 @@ obj-$(CONFIG_VIRTIO_SANDBOX) += virtio_sandbox.o
obj-$(CONFIG_VIRTIO_NET) += virtio_net.o
obj-$(CONFIG_VIRTIO_BLK) += virtio_blk.o
obj-$(CONFIG_VIRTIO_RNG) += virtio_rng.o
+obj-$(CONFIG_VIRTIO_GPU) += virtio_gpu.o
diff --git a/drivers/virtio/virtio-uclass.c b/drivers/virtio/virtio-uclass.c
index c36e9e9b3a77..f040907e3a84 100644
--- a/drivers/virtio/virtio-uclass.c
+++ b/drivers/virtio/virtio-uclass.c
@@ -30,6 +30,7 @@ static const char *const virtio_drv_name[VIRTIO_ID_MAX_NUM] = {
[VIRTIO_ID_NET] = VIRTIO_NET_DRV_NAME,
[VIRTIO_ID_BLOCK] = VIRTIO_BLK_DRV_NAME,
[VIRTIO_ID_RNG] = VIRTIO_RNG_DRV_NAME,
+ [VIRTIO_ID_GPU] = VIRTIO_GPU_DRV_NAME,
};
int virtio_get_config(struct udevice *vdev, unsigned int offset,
diff --git a/drivers/virtio/virtio_gpu.c b/drivers/virtio/virtio_gpu.c
new file mode 100644
index 000000000000..cd4dbc6857aa
--- /dev/null
+++ b/drivers/virtio/virtio_gpu.c
@@ -0,0 +1,284 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * virtio GPU driver
+ * 2025 Daniel Palmer <daniel at thingy.jp>
+ */
+
+#include <dm.h>
+#include <malloc.h>
+#include <video.h>
+#include <virtio_types.h>
+#include <virtio.h>
+#include <virtio_ring.h>
+
+#include "virtio_gpu.h"
+
+#define VQ_CONTROL 0
+#define VQ_CURSOR 1
+#define NUM_VQS 2
+#define FRAMEBUFFER_RESOURCE_ID 1
+
+struct virtio_gpu_priv {
+ struct virtqueue *vqs[NUM_VQS];
+};
+
+static int virtio_gpu_cmd(struct virtqueue *vq,
+ void *req, size_t req_size,
+ void *resp, size_t resp_size)
+{
+ struct virtio_sg resp_sg = { resp, resp_size };
+ struct virtio_sg req_sg = { req, req_size };
+ struct virtio_sg *sgs[] = { &req_sg, &resp_sg };
+ struct virtio_gpu_ctrl_hdr *resp_hdr = resp;
+ int ret;
+
+ ret = virtqueue_add(vq, sgs, 1, 1);
+ if (ret)
+ return ret;
+
+ virtqueue_kick(vq);
+
+ while (!virtqueue_get_buf(vq, NULL))
+ ;
+
+ /* Some basic error handling */
+ switch (le32_to_cpu(resp_hdr->type)) {
+ case VIRTIO_GPU_RESP_ERR_UNSPEC:
+ case VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID:
+ case VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID:
+ case VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID:
+ case VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER:
+ return -EINVAL;
+ case VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY:
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+static int virtio_gpu_get_display_info(struct virtqueue *vq,
+ struct virtio_gpu_resp_display_info *info)
+{
+ struct virtio_gpu_ctrl_hdr req = {
+ .type = cpu_to_le32(VIRTIO_GPU_CMD_GET_DISPLAY_INFO),
+ };
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), info, sizeof(*info));
+}
+
+static int virtio_gpu_resource_create_2d(struct virtqueue *vq,
+ u32 resource_id,
+ u32 format,
+ u32 width,
+ u32 height)
+{
+ struct virtio_gpu_resource_create_2d req = {
+ .hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_CREATE_2D),
+ .resource_id = cpu_to_le32(resource_id),
+ .format = cpu_to_le32(format),
+ .width = cpu_to_le32(width),
+ .height = cpu_to_le32(height),
+ };
+ struct virtio_gpu_ctrl_hdr resp;
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), &resp, sizeof(resp));
+}
+
+struct virtio_gpu_attach_backing_hdr_ent {
+ struct virtio_gpu_resource_attach_backing hdr;
+ struct virtio_gpu_mem_entry entry;
+};
+
+static int virtio_gpu_resource_attach_backing(struct virtqueue *vq,
+ u32 resource_id,
+ u64 addr,
+ u32 length)
+{
+ struct virtio_gpu_attach_backing_hdr_ent req = {
+ .hdr = {
+ .hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING),
+ .resource_id = cpu_to_le32(resource_id),
+ .nr_entries = cpu_to_le32(1),
+ },
+ .entry = {
+ .addr = cpu_to_le64(addr),
+ .length = cpu_to_le32(length),
+ },
+ };
+ struct virtio_gpu_ctrl_hdr resp;
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), &resp, sizeof(resp));
+}
+
+static int virtio_gpu_set_scanout(struct virtqueue *vq,
+ u32 resource_id,
+ u32 width, u32 height)
+{
+ struct virtio_gpu_set_scanout req = {
+ .hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_SET_SCANOUT),
+ .resource_id = cpu_to_le32(resource_id),
+ .r = {
+ .width = cpu_to_le32(width),
+ .height = cpu_to_le32(height),
+ },
+ };
+ struct virtio_gpu_ctrl_hdr resp;
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), &resp, sizeof(resp));
+}
+
+static int virtio_gpu_set_transfer_to_host_2d(struct virtqueue *vq,
+ u32 resource_id,
+ u32 width,
+ u32 height)
+{
+ struct virtio_gpu_transfer_to_host_2d req = {
+ .hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D),
+ .resource_id = cpu_to_le32(resource_id),
+ .r = {
+ .width = cpu_to_le32(width),
+ .height = cpu_to_le32(height),
+ },
+ };
+ struct virtio_gpu_ctrl_hdr resp;
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), &resp, sizeof(resp));
+}
+
+static int virtio_gpu_resource_flush(struct virtqueue *vq,
+ u32 resource_id,
+ u32 width,
+ u32 height)
+{
+ struct virtio_gpu_resource_flush req = {
+ .hdr.type = cpu_to_le32(VIRTIO_GPU_CMD_RESOURCE_FLUSH),
+ .resource_id = cpu_to_le32(resource_id),
+ .r = {
+ .width = cpu_to_le32(width),
+ .height = cpu_to_le32(height),
+ },
+ };
+ struct virtio_gpu_ctrl_hdr resp;
+
+ return virtio_gpu_cmd(vq, &req, sizeof(req), &resp, sizeof(resp));
+}
+
+static int virtio_gpu_flush(struct udevice *dev)
+{
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct virtio_gpu_priv *priv = dev_get_priv(dev);
+ struct virtqueue *vq = priv->vqs[VQ_CONTROL];
+ int ret;
+
+ ret = virtio_gpu_set_transfer_to_host_2d(vq,
+ FRAMEBUFFER_RESOURCE_ID,
+ uc_priv->xsize,
+ uc_priv->ysize);
+ if (ret)
+ return ret;
+
+ ret = virtio_gpu_resource_flush(vq,
+ FRAMEBUFFER_RESOURCE_ID,
+ uc_priv->xsize,
+ uc_priv->ysize);
+
+ return ret;
+}
+
+static int virtio_gpu_probe(struct udevice *dev)
+{
+ struct video_uc_plat *plat = dev_get_uclass_plat(dev);
+ struct video_priv *uc_priv = dev_get_uclass_priv(dev);
+ struct virtio_gpu_priv *priv = dev_get_priv(dev);
+ struct virtio_gpu_resp_display_info display_info;
+ struct virtqueue *vq;
+ u32 width, height;
+ int ret;
+ int i;
+
+ width = CONFIG_VIRTIO_DEFAULT_WIDTH;
+ height = CONFIG_VIRTIO_DEFAULT_HEIGHT;
+
+ ret = virtio_find_vqs(dev, NUM_VQS, priv->vqs);
+ if (ret)
+ return ret;
+
+ vq = priv->vqs[VQ_CONTROL];
+
+ ret = virtio_gpu_get_display_info(vq,
+ &display_info);
+ if (ret)
+ return ret;
+
+ for (i = 0; i < VIRTIO_GPU_MAX_SCANOUTS; i++) {
+ u32 h = le32_to_cpu(display_info.pmodes[i].r.height);
+ u32 w = le32_to_cpu(display_info.pmodes[i].r.width);
+ u32 e = le32_to_cpu(display_info.pmodes[i].enabled);
+
+ if (!e)
+ continue;
+
+ /* For now just use the first enabled one */
+ width = w;
+ height = h;
+ break;
+ }
+
+ /* Just use 32 bpp rgba for now */
+ uc_priv->xsize = width;
+ uc_priv->ysize = height;
+ uc_priv->bpix = VIDEO_BPP32;
+ uc_priv->format = VIDEO_RGBA8888;
+
+ ret = virtio_gpu_resource_create_2d(vq,
+ FRAMEBUFFER_RESOURCE_ID,
+ VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM,
+ uc_priv->xsize,
+ uc_priv->ysize);
+ if (ret)
+ return ret;
+
+ /* virtio GPU apparently doesn't care about alignment */
+ plat->size = (width * height) * 4;
+ plat->base = (ulong)malloc(plat->size);
+ if (!plat->base)
+ return -ENOMEM;
+
+ ret = virtio_gpu_resource_attach_backing(vq,
+ FRAMEBUFFER_RESOURCE_ID,
+ plat->base,
+ round_up(plat->size, 4096));
+ if (ret)
+ goto err;
+
+ ret = virtio_gpu_set_scanout(vq,
+ FRAMEBUFFER_RESOURCE_ID,
+ uc_priv->xsize,
+ uc_priv->ysize);
+ if (ret)
+ goto err;
+
+ /* Do an initial flush to activate the output */
+ ret = virtio_gpu_flush(dev);
+ if (ret)
+ goto err;
+
+ return 0;
+
+err:
+ free((void *)plat->base);
+ return ret;
+}
+
+static const struct video_ops virtio_gpu_ops = {
+ .video_sync = virtio_gpu_flush,
+};
+
+U_BOOT_DRIVER(virtio_gpu) = {
+ .name = VIRTIO_GPU_DRV_NAME,
+ .id = UCLASS_VIDEO,
+ .ops = &virtio_gpu_ops,
+ .probe = virtio_gpu_probe,
+ .flags = DM_FLAG_ACTIVE_DMA,
+ .priv_auto = sizeof(struct virtio_gpu_priv),
+};
diff --git a/drivers/virtio/virtio_gpu.h b/drivers/virtio/virtio_gpu.h
new file mode 100644
index 000000000000..6732c7218ca2
--- /dev/null
+++ b/drivers/virtio/virtio_gpu.h
@@ -0,0 +1,461 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied at redhat.com>
+ * Gerd Hoffmann <kraxel at redhat.com>
+ *
+ * This header is BSD licensed so anyone can use the definitions
+ * to implement compatible drivers/servers:
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of IBM nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL IBM OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#ifndef VIRTIO_GPU_HW_H
+#define VIRTIO_GPU_HW_H
+
+#include <linux/types.h>
+
+/*
+ * VIRTIO_GPU_CMD_CTX_*
+ * VIRTIO_GPU_CMD_*_3D
+ */
+#define VIRTIO_GPU_F_VIRGL 0
+
+/*
+ * VIRTIO_GPU_CMD_GET_EDID
+ */
+#define VIRTIO_GPU_F_EDID 1
+/*
+ * VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID
+ */
+#define VIRTIO_GPU_F_RESOURCE_UUID 2
+
+/*
+ * VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB
+ */
+#define VIRTIO_GPU_F_RESOURCE_BLOB 3
+/*
+ * VIRTIO_GPU_CMD_CREATE_CONTEXT with
+ * context_init and multiple timelines
+ */
+#define VIRTIO_GPU_F_CONTEXT_INIT 4
+
+enum virtio_gpu_ctrl_type {
+ VIRTIO_GPU_UNDEFINED = 0,
+
+ /* 2d commands */
+ VIRTIO_GPU_CMD_GET_DISPLAY_INFO = 0x0100,
+ VIRTIO_GPU_CMD_RESOURCE_CREATE_2D,
+ VIRTIO_GPU_CMD_RESOURCE_UNREF,
+ VIRTIO_GPU_CMD_SET_SCANOUT,
+ VIRTIO_GPU_CMD_RESOURCE_FLUSH,
+ 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,
+ VIRTIO_GPU_CMD_GET_EDID,
+ VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID,
+ VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB,
+ VIRTIO_GPU_CMD_SET_SCANOUT_BLOB,
+
+ /* 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,
+ VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB,
+ VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB,
+
+ /* cursor commands */
+ VIRTIO_GPU_CMD_UPDATE_CURSOR = 0x0300,
+ VIRTIO_GPU_CMD_MOVE_CURSOR,
+
+ /* 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,
+ VIRTIO_GPU_RESP_OK_EDID,
+ VIRTIO_GPU_RESP_OK_RESOURCE_UUID,
+ VIRTIO_GPU_RESP_OK_MAP_INFO,
+
+ /* error responses */
+ VIRTIO_GPU_RESP_ERR_UNSPEC = 0x1200,
+ VIRTIO_GPU_RESP_ERR_OUT_OF_MEMORY,
+ VIRTIO_GPU_RESP_ERR_INVALID_SCANOUT_ID,
+ VIRTIO_GPU_RESP_ERR_INVALID_RESOURCE_ID,
+ VIRTIO_GPU_RESP_ERR_INVALID_CONTEXT_ID,
+ VIRTIO_GPU_RESP_ERR_INVALID_PARAMETER,
+};
+
+enum virtio_gpu_shm_id {
+ VIRTIO_GPU_SHM_ID_UNDEFINED = 0,
+ /*
+ * VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB
+ * VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB
+ */
+ VIRTIO_GPU_SHM_ID_HOST_VISIBLE = 1
+};
+
+#define VIRTIO_GPU_FLAG_FENCE (1 << 0)
+/*
+ * If the following flag is set, then ring_idx contains the index
+ * of the command ring that needs to used when creating the fence
+ */
+#define VIRTIO_GPU_FLAG_INFO_RING_IDX (1 << 1)
+
+struct virtio_gpu_ctrl_hdr {
+ __le32 type;
+ __le32 flags;
+ __le64 fence_id;
+ __le32 ctx_id;
+ __u8 ring_idx;
+ __u8 padding[3];
+};
+
+/* data passed in the cursor vq */
+
+struct virtio_gpu_cursor_pos {
+ __le32 scanout_id;
+ __le32 x;
+ __le32 y;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_UPDATE_CURSOR, VIRTIO_GPU_CMD_MOVE_CURSOR */
+struct virtio_gpu_update_cursor {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_cursor_pos pos; /* update & move */
+ __le32 resource_id; /* update only */
+ __le32 hot_x; /* update only */
+ __le32 hot_y; /* update only */
+ __le32 padding;
+};
+
+/* data passed in the control vq, 2d related */
+
+struct virtio_gpu_rect {
+ __le32 x;
+ __le32 y;
+ __le32 width;
+ __le32 height;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_UNREF */
+struct virtio_gpu_resource_unref {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_CREATE_2D: create a 2d resource with a format */
+struct virtio_gpu_resource_create_2d {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 format;
+ __le32 width;
+ __le32 height;
+};
+
+/* VIRTIO_GPU_CMD_SET_SCANOUT */
+struct virtio_gpu_set_scanout {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_rect r;
+ __le32 scanout_id;
+ __le32 resource_id;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_FLUSH */
+struct virtio_gpu_resource_flush {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_rect r;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D: simple transfer to_host */
+struct virtio_gpu_transfer_to_host_2d {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_rect r;
+ __le64 offset;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+struct virtio_gpu_mem_entry {
+ __le64 addr;
+ __le32 length;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_ATTACH_BACKING */
+struct virtio_gpu_resource_attach_backing {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 nr_entries;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_DETACH_BACKING */
+struct virtio_gpu_resource_detach_backing {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_DISPLAY_INFO */
+#define VIRTIO_GPU_MAX_SCANOUTS 16
+struct virtio_gpu_resp_display_info {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_display_one {
+ struct virtio_gpu_rect r;
+ __le32 enabled;
+ __le32 flags;
+ } 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 */
+#define VIRTIO_GPU_CONTEXT_INIT_CAPSET_ID_MASK 0x000000ff
+struct virtio_gpu_ctx_create {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 nlen;
+ __le32 context_init;
+ 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
+#define VIRTIO_GPU_CAPSET_VIRGL2 2
+#define VIRTIO_GPU_CAPSET_GFXSTREAM_VULKAN 3
+#define VIRTIO_GPU_CAPSET_VENUS 4
+#define VIRTIO_GPU_CAPSET_CROSS_DOMAIN 5
+#define VIRTIO_GPU_CAPSET_DRM 6
+
+/* 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;
+ __u8 capset_data[];
+};
+
+/* VIRTIO_GPU_CMD_GET_EDID */
+struct virtio_gpu_cmd_get_edid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 scanout;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_EDID */
+struct virtio_gpu_resp_edid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 size;
+ __le32 padding;
+ __u8 edid[1024];
+};
+
+#define VIRTIO_GPU_EVENT_DISPLAY (1 << 0)
+
+struct virtio_gpu_config {
+ __le32 events_read;
+ __le32 events_clear;
+ __le32 num_scanouts;
+ __le32 num_capsets;
+};
+
+/* simple formats for fbcon/X use */
+enum virtio_gpu_formats {
+ VIRTIO_GPU_FORMAT_B8G8R8A8_UNORM = 1,
+ VIRTIO_GPU_FORMAT_B8G8R8X8_UNORM = 2,
+ VIRTIO_GPU_FORMAT_A8R8G8B8_UNORM = 3,
+ VIRTIO_GPU_FORMAT_X8R8G8B8_UNORM = 4,
+
+ VIRTIO_GPU_FORMAT_R8G8B8A8_UNORM = 67,
+ VIRTIO_GPU_FORMAT_X8B8G8R8_UNORM = 68,
+
+ VIRTIO_GPU_FORMAT_A8B8G8R8_UNORM = 121,
+ VIRTIO_GPU_FORMAT_R8G8B8X8_UNORM = 134,
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_ASSIGN_UUID */
+struct virtio_gpu_resource_assign_uuid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+/* VIRTIO_GPU_RESP_OK_RESOURCE_UUID */
+struct virtio_gpu_resp_resource_uuid {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __u8 uuid[16];
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_CREATE_BLOB */
+struct virtio_gpu_resource_create_blob {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+#define VIRTIO_GPU_BLOB_MEM_GUEST 0x0001
+#define VIRTIO_GPU_BLOB_MEM_HOST3D 0x0002
+#define VIRTIO_GPU_BLOB_MEM_HOST3D_GUEST 0x0003
+
+#define VIRTIO_GPU_BLOB_FLAG_USE_MAPPABLE 0x0001
+#define VIRTIO_GPU_BLOB_FLAG_USE_SHAREABLE 0x0002
+#define VIRTIO_GPU_BLOB_FLAG_USE_CROSS_DEVICE 0x0004
+ /* zero is invalid blob mem */
+ __le32 blob_mem;
+ __le32 blob_flags;
+ __le32 nr_entries;
+ __le64 blob_id;
+ __le64 size;
+ /*
+ * sizeof(nr_entries * virtio_gpu_mem_entry) bytes follow
+ */
+};
+
+/* VIRTIO_GPU_CMD_SET_SCANOUT_BLOB */
+struct virtio_gpu_set_scanout_blob {
+ struct virtio_gpu_ctrl_hdr hdr;
+ struct virtio_gpu_rect r;
+ __le32 scanout_id;
+ __le32 resource_id;
+ __le32 width;
+ __le32 height;
+ __le32 format;
+ __le32 padding;
+ __le32 strides[4];
+ __le32 offsets[4];
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_MAP_BLOB */
+struct virtio_gpu_resource_map_blob {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 padding;
+ __le64 offset;
+};
+
+/* VIRTIO_GPU_RESP_OK_MAP_INFO */
+#define VIRTIO_GPU_MAP_CACHE_MASK 0x0f
+#define VIRTIO_GPU_MAP_CACHE_NONE 0x00
+#define VIRTIO_GPU_MAP_CACHE_CACHED 0x01
+#define VIRTIO_GPU_MAP_CACHE_UNCACHED 0x02
+#define VIRTIO_GPU_MAP_CACHE_WC 0x03
+struct virtio_gpu_resp_map_info {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __u32 map_info;
+ __u32 padding;
+};
+
+/* VIRTIO_GPU_CMD_RESOURCE_UNMAP_BLOB */
+struct virtio_gpu_resource_unmap_blob {
+ struct virtio_gpu_ctrl_hdr hdr;
+ __le32 resource_id;
+ __le32 padding;
+};
+
+#endif
diff --git a/include/virtio.h b/include/virtio.h
index 3edf023463d7..f53158e355b1 100644
--- a/include/virtio.h
+++ b/include/virtio.h
@@ -28,14 +28,16 @@
#define VIRTIO_VENDOR_QEMU 0x554d4551
-#define VIRTIO_ID_NET 1 /* virtio net */
-#define VIRTIO_ID_BLOCK 2 /* virtio block */
-#define VIRTIO_ID_RNG 4 /* virtio rng */
-#define VIRTIO_ID_MAX_NUM 5
+#define VIRTIO_ID_NET 1 /* virtio net */
+#define VIRTIO_ID_BLOCK 2 /* virtio block */
+#define VIRTIO_ID_RNG 4 /* virtio rng */
+#define VIRTIO_ID_GPU 16 /* virtio gpu */
+#define VIRTIO_ID_MAX_NUM 17
#define VIRTIO_NET_DRV_NAME "virtio-net"
#define VIRTIO_BLK_DRV_NAME "virtio-blk"
#define VIRTIO_RNG_DRV_NAME "virtio-rng"
+#define VIRTIO_GPU_DRV_NAME "virtio-gpu"
/* Status byte for guest to report progress, and synchronize features */
--
2.53.0
More information about the U-Boot
mailing list