[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH v6 03/13] virtio-gpu: Add udmabuf helpers
From: |
Vivek Kasireddy |
Subject: |
[PATCH v6 03/13] virtio-gpu: Add udmabuf helpers |
Date: |
Mon, 24 May 2021 15:30:53 -0700 |
Add helper functions to create a dmabuf for a resource and mmap it.
Also, introduce the fields blob and blob_size so that these helpers
can start to use them but the full picture will emerge only after
adding create_blob API in patch 8 of this series.
To be able to create a dmabuf using the udmabuf driver, Qemu needs
to be lauched with the memfd memory backend like this:
qemu-system-x86_64 -m 8192m -object memory-backend-memfd,id=mem1,size=8192M
-machine memory-backend=mem1
Based-on-patch-by: Gerd Hoffmann <kraxel@redhat.com>
Cc: Gerd Hoffmann <kraxel@redhat.com>
Signed-off-by: Vivek Kasireddy <vivek.kasireddy@intel.com>
---
hw/display/meson.build | 2 +-
hw/display/virtio-gpu-udmabuf.c | 180 ++++++++++++++++++++++++++++++++
include/hw/virtio/virtio-gpu.h | 11 ++
3 files changed, 192 insertions(+), 1 deletion(-)
create mode 100644 hw/display/virtio-gpu-udmabuf.c
diff --git a/hw/display/meson.build b/hw/display/meson.build
index aaf797c5e9..224b33f2bb 100644
--- a/hw/display/meson.build
+++ b/hw/display/meson.build
@@ -55,7 +55,7 @@ softmmu_ss.add(when: [pixman, 'CONFIG_ATI_VGA'], if_true:
files('ati.c', 'ati_2d
if config_all_devices.has_key('CONFIG_VIRTIO_GPU')
virtio_gpu_ss = ss.source_set()
virtio_gpu_ss.add(when: 'CONFIG_VIRTIO_GPU',
- if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c'),
pixman])
+ if_true: [files('virtio-gpu-base.c', 'virtio-gpu.c',
'virtio-gpu-udmabuf.c'), pixman])
virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true:
files('vhost-user-gpu.c'))
hw_display_modules += {'virtio-gpu': virtio_gpu_ss}
diff --git a/hw/display/virtio-gpu-udmabuf.c b/hw/display/virtio-gpu-udmabuf.c
new file mode 100644
index 0000000000..1d5f3e3db2
--- /dev/null
+++ b/hw/display/virtio-gpu-udmabuf.c
@@ -0,0 +1,180 @@
+/*
+ * Virtio GPU Device
+ *
+ * Copyright Red Hat, Inc. 2013-2014
+ *
+ * Authors:
+ * Dave Airlie <airlied@redhat.com>
+ * Gerd Hoffmann <kraxel@redhat.com>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qemu/units.h"
+#include "qemu-common.h"
+#include "qemu/iov.h"
+#include "ui/console.h"
+#include "hw/virtio/virtio-gpu.h"
+#include "hw/virtio/virtio-gpu-pixman.h"
+#include "trace.h"
+
+#ifdef CONFIG_LINUX
+
+#include "exec/ramblock.h"
+#include "sysemu/hostmem.h"
+#include <sys/fcntl.h>
+#include <sys/ioctl.h>
+#include <linux/memfd.h>
+#include "standard-headers/linux/udmabuf.h"
+
+static void virtio_gpu_create_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ struct udmabuf_create_list *list;
+ RAMBlock *rb;
+ ram_addr_t offset;
+ int udmabuf, i;
+
+ udmabuf = udmabuf_fd();
+ if (udmabuf < 0) {
+ return;
+ }
+
+ list = g_malloc0(sizeof(struct udmabuf_create_list) +
+ sizeof(struct udmabuf_create_item) * res->iov_cnt);
+
+ for (i = 0; i < res->iov_cnt; i++) {
+ rcu_read_lock();
+ rb = qemu_ram_block_from_host(res->iov[i].iov_base, false, &offset);
+ rcu_read_unlock();
+
+ if (!rb || rb->fd < 0) {
+ g_free(list);
+ return;
+ }
+
+ list->list[i].memfd = rb->fd;
+ list->list[i].offset = offset;
+ list->list[i].size = res->iov[i].iov_len;
+ }
+
+ list->count = res->iov_cnt;
+ list->flags = UDMABUF_FLAGS_CLOEXEC;
+
+ res->dmabuf_fd = ioctl(udmabuf, UDMABUF_CREATE_LIST, list);
+ if (res->dmabuf_fd < 0) {
+ warn_report("%s: UDMABUF_CREATE_LIST: %s", __func__,
+ strerror(errno));
+ }
+ g_free(list);
+}
+
+static void virtio_gpu_remap_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ res->remapped = mmap(NULL, res->blob_size, PROT_READ,
+ MAP_SHARED, res->dmabuf_fd, 0);
+ if (res->remapped == MAP_FAILED) {
+ warn_report("%s: dmabuf mmap failed: %s", __func__,
+ strerror(errno));
+ res->remapped = NULL;
+ }
+}
+
+static void virtio_gpu_destroy_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ if (res->remapped) {
+ munmap(res->remapped, res->blob_size);
+ res->remapped = NULL;
+ }
+ if (res->dmabuf_fd >= 0) {
+ close(res->dmabuf_fd);
+ res->dmabuf_fd = -1;
+ }
+}
+
+static int find_memory_backend_type(Object *obj, void *opaque)
+{
+ bool *memfd_backend = opaque;
+ int ret;
+
+ if (object_dynamic_cast(obj, TYPE_MEMORY_BACKEND)) {
+ HostMemoryBackend *backend = MEMORY_BACKEND(obj);
+ RAMBlock *rb = backend->mr.ram_block;
+
+ if (rb && rb->fd > 0) {
+ ret = fcntl(rb->fd, F_GET_SEALS);
+ if (ret > 0) {
+ *memfd_backend = true;
+ }
+ }
+ }
+
+ return 0;
+}
+
+bool virtio_gpu_have_udmabuf(void)
+{
+ Object *memdev_root;
+ int udmabuf;
+ bool memfd_backend = false;
+
+ udmabuf = udmabuf_fd();
+ if (udmabuf < 0) {
+ return false;
+ }
+
+ memdev_root = object_resolve_path("/objects", NULL);
+ object_child_foreach(memdev_root, find_memory_backend_type,
&memfd_backend);
+
+ return memfd_backend;
+}
+
+void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ void *pdata = NULL;
+
+ res->dmabuf_fd = -1;
+ if (res->iov_cnt == 1) {
+ pdata = res->iov[0].iov_base;
+ } else {
+ virtio_gpu_create_udmabuf(res);
+ if (res->dmabuf_fd < 0) {
+ return;
+ }
+ virtio_gpu_remap_udmabuf(res);
+ if (!res->remapped) {
+ return;
+ }
+ pdata = res->remapped;
+ }
+
+ res->blob = pdata;
+}
+
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ if (res->remapped) {
+ virtio_gpu_destroy_udmabuf(res);
+ }
+}
+
+#else
+
+bool virtio_gpu_have_udmabuf(void)
+{
+ /* nothing (stub) */
+ return false;
+}
+
+void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ /* nothing (stub) */
+}
+
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res)
+{
+ /* nothing (stub) */
+}
+
+#endif
diff --git a/include/hw/virtio/virtio-gpu.h b/include/hw/virtio/virtio-gpu.h
index 8ca2c55d9a..265b1c516c 100644
--- a/include/hw/virtio/virtio-gpu.h
+++ b/include/hw/virtio/virtio-gpu.h
@@ -50,6 +50,12 @@ struct virtio_gpu_simple_resource {
uint32_t scanout_bitmask;
pixman_image_t *image;
uint64_t hostmem;
+
+ uint64_t blob_size;
+ void *blob;
+ int dmabuf_fd;
+ uint8_t *remapped;
+
QTAILQ_ENTRY(virtio_gpu_simple_resource) next;
};
@@ -238,6 +244,11 @@ void virtio_gpu_update_cursor_data(VirtIOGPU *g,
struct virtio_gpu_scanout *s,
uint32_t resource_id);
+/* virtio-gpu-udmabuf.c */
+bool virtio_gpu_have_udmabuf(void);
+void virtio_gpu_init_udmabuf(struct virtio_gpu_simple_resource *res);
+void virtio_gpu_fini_udmabuf(struct virtio_gpu_simple_resource *res);
+
/* virtio-gpu-3d.c */
void virtio_gpu_virgl_process_cmd(VirtIOGPU *g,
struct virtio_gpu_ctrl_command *cmd);
--
2.30.2
- [PATCH v6 00/13] virtio-gpu: Add support for Blob resources feature, Vivek Kasireddy, 2021/05/24
- [PATCH v6 01/13] ui: Get the fd associated with udmabuf driver, Vivek Kasireddy, 2021/05/24
- [PATCH v6 02/13] headers: Add udmabuf.h, Vivek Kasireddy, 2021/05/24
- [PATCH v6 03/13] virtio-gpu: Add udmabuf helpers,
Vivek Kasireddy <=
- [PATCH v6 04/13] virtio-gpu: Add virtio_gpu_find_check_resource, Vivek Kasireddy, 2021/05/24
- [PATCH v6 05/13] virtio-gpu: Refactor virtio_gpu_set_scanout, Vivek Kasireddy, 2021/05/24
- [PATCH v6 06/13] virtio-gpu: Refactor virtio_gpu_create_mapping_iov, Vivek Kasireddy, 2021/05/24
- [PATCH v6 07/13] virtio-gpu: Add initial definitions for blob resources, Vivek Kasireddy, 2021/05/24
- [PATCH v6 08/13] virtio-gpu: Add virtio_gpu_resource_create_blob, Vivek Kasireddy, 2021/05/24
- [PATCH v6 09/13] ui/pixman: Add qemu_pixman_to_drm_format(), Vivek Kasireddy, 2021/05/24
- [PATCH v6 10/13] virtio-gpu: Add helpers to create and destroy dmabuf objects, Vivek Kasireddy, 2021/05/24
- [PATCH v6 11/13] virtio-gpu: Factor out update scanout, Vivek Kasireddy, 2021/05/24