libdrm: introducde DRM dispatcher

The dispatcher will select between the various DRM drivers. For
now it is only used by the etnaviv driver.

Issue #4559.
This commit is contained in:
Josef Söntgen 2022-07-15 16:44:15 +02:00 committed by Christian Helmuth
parent 1f819a26e5
commit d2c26fd504
9 changed files with 162 additions and 47 deletions

View File

@ -0,0 +1,24 @@
/*
* \brief Libdrm ioctl back end dispatcher
* \author Josef Soentgen
* \date 2022-07-15
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
#ifndef _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_
#define _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_
namespace Libdrm {
enum Driver { INVALID, ETNAVIV };
}; /* namespace Libdrm */
void drm_init(Libdrm::Driver);
#endif /* #ifndef _INCLUDE__LIBDRM__IOCTL_DISPATCH_H_ */

View File

@ -5,6 +5,7 @@ DRM_SRC_DIR = $(call select_from_ports,libdrm)/src/lib/libdrm
endif
INC_DIR += $(DRM_SRC_DIR)
INC_DIR += $(DRM_SRC_DIR)/include
INC_DIR += $(addprefix $(DRM_SRC_DIR)/,include/etnaviv include/drm include)
INC_DIR += $(addprefix $(DRM_SRC_DIR)/,etnaviv)
INC_DIR += $(addprefix $(DRM_SRC_DIR)/,iris)

View File

@ -2,9 +2,11 @@ LIB_DIR := $(REP_DIR)/src/lib/libdrm
# include before to shadow libdrm_macros.h
INC_DIR += $(LIB_DIR)/include
INC_DIR += $(REP_DIR)/src/lib/libdrm
LIBDRM_PORT_DIR := $(call select_from_ports,libdrm)/src/lib/libdrm
REP_INC_DIR += include/libdrm
REP_INC_DIR += include/drm
LIBS := libc

View File

@ -4,4 +4,4 @@ LIBS += vfs_gpu
include $(call select_from_repositories,lib/import/import-libdrm.mk)
SRC_CC := ioctl_etnaviv.cc
SRC_CC := ioctl_dispatch.cc ioctl_etnaviv.cc

View File

@ -19,6 +19,8 @@ include:
cp -r $(PORT_DIR)/src/lib/libdrm/intel/*.h $@/intel
mkdir -p $@/etnaviv
cp -r $(PORT_DIR)/src/lib/libdrm/etnaviv/*.h $@/etnaviv
mkdir -p $@/libdrm
cp $(REP_DIR)/include/libdrm/ioctl_dispatch.h $@/libdrm
content: LICENSE

View File

@ -2,11 +2,13 @@ MIRROR_FROM_REP_DIR := lib/mk/libdrm.mk \
lib/mk/libdrm.inc \
lib/mk/spec/arm_v8/libdrm.mk \
lib/mk/spec/x86_64/libdrm.mk \
include/libdrm/ioctl_dispatch.h \
src/lib/libdrm/include \
src/lib/libdrm/dummies.c \
src/lib/libdrm/ioctl_dummy.cc \
src/lib/libdrm/ioctl_iris.cc \
src/lib/libdrm/ioctl_etnaviv.cc \
src/lib/libdrm/ioctl_dispatch.cc
content: $(MIRROR_FROM_REP_DIR) src/lib/libdrm/target.mk

View File

@ -0,0 +1,98 @@
/*
* \brief DRM ioctl back end dispatcher
* \author Josef Soentgen
* \date 2022-07-15
*/
/*
* Copyright (C) 2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
*/
/* Genode includes */
#include <base/log.h>
#include <libdrm/ioctl_dispatch.h>
extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
#include <poll.h>
}
/* etnaviv driver */
extern void etnaviv_drm_init();
extern int etnaviv_drm_ioctl(unsigned long, void *);
extern void *etnaviv_drm_mmap(off_t, size_t);
extern int etnaviv_drm_munmap(void *);
static Libdrm::Driver drm_backend_type = Libdrm::Driver::INVALID;
/**
* Initialize DRM back end and set type
*/
void drm_init(Libdrm::Driver driver)
{
switch (driver) {
case Libdrm::Driver::ETNAVIV:
etnaviv_drm_init();
drm_backend_type = Libdrm::Driver::ETNAVIV;
break;
default:
Genode::error(__func__, ": unknown back end, abort");
abort();
}
}
/**
* Perfom I/O control request
*/
extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
{
switch (drm_backend_type) {
case Libdrm::Driver::ETNAVIV: return etnaviv_drm_ioctl(request, arg);
default: return -1;
}
}
/**
* Map DRM buffer-object
*/
extern "C" void *drm_mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset)
{
(void)addr;
(void)prot;
(void)flags;
(void)fd;
switch (drm_backend_type) {
case Libdrm::Driver::ETNAVIV: return etnaviv_drm_mmap(offset, length);
default: return NULL;
}
}
/**
* Unmap DRM buffer-object
*/
extern "C" int drm_munmap(void *addr, size_t length)
{
(void)length;
switch (drm_backend_type) {
case Libdrm::Driver::ETNAVIV: return etnaviv_drm_munmap(addr);
default: return -1;
}
}

View File

