libdrm/iris: use VFS/GPU plugin

Synchronize GPU completion by calling 'read' of the vfs_gpu plugin. This
enables pthreads to wait for GPU completions instead of the main EP.

issue #4380
This commit is contained in:
Sebastian Sumpf 2021-10-14 09:03:48 +02:00 committed by Norman Feske
parent b3e12dcece
commit 567b9dfa39
4 changed files with 80 additions and 38 deletions

View File

@ -3,3 +3,5 @@ include $(REP_DIR)/lib/mk/libdrm.inc
include $(call select_from_repositories,lib/import/import-libdrm.mk)
SRC_CC := ioctl_iris.cc
CC_CXX_WARN_STRICT =

View File

@ -4,6 +4,7 @@ _/src/init
_/src/libdrm
_/src/libc
_/src/vfs
_/src/vfs_gpu
_/src/expat
_/src/zlib
_/src/stdcxx

View File

@ -8,7 +8,7 @@
</requires>
<content>
<rom label="egl.lib.so"/>
<rom label="egl.lib.so"/>
<rom label="expat.lib.so"/>
<rom label="gears"/>
<rom label="glapi.lib.so"/>
@ -20,6 +20,7 @@
<rom label="mesa.lib.so"/>
<rom label="stdcxx.lib.so"/>
<rom label="vfs.lib.so"/>
<rom label="vfs_gpu.lib.so"/>
<rom label="zlib.lib.so"/>
</content>
@ -27,7 +28,7 @@
<libc stdout="/dev/log" stderr="/dev/log" rtc="/dev/rtc" />
<vfs>
<dir name="dev">
<log/> <inline name="rtc">2000-01-01 00:00</inline>
<log/> <inline name="rtc">2000-01-01 00:00</inline> <gpu/>
</dir>
</vfs>
<env key="GALLIUM_HUD" value="fps"/>

View File

