virtio-gpu: Add udmabuf helpers
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> Message-Id: <20210526231429.1045476-4-vivek.kasireddy@intel.com> Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>
This commit is contained in:
parent
4d01086161
commit
9b60cdf987
@ -56,6 +56,7 @@ 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])
|
||||
virtio_gpu_ss.add(when: 'CONFIG_LINUX', if_true: files('virtio-gpu-udmabuf.c'))
|
||||
virtio_gpu_ss.add(when: 'CONFIG_VHOST_USER_GPU', if_true: files('vhost-user-gpu.c'))
|
||||
hw_display_modules += {'virtio-gpu': virtio_gpu_ss}
|
||||
|
||||
|
158
hw/display/virtio-gpu-udmabuf.c
Normal file
158
hw/display/virtio-gpu-udmabuf.c
Normal file
@ -0,0 +1,158 @@
|
||||
/*
|
||||
* 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"
|
||||
#include "exec/ramblock.h"
|
||||
#include "sysemu/hostmem.h"
|
||||
#include <sys/ioctl.h>
|
||||
#include <fcntl.h>
|
||||
#include <linux/memfd.h>
|
||||
#include "qemu/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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user