@ -24,6 +24,8 @@
#include <vfs_gpu.h>
extern "C" {
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <unistd.h>
@ -36,6 +38,7 @@ extern "C" {
enum { verbose_ioctl = false };
namespace {
/**
* Get DRM command number
@ -105,8 +108,10 @@ const char *command_name(unsigned long request)
}
}
} /* anonymous namespace */
namespace Drm {
namespace Etnaviv {
size_t get_payload_size(drm_etnaviv_gem_submit const &submit);
@ -128,7 +133,7 @@ namespace Drm {
} /* anonymous namespace */
size_t Drm::get_payload_size(drm_etnaviv_gem_submit const &submit)
size_t Etnaviv::get_payload_size(drm_etnaviv_gem_submit const &submit)
{
size_t size = 0;
@ -141,7 +146,7 @@ size_t Drm::get_payload_size(drm_etnaviv_gem_submit const &submit)
}
void Drm::serialize(drm_etnaviv_gem_submit *submit, char *content)
void Etnaviv::serialize(drm_etnaviv_gem_submit *submit, char *content)
{
size_t offset = 0;
@ -204,7 +209,7 @@ void Drm::serialize(drm_etnaviv_gem_submit *submit, char *content)
}
size_t Drm::get_payload_size(drm_version const &version)
size_t Etnaviv::get_payload_size(drm_version const &version)
{
size_t size = 0;
size += version.name_len;
@ -214,7 +219,7 @@ size_t Drm::get_payload_size(drm_version const &version)
}
void Drm::serialize(drm_version *version, char *content)
void Etnaviv::serialize(drm_version *version, char *content)
{
size_t offset = 0;
char *start = 0;
@ -236,7 +241,7 @@ void Drm::serialize(drm_version *version, char *content)
}
void Drm::deserialize(drm_version *version, char *content)
void Etnaviv::deserialize(drm_version *version, char *content)
{
drm_version *cversion = reinterpret_cast<drm_version*>(content);
@ -258,8 +263,9 @@ void Drm::deserialize(drm_version *version, char *content)
}
namespace Gpu {
namespace Etnaviv {
using namespace Genode;
using namespace Gpu;
struct Call;
} /* namespace Gpu */
@ -269,16 +275,16 @@ struct Gpu::Buffer
{
Gpu::Connection &_gpu;
Id_space<Gpu::Buffer>::Element const _elem;
Genode::Id_space<Gpu::Buffer>::Element const _elem;
Dataspace_capability const cap;
size_t const size;
Genode::Dataspace_capability const cap;
size_t const size;
Constructible<Genode::Attached_dataspace> _attached_buffer { };
Genode::Constructible<Genode::Attached_dataspace> _attached_buffer { };
Buffer(Gpu::Connection &gpu,
size_t size,
Id_space<Gpu::Buffer> &space)
Buffer(Gpu::Connection &gpu,
size_t size,
Genode::Id_space<Gpu::Buffer> &space)
:
_gpu { gpu },
_elem { *this, space },
@ -312,7 +318,7 @@ struct Gpu::Buffer
};
class Gpu::Call
class Etnaviv::Call
{
private:
@ -477,7 +483,7 @@ class Gpu::Call
int _drm_etnaviv_gem_submit(drm_etnaviv_gem_submit &arg)
{
size_t const payload_size = Drm::get_payload_size(arg);
size_t const payload_size = Etnaviv::get_payload_size(arg);
if (payload_size > EXEC_BUFFER_SIZE) {
Genode::error(__func__, ": exec buffer too small (",
(unsigned)EXEC_BUFFER_SIZE, ") needed ", payload_size);
@ -490,7 +496,7 @@ class Gpu::Call
*/
char *local_exec_buffer = (char*)_exec_buffer->mmap_addr();
Genode::memset(local_exec_buffer, 0, EXEC_BUFFER_SIZE);
Drm::serialize(&arg, local_exec_buffer);
Etnaviv::serialize(&arg, local_exec_buffer);
try {
Genode::uint64_t const pending_exec_buffer =
@ -673,10 +679,10 @@ class Gpu::Call
};
static Genode::Constructible<Gpu::Call> _drm;
static Genode::Constructible<Etnaviv::Call> _drm;
void drm_init()
void etnaviv_drm_init()
{
struct ::stat buf;
if (stat("/dev/gpu", &buf) < 0) {
@ -689,9 +695,6 @@ void drm_init()
}
/**
* Dump I/O control request to LOG
*/
static void dump_ioctl(unsigned long request)
{
using namespace Genode;
@ -705,10 +708,7 @@ static void dump_ioctl(unsigned long request)
}
/**
* Perfom I/O control request
*/
extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
int etnaviv_drm_ioctl(unsigned long request, void *arg)
{
if (verbose_ioctl)
dump_ioctl(request);
@ -726,28 +726,14 @@ extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
}
/**
* Map DRM buffer-object
*/
void *drm_mmap(void *addr, size_t length, int prot, int flags,
int fd, off_t offset)
void *etnaviv_drm_mmap(off_t offset, size_t length)
{
(void)addr;
(void)prot;
(void)flags;
(void)fd;
return _drm->mmap(offset, length);
}
/**
* Unmap DRM buffer-object
*/
int drm_munmap(void *addr, size_t length)
int etnaviv_drm_munmap(void *addr)
{
(void)length;
_drm->munmap(addr);
return 0;
}

View File

@ -5,7 +5,7 @@
*/
/*
* Copyright (C) 2021 Genode Labs GmbH
* Copyright (C) 2021-2022 Genode Labs GmbH
*
* This file is part of the Genode OS framework, which is distributed
* under the terms of the GNU Affero General Public License version 3.
@ -15,13 +15,13 @@
#include <../include/util/list.h>
#include <base/env.h>
#include <libdrm/ioctl_dispatch.h>
extern "C" {
#include <platform.h>
}
extern void drm_init();
void genode_drm_init()
{
drm_init();
drm_init(Libdrm::Driver::ETNAVIV);
}