@ -18,6 +18,7 @@
#include <base/heap.h>
#include <base/log.h>
#include <base/registry.h>
#include <base/shared_object.h>
#include <base/sleep.h>
#include <gpu_session/connection.h>
@ -28,11 +29,17 @@ extern "C" {
#include <errno.h>
#include <drm.h>
#include <i915_drm.h>
#include <unistd.h>
#define DRM_NUMBER(req) ((req) & 0xff)
}
namespace Libc {
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
}
using Genode::addr_t;
using Genode::Attached_dataspace;
using Genode::Constructible;
@ -251,11 +258,13 @@ class Drm_call
using Ram_quota = Genode::Ram_quota;
Genode::Env &_env;
Genode::Heap _heap { _env.ram(), _env.rm() };
Gpu::Connection _gpu_session { _env, 3*1024*1024 };
Genode::Heap &_heap;
Gpu::Connection &_gpu_session;
Gpu::Info_intel const &_gpu_info {
*_gpu_session.attached_info<Gpu::Info_intel>() };
size_t _available_gtt_size { _gpu_info.aperture_size };
int _wait_fd { 0 };
using Buffer = Gpu::Buffer;
using Buffer_space = Genode::Id_space<Buffer>;
@ -669,16 +678,6 @@ class Drm_call
}
}
/***************************
** execbuffer completion **
***************************/
void _handle_completion() { }
Genode::Io_signal_handler<Drm_call> _completion_sigh {
_env.ep(), *this, &Drm_call::_handle_completion };
/************
** ioctls **
************/
@ -884,6 +883,14 @@ class Drm_call
return 0;
}
int _device_gem_context_destroy(void *arg)
{
unsigned id = reinterpret_cast<drm_i915_gem_context_destroy *>(arg)->ctx_id;
return 0;
}
int _device_gem_context_set_param(void *arg)
{
auto * const p = reinterpret_cast<drm_i915_gem_context_param*>(arg);
@ -1166,26 +1173,23 @@ class Drm_call
}
switch (cmd) {
case DRM_I915_GEM_GET_APERTURE: return _device_gem_get_aperture_size(arg);
case DRM_I915_GETPARAM: return _device_getparam(arg);
case DRM_I915_GEM_CREATE: return _device_gem_create(arg);
case DRM_I915_GEM_MMAP: return _device_gem_mmap(arg);
case DRM_I915_GEM_MMAP_GTT: return _device_gem_mmap_gtt(arg);
case DRM_I915_GEM_SET_DOMAIN: return _device_gem_set_domain(arg);
case DRM_I915_GEM_CONTEXT_CREATE: return _device_gem_context_create(arg);
case DRM_I915_GEM_SET_TILING: return _device_gem_set_tiling(arg);
case DRM_I915_GEM_SW_FINISH: return _device_gem_sw_finish(arg);
case DRM_I915_GEM_EXECBUFFER2: return _device_gem_execbuffer2(arg);
case DRM_I915_GEM_BUSY: return _device_gem_busy(arg);
case DRM_I915_GEM_MADVISE: return _device_gem_madvise(arg);
case DRM_I915_GEM_WAIT: return 0;
case DRM_I915_QUERY: return _device_query(arg);
case DRM_I915_GEM_GET_APERTURE: return _device_gem_get_aperture_size(arg);
case DRM_I915_GETPARAM: return _device_getparam(arg);
case DRM_I915_GEM_CREATE: return _device_gem_create(arg);
case DRM_I915_GEM_MMAP: return _device_gem_mmap(arg);
case DRM_I915_GEM_MMAP_GTT: return _device_gem_mmap_gtt(arg);
case DRM_I915_GEM_SET_DOMAIN: return _device_gem_set_domain(arg);
case DRM_I915_GEM_CONTEXT_CREATE: return _device_gem_context_create(arg);
case DRM_I915_GEM_CONTEXT_DESTROY: return _device_gem_context_destroy(arg);
case DRM_I915_GEM_SET_TILING: return _device_gem_set_tiling(arg);
case DRM_I915_GEM_SW_FINISH: return _device_gem_sw_finish(arg);
case DRM_I915_GEM_EXECBUFFER2: return _device_gem_execbuffer2(arg);
case DRM_I915_GEM_BUSY: return _device_gem_busy(arg);
case DRM_I915_GEM_MADVISE: return _device_gem_madvise(arg);
case DRM_I915_GEM_WAIT: return 0;
case DRM_I915_QUERY: return _device_query(arg);
case DRM_I915_GEM_CONTEXT_SETPARAM: return _device_gem_context_set_param(arg);
case DRM_I915_GEM_CONTEXT_GETPARAM: return _device_gem_context_get_param(arg);
case DRM_I915_GEM_CONTEXT_DESTROY:
if(verbose_ioctl)
Genode::warning("DRM_IOCTL_I915_GEM_CONTEXT_DESTROY not supported");
return 0;
default:
if (verbose_ioctl)
Genode::error("Unhandled device specific ioctl:", Genode::Hex(cmd));
@ -1365,15 +1369,20 @@ class Drm_call
public:
Drm_call(Genode::Env &env)
: _env(env)
Drm_call(Genode::Env &env, Genode::Heap &heap, Gpu::Connection &gpu_session)
: _env(env), _heap(heap), _gpu_session(gpu_session)
{
/* make handle id 0 unavailable, handled as invalid by iris */
drm_syncobj_create reserve_id_0 { };
if (_generic_syncobj_create(&reserve_id_0))
Genode::warning("syncobject 0 not reserved");
_gpu_session.completion_sigh(_completion_sigh);
_wait_fd = Libc::open("/dev/gpu", 0);
if (_wait_fd < 0) {
Genode::error("Failed to open '/dev/gpu': ",
"try configure '<gpu>' in 'dev' directory of VFS'");
throw -1;
}
}
int lseek(int fd, off_t offset, int whence)
@ -1491,7 +1500,10 @@ class Drm_call
if (_gpu_session.complete(seqno)) {
break;
}
_env.ep().wait_and_dispatch_one_io_signal();
/* wait for completion signal in VFS plugin */
char buf;
Libc::read(_wait_fd, &buf, 1);
}
/* mark done buffer objects */
@ -1511,7 +1523,27 @@ static Genode::Constructible<Drm_call> _call;
void drm_init(Genode::Env &env)
{
_call.construct(env);
using namespace Genode;
/*
* XXX: lookup Gpu::Connection via 'Gpu::Connection &vfs_gpu_connection()' in
* vfs_gpu.lib.so' VFS plugin
*/
static Heap heap { env.ram(), env.rm() };
try {
Shared_object object { env, heap, "vfs_gpu.lib.so",
Shared_object::BIND_LAZY,
Shared_object::DONT_KEEP };
void *vfs_gpu_connection = object.lookup("_Z18vfs_gpu_connectionv");
log("libdrm (iris): 'vfs_gpu_connection' found at: ", vfs_gpu_connection);
Gpu::Connection &gpu_session = ((Gpu::Connection & (*)())vfs_gpu_connection)();
_call.construct(env, heap, gpu_session);
} catch (Shared_object::Invalid_rom_module) {
Genode::error("'vfs_gpu.lib.so' plugin not found");
} catch (...) { }
}
@ -1524,6 +1556,8 @@ extern "C" void *drm_mmap(void * /* vaddr */, size_t length,
int /* prot */, int /* flags */,
int /* fd */, off_t offset)
{
if (_call.constructed() == false) { errno = EIO; return nullptr; }
/* sanity check if we got a GTT mapped offset */
bool const ok = _call->map_buffer_ggtt(offset, length);
return ok ? (void *)offset : nullptr;
@ -1534,6 +1568,8 @@ extern "C" void *drm_mmap(void * /* vaddr */, size_t length,
*/
extern "C" int drm_munmap(void *addr, size_t length)
{
if (_call.constructed() == false) { errno = EIO; return -1; }
_call->unmap_buffer(addr, length);
return 0;
}
@ -1555,7 +1591,9 @@ extern "C" int drm_lseek(int fd, off_t offset, int whence)
extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg)
{
if (_call.constructed() == false) { errno = EIO; return -1; }
if (verbose_ioctl) { dump_ioctl(request); }
int const ret = _call->ioctl(request, arg);
if (verbose_ioctl) { Genode::log("returned ", ret); }
return ret;