From dd904241297adebc33efb1ac656e4375a571775f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Mon, 5 Jul 2021 17:44:45 +0200 Subject: [PATCH] libports: libdrm-2.4.105 update MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Support for iris and etnvaviv * entaviv: - libdrm on FreeBSD is not prepared for !PCI (and libc our is missing - missing include in xf86drmMode.c - etnaviv relies on linux header files - dummy in $(INC_DIR) - IOCTL FreeBSD ↔ Linux have swapped IO/OUT bit - O_CLOEXEC differs between FreeBSD ↔ Linux issue #4254 --- .../libports/lib/import/import-libdrm-iris.mk | 3 + repos/libports/lib/import/import-libdrm.mk | 9 + repos/libports/lib/mk/libdrm.inc | 33 + repos/libports/lib/mk/libdrm.mk | 5 + repos/libports/lib/mk/spec/arm_v8/libdrm.mk | 8 + .../lib/mk/spec/x86_64/libdrm-iris.mk | 5 + repos/libports/lib/symbols/libdrm | 321 +++++ repos/libports/ports/libdrm.hash | 2 +- repos/libports/ports/libdrm.port | 13 +- repos/libports/recipes/api/libdrm/content.mk | 27 + repos/libports/recipes/api/libdrm/hash | 1 + repos/libports/recipes/src/libdrm/api | 1 + repos/libports/recipes/src/libdrm/content.mk | 39 + repos/libports/recipes/src/libdrm/hash | 1 + repos/libports/recipes/src/libdrm/used_apis | 3 + repos/libports/src/lib/libdrm/dummies.c | 6 + repos/libports/src/lib/libdrm/files.list | 42 + .../src/lib/libdrm/include/genode_types.h | 9 + .../src/lib/libdrm/include/libdrm_macros.h | 18 + .../src/lib/libdrm/include/linux/stddef.h | 0 .../src/lib/libdrm/include/linux/types.h | 0 repos/libports/src/lib/libdrm/ioctl_dummy.cc | 56 + .../libports/src/lib/libdrm/ioctl_etnaviv.cc | 488 +++++++ repos/libports/src/lib/libdrm/ioctl_iris.cc | 1190 +++++++++++++++++ .../src/lib/libdrm/patches/util_match.patch | 14 + .../src/lib/libdrm/patches/xf86drmMode.patch | 11 + 26 files changed, 2301 insertions(+), 4 deletions(-) create mode 100644 repos/libports/lib/import/import-libdrm-iris.mk create mode 100644 repos/libports/lib/import/import-libdrm.mk create mode 100644 repos/libports/lib/mk/libdrm.inc create mode 100644 repos/libports/lib/mk/libdrm.mk create mode 100644 repos/libports/lib/mk/spec/arm_v8/libdrm.mk create mode 100644 repos/libports/lib/mk/spec/x86_64/libdrm-iris.mk create mode 100644 repos/libports/lib/symbols/libdrm create mode 100644 repos/libports/recipes/api/libdrm/content.mk create mode 100644 repos/libports/recipes/api/libdrm/hash create mode 100644 repos/libports/recipes/src/libdrm/api create mode 100644 repos/libports/recipes/src/libdrm/content.mk create mode 100644 repos/libports/recipes/src/libdrm/hash create mode 100644 repos/libports/recipes/src/libdrm/used_apis create mode 100644 repos/libports/src/lib/libdrm/dummies.c create mode 100644 repos/libports/src/lib/libdrm/files.list create mode 100644 repos/libports/src/lib/libdrm/include/genode_types.h create mode 100644 repos/libports/src/lib/libdrm/include/libdrm_macros.h create mode 100644 repos/libports/src/lib/libdrm/include/linux/stddef.h create mode 100644 repos/libports/src/lib/libdrm/include/linux/types.h create mode 100644 repos/libports/src/lib/libdrm/ioctl_dummy.cc create mode 100644 repos/libports/src/lib/libdrm/ioctl_etnaviv.cc create mode 100644 repos/libports/src/lib/libdrm/ioctl_iris.cc create mode 100644 repos/libports/src/lib/libdrm/patches/util_match.patch create mode 100644 repos/libports/src/lib/libdrm/patches/xf86drmMode.patch diff --git a/repos/libports/lib/import/import-libdrm-iris.mk b/repos/libports/lib/import/import-libdrm-iris.mk new file mode 100644 index 0000000000..33fd58200e --- /dev/null +++ b/repos/libports/lib/import/import-libdrm-iris.mk @@ -0,0 +1,3 @@ +include $(REP_DIR)/lib/import/import-libdrm.inc + +INC_DIR += $(DRM_SRC_DIR) $(addprefix $(DRM_SRC_DIR)/,iris) diff --git a/repos/libports/lib/import/import-libdrm.mk b/repos/libports/lib/import/import-libdrm.mk new file mode 100644 index 0000000000..2e1281e753 --- /dev/null +++ b/repos/libports/lib/import/import-libdrm.mk @@ -0,0 +1,9 @@ +ifeq ($(CONTRIB_DIR),) +DRM_SRC_DIR = $(realpath $(call select_from_repositories,include/drm)/../..) +else +DRM_SRC_DIR = $(call select_from_ports,libdrm)/src/lib/libdrm +endif + +INC_DIR += $(DRM_SRC_DIR) +INC_DIR += $(addprefix $(DRM_SRC_DIR)/,include/drm include) +INC_DIR += $(addprefix $(DRM_SRC_DIR)/,etnaviv) diff --git a/repos/libports/lib/mk/libdrm.inc b/repos/libports/lib/mk/libdrm.inc new file mode 100644 index 0000000000..948d317460 --- /dev/null +++ b/repos/libports/lib/mk/libdrm.inc @@ -0,0 +1,33 @@ +LIB_DIR := $(REP_DIR)/src/lib/libdrm + +# include before to shadow libdrm_macros.h +INC_DIR += $(LIB_DIR)/include + +LIBDRM_PORT_DIR := $(call select_from_ports,libdrm)/src/lib/libdrm + +REP_INC_DIR += include/drm + +LIBS := libc +SHARED_LIB := yes + +SRC_C := xf86drm.c \ + xf86drmHash.c \ + xf86drmMode.c \ + xf86drmRandom.c \ + xf86drmSL.c + +SRC_C += dummies.c + +CC_OPT = -DHAVE_LIBDRM_ATOMIC_PRIMITIVES=1 -DHAVE_SYS_SYSCTL_H=1 + +# +# We rename 'ioctl' calls to 'genode_ioctl' calls, this way we are not required +# to write a libc plugin for libdrm. +# +CC_C_OPT += -Dioctl=genode_ioctl + +vpath %.c $(LIBDRM_PORT_DIR) +vpath %.c $(LIB_DIR) +vpath %.cc $(LIB_DIR) + +CC_CXX_WARN_STRICE := diff --git a/repos/libports/lib/mk/libdrm.mk b/repos/libports/lib/mk/libdrm.mk new file mode 100644 index 0000000000..90ac9c2be4 --- /dev/null +++ b/repos/libports/lib/mk/libdrm.mk @@ -0,0 +1,5 @@ +include $(REP_DIR)/lib/mk/libdrm.inc + +include $(call select_from_repositories,lib/import/import-libdrm.mk) + +SRC_CC := ioctl_dummy.cc diff --git a/repos/libports/lib/mk/spec/arm_v8/libdrm.mk b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk new file mode 100644 index 0000000000..894e4b627d --- /dev/null +++ b/repos/libports/lib/mk/spec/arm_v8/libdrm.mk @@ -0,0 +1,8 @@ +include $(REP_DIR)/lib/mk/libdrm.inc + +include $(call select_from_repositories,lib/import/import-libdrm.mk) + +# +# Enable when GPU multiplexer is available for Vivante +# +#SRC_CC := ioctl_etnaviv.cc diff --git a/repos/libports/lib/mk/spec/x86_64/libdrm-iris.mk b/repos/libports/lib/mk/spec/x86_64/libdrm-iris.mk new file mode 100644 index 0000000000..1ed8edc0f3 --- /dev/null +++ b/repos/libports/lib/mk/spec/x86_64/libdrm-iris.mk @@ -0,0 +1,5 @@ +include $(REP_DIR)/lib/mk/libdrm.inc + +include $(call select_from_repositories,lib/import/import-libdrm-iris.mk) + +SRC_CC := ioctl_iris.cc diff --git a/repos/libports/lib/symbols/libdrm b/repos/libports/lib/symbols/libdrm new file mode 100644 index 0000000000..cba3120daa --- /dev/null +++ b/repos/libports/lib/symbols/libdrm @@ -0,0 +1,321 @@ +# core symbols +drmAddBufs T +drmAddContextPrivateMapping T +drmAddContextTag T +drmAddMap T +drmAgpAcquire T +drmAgpAlloc T +drmAgpBase T +drmAgpBind T +drmAgpDeviceId T +drmAgpEnable T +drmAgpFree T +drmAgpGetMode T +drmAgpMemoryAvail T +drmAgpMemoryUsed T +drmAgpRelease T +drmAgpSize T +drmAgpUnbind T +drmAgpVendorId T +drmAgpVersionMajor T +drmAgpVersionMinor T +drmAuthMagic T +drmAvailable T +drmCheckModesettingSupported T +drmClose T +drmCloseOnce T +drmCommandNone T +drmCommandRead T +drmCommandWrite T +drmCommandWriteRead T +drmCreateContext T +drmCreateDrawable T +drmCrtcGetSequence T +drmCrtcQueueSequence T +drmCtlInstHandler T +drmCtlUninstHandler T +drmDelContextTag T +drmDestroyContext T +drmDestroyDrawable T +drmDevicesEqual T +drmDMA T +drmDropMaster T +drmError T +drmFinish T +drmFree T +drmFreeBufs T +drmFreeBusid T +drmFreeDevice T +drmFreeDevices T +drmFreeReservedContextList T +drmFreeVersion T +drmGetBufInfo T +drmGetBusid T +drmGetCap T +drmGetClient T +drmGetContextFlags T +drmGetContextPrivateMapping T +drmGetContextTag T +drmGetDevice T +drmGetDevice2 T +drmGetDeviceNameFromFd T +drmGetDeviceNameFromFd2 T +drmGetDevices T +drmGetDevices2 T +drmGetEntry T +drmGetHashTable T +drmGetInterruptFromBusID T +drmGetLibVersion T +drmGetLock T +drmGetMagic T +drmGetMap T +drmGetNodeTypeFromFd T +drmGetPrimaryDeviceNameFromFd T +drmGetRenderDeviceNameFromFd T +drmGetReservedContextList T +drmGetStats T +drmGetVersion T +drmHandleEvent T +drmHashCreate T +drmHashDelete T +drmHashDestroy T +drmHashFirst T +drmHashInsert T +drmHashLookup T +drmHashNext T +drmIoctl T +drmIsKMS T +drmIsMaster T +drmMalloc T +drmMap T +drmMapBufs T +drmMarkBufs T +drmModeAddFB T +drmModeAddFB2 T +drmModeAddFB2WithModifiers T +drmModeAtomicAddProperty T +drmModeAtomicAlloc T +drmModeAtomicCommit T +drmModeAtomicDuplicate T +drmModeAtomicFree T +drmModeAtomicGetCursor T +drmModeAtomicMerge T +drmModeAtomicSetCursor T +drmModeAttachMode T +drmModeConnectorSetProperty T +drmModeCreateLease T +drmModeCreatePropertyBlob T +drmModeCrtcGetGamma T +drmModeCrtcSetGamma T +drmModeDestroyPropertyBlob T +drmModeDetachMode T +drmModeDirtyFB T +drmModeFreeConnector T +drmModeFreeCrtc T +drmModeFreeEncoder T +drmModeFreeFB T +drmModeFreeFB2 T +drmModeFreeModeInfo T +drmModeFreeObjectProperties T +drmModeFreePlane T +drmModeFreePlaneResources T +drmModeFreeProperty T +drmModeFreePropertyBlob T +drmModeFreeResources T +drmModeGetConnector T +drmModeGetConnectorCurrent T +drmModeGetCrtc T +drmModeGetEncoder T +drmModeGetFB T +drmModeGetFB2 T +drmModeGetLease T +drmModeGetPlane T +drmModeGetPlaneResources T +drmModeGetProperty T +drmModeGetPropertyBlob T +drmModeGetResources T +drmModeListLessees T +drmModeMoveCursor T +drmModeObjectGetProperties T +drmModeObjectSetProperty T +drmModePageFlip T +drmModePageFlipTarget T +drmModeRevokeLease T +drmModeRmFB T +drmModeSetCrtc T +drmModeSetCursor T +drmModeSetCursor2 T +drmModeSetPlane T +drmMsg T +drmOpen T +drmOpenControl T +drmOpenOnce T +drmOpenOnceWithType T +drmOpenRender T +drmOpenWithType T +drmPrimeFDToHandle T +drmPrimeHandleToFD T +drmRandom T +drmRandomCreate T +drmRandomDestroy T +drmRandomDouble T +drmRmMap T +drmScatterGatherAlloc T +drmScatterGatherFree T +drmSetBusid T +drmSetClientCap T +drmSetContextFlags T +drmSetInterfaceVersion T +drmSetMaster T +drmSetServerInfo T +drmSLCreate T +drmSLDelete T +drmSLDestroy T +drmSLDump T +drmSLFirst T +drmSLInsert T +drmSLLookup T +drmSLLookupNeighbors T +drmSLNext T +drmSwitchToContext T +drmSyncobjCreate T +drmSyncobjDestroy T +drmSyncobjExportSyncFile T +drmSyncobjFDToHandle T +drmSyncobjHandleToFD T +drmSyncobjImportSyncFile T +drmSyncobjQuery T +drmSyncobjQuery2 T +drmSyncobjReset T +drmSyncobjSignal T +drmSyncobjTimelineSignal T +drmSyncobjTimelineWait T +drmSyncobjTransfer T +drmSyncobjWait T +drmUnlock T +drmUnmap T +drmUnmapBufs T +drmUpdateDrawableInfo T +drmWaitVBlank T + +# Etnaviv symbols +etna_device_new T +etna_device_new_dup T +etna_device_ref T +etna_device_del T +etna_device_fd T +etna_gpu_new T +etna_gpu_del T +etna_gpu_get_param T +etna_pipe_new T +etna_pipe_del T +etna_pipe_wait T +etna_pipe_wait_ns T +etna_bo_new T +etna_bo_from_name T +etna_bo_from_dmabuf T +etna_bo_ref T +etna_bo_del T +etna_bo_get_name T +etna_bo_handle T +etna_bo_dmabuf T +etna_bo_size T +etna_bo_map T +etna_bo_cpu_prep T +etna_bo_cpu_fini T +etna_cmd_stream_new T +etna_cmd_stream_del T +etna_cmd_stream_timestamp T +etna_cmd_stream_flush T +etna_cmd_stream_flush2 T +etna_cmd_stream_finish T +etna_cmd_stream_perf T +etna_cmd_stream_reloc T +etna_perfmon_create T +etna_perfmon_del T +etna_perfmon_get_dom_by_name T +etna_perfmon_get_sig_by_name T + +# Intel symbols +drm_intel_bo_alloc T +drm_intel_bo_alloc_for_render T +drm_intel_bo_alloc_tiled T +drm_intel_bo_alloc_userptr T +drm_intel_bo_busy T +drm_intel_bo_disable_reuse T +drm_intel_bo_emit_reloc T +drm_intel_bo_emit_reloc_fence T +drm_intel_bo_exec T +drm_intel_bo_fake_alloc_static T +drm_intel_bo_fake_disable_backing_store T +drm_intel_bo_flink T +drm_intel_bo_gem_create_from_name T +drm_intel_bo_gem_create_from_prime T +drm_intel_bo_gem_export_to_prime T +drm_intel_bo_get_subdata T +drm_intel_bo_get_tiling T +drm_intel_bo_is_reusable T +drm_intel_bo_madvise T +drm_intel_bo_map T +drm_intel_bo_mrb_exec T +drm_intel_bo_pin T +drm_intel_bo_reference T +drm_intel_bo_references T +drm_intel_bo_set_softpin_offset T +drm_intel_bo_set_tiling T +drm_intel_bo_subdata T +drm_intel_bo_unmap T +drm_intel_bo_unpin T +drm_intel_bo_unreference T +drm_intel_bo_use_48b_address_range T +drm_intel_bo_wait_rendering T +drm_intel_bufmgr_check_aperture_space T +drm_intel_bufmgr_destroy T +drm_intel_bufmgr_fake_contended_lock_take T +drm_intel_bufmgr_fake_evict_all T +drm_intel_bufmgr_fake_init T +drm_intel_bufmgr_fake_set_exec_callback T +drm_intel_bufmgr_fake_set_fence_callback T +drm_intel_bufmgr_fake_set_last_dispatch T +drm_intel_bufmgr_gem_can_disable_implicit_sync T +drm_intel_bufmgr_gem_enable_fenced_relocs T +drm_intel_bufmgr_gem_enable_reuse T +drm_intel_bufmgr_gem_get_devid T +drm_intel_bufmgr_gem_init T +drm_intel_bufmgr_gem_set_aub_annotations T +drm_intel_bufmgr_gem_set_aub_dump T +drm_intel_bufmgr_gem_set_aub_filename T +drm_intel_bufmgr_gem_set_vma_cache_size T +drm_intel_bufmgr_set_debug T +drm_intel_decode T +drm_intel_decode_context_alloc T +drm_intel_decode_context_free T +drm_intel_decode_set_batch_pointer T +drm_intel_decode_set_dump_past_end T +drm_intel_decode_set_head_tail T +drm_intel_decode_set_output_file T +drm_intel_gem_bo_aub_dump_bmp T +drm_intel_gem_bo_clear_relocs T +drm_intel_gem_bo_context_exec T +drm_intel_gem_bo_disable_implicit_sync T +drm_intel_gem_bo_enable_implicit_sync T +drm_intel_gem_bo_fence_exec T +drm_intel_gem_bo_get_reloc_count T +drm_intel_gem_bo_map__cpu T +drm_intel_gem_bo_map__gtt T +drm_intel_gem_bo_map__wc T +drm_intel_gem_bo_map_gtt T +drm_intel_gem_bo_map_unsynchronized T +drm_intel_gem_bo_start_gtt_access T +drm_intel_gem_bo_unmap_gtt T +drm_intel_gem_bo_wait T +drm_intel_gem_context_create T +drm_intel_gem_context_destroy T +drm_intel_gem_context_get_id T +drm_intel_get_aperture_sizes T +drm_intel_get_eu_total T +drm_intel_get_min_eu_in_pool T +drm_intel_get_pipe_from_crtc_id T +drm_intel_get_pooled_eu T +drm_intel_get_reset_stats T +drm_intel_get_subslice_total T diff --git a/repos/libports/ports/libdrm.hash b/repos/libports/ports/libdrm.hash index db061a87c7..9c99ec0f44 100644 --- a/repos/libports/ports/libdrm.hash +++ b/repos/libports/ports/libdrm.hash @@ -1 +1 @@ -c1cce0579aca9e31ade000bfa8ba58826b56cc43 +b9c5f6ab814f107e5eb743892281c6ef0e80d860 diff --git a/repos/libports/ports/libdrm.port b/repos/libports/ports/libdrm.port index 3f24a83e9d..fba5650045 100644 --- a/repos/libports/ports/libdrm.port +++ b/repos/libports/ports/libdrm.port @@ -1,7 +1,14 @@ LICENSE := MIT -VERSION := 2.4.21 +VERSION := 2.4.105 DOWNLOADS := libdrm.archive -URL(libdrm) := http://dri.freedesktop.org/libdrm/libdrm-$(VERSION).tar.bz2 -SHA(libdrm) := 4e1b612ba3b6b1deae4a8c14946099283e7a00e48a5ab002eaf4312f5a8ba14b +URL(libdrm) := https://dri.freedesktop.org/libdrm/libdrm-$(VERSION).tar.xz +SHA(libdrm) := 1d1d024b7cadc63e2b59cddaca94f78864940ab440843841113fbac6afaf2a46 DIR(libdrm) := src/lib/libdrm +FILE_LIST := $(REP_DIR)/src/lib/libdrm/files.list +TAR_OPT(libdrm) := --strip-components=1 --files-from $(FILE_LIST) +HASH_INPUT += $(FILE_LIST) + + +PATCHES := $(wildcard $(REP_DIR)/src/lib/libdrm/patches/*.patch) +PATCH_OPT := -p1 diff --git a/repos/libports/recipes/api/libdrm/content.mk b/repos/libports/recipes/api/libdrm/content.mk new file mode 100644 index 0000000000..9938d01386 --- /dev/null +++ b/repos/libports/recipes/api/libdrm/content.mk @@ -0,0 +1,27 @@ +MIRROR_FROM_REP_DIR := lib/import/import-libdrm.mk \ + lib/symbols/libdrm + +content: $(MIRROR_FROM_REP_DIR) + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +PORT_DIR := $(call port_dir,$(REP_DIR)/ports/libdrm) + +content: include + +include: + mkdir -p $@ + cp -r $(PORT_DIR)/src/lib/libdrm/*.h $@ + mkdir -p $@/drm + cp -r $(PORT_DIR)/src/lib/libdrm/include/drm/*.h $@/drm + mkdir -p $@/intel + cp -r $(PORT_DIR)/src/lib/libdrm/intel/*.h $@/intel + mkdir -p $@/etnaviv + cp -r $(PORT_DIR)/src/lib/libdrm/etnaviv/*.h $@/etnaviv + +content: LICENSE + +LICENSE: + echo "MIT, see header files" > $@ + diff --git a/repos/libports/recipes/api/libdrm/hash b/repos/libports/recipes/api/libdrm/hash new file mode 100644 index 0000000000..5b800c8b4a --- /dev/null +++ b/repos/libports/recipes/api/libdrm/hash @@ -0,0 +1 @@ +2021-08-23-i 96aa4ff0161eea571aa94734fa699e1715607b94 diff --git a/repos/libports/recipes/src/libdrm/api b/repos/libports/recipes/src/libdrm/api new file mode 100644 index 0000000000..56766d3f1e --- /dev/null +++ b/repos/libports/recipes/src/libdrm/api @@ -0,0 +1 @@ +libdrm diff --git a/repos/libports/recipes/src/libdrm/content.mk b/repos/libports/recipes/src/libdrm/content.mk new file mode 100644 index 0000000000..9810c29aef --- /dev/null +++ b/repos/libports/recipes/src/libdrm/content.mk @@ -0,0 +1,39 @@ +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 \ + 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 \ + +content: $(MIRROR_FROM_REP_DIR) src/lib/libdrm/target.mk + +$(MIRROR_FROM_REP_DIR): + $(mirror_from_rep_dir) + +src/lib/libdrm/target.mk: + mkdir -p $(dir $@) + echo "LIBS = libdrm" > $@ + +PORT_DIR := $(call port_dir,$(REP_DIR)/ports/libdrm) + +MIRROR_FROM_PORT_DIR := $(addprefix src/lib/libdrm/,\ + xf86drm.c \ + xf86drmHash.c \ + xf86drmMode.c \ + xf86drmRandom.c \ + xf86drmSL.c) + +content: $(MIRROR_FROM_PORT_DIR) + +$(MIRROR_FROM_PORT_DIR): + mkdir -p $(dir $@) + cp -r $(PORT_DIR)/$@ $(dir $@) + +content: LICENSE + +LICENSE: + echo "MIT, see header files" > $@ + diff --git a/repos/libports/recipes/src/libdrm/hash b/repos/libports/recipes/src/libdrm/hash new file mode 100644 index 0000000000..2478c71c4e --- /dev/null +++ b/repos/libports/recipes/src/libdrm/hash @@ -0,0 +1 @@ +2021-08-22-b 42aee82ddfd7aefca1086c92a4a50f6d49b7d797 diff --git a/repos/libports/recipes/src/libdrm/used_apis b/repos/libports/recipes/src/libdrm/used_apis new file mode 100644 index 0000000000..139debad25 --- /dev/null +++ b/repos/libports/recipes/src/libdrm/used_apis @@ -0,0 +1,3 @@ +base +gpu_session +libc diff --git a/repos/libports/src/lib/libdrm/dummies.c b/repos/libports/src/lib/libdrm/dummies.c new file mode 100644 index 0000000000..ae1b16ed34 --- /dev/null +++ b/repos/libports/src/lib/libdrm/dummies.c @@ -0,0 +1,6 @@ +#include + +char *devname_r(dev_t dev, mode_t type, char *buf, int len) +{ + return (void*)0; +} diff --git a/repos/libports/src/lib/libdrm/files.list b/repos/libports/src/lib/libdrm/files.list new file mode 100644 index 0000000000..d5b06650d8 --- /dev/null +++ b/repos/libports/src/lib/libdrm/files.list @@ -0,0 +1,42 @@ +libdrm-2.4.105/etnaviv/etnaviv_bo.c +libdrm-2.4.105/etnaviv/etnaviv_bo_cache.c +libdrm-2.4.105/etnaviv/etnaviv_cmd_stream.c +libdrm-2.4.105/etnaviv/etnaviv_device.c +libdrm-2.4.105/etnaviv/etnaviv_drm.h +libdrm-2.4.105/etnaviv/etnaviv_drmif.h +libdrm-2.4.105/etnaviv/etnaviv_gpu.c +libdrm-2.4.105/etnaviv/etnaviv_perfmon.c +libdrm-2.4.105/etnaviv/etnaviv_pipe.c +libdrm-2.4.105/etnaviv/etnaviv_priv.h +libdrm-2.4.105/include/drm/drm.h +libdrm-2.4.105/include/drm/drm_mode.h +libdrm-2.4.105/include/drm/i915_drm.h +libdrm-2.4.105/intel/i915_pciids.h +libdrm-2.4.105/intel/intel_aub.h +libdrm-2.4.105/intel/intel_bufmgr.c +libdrm-2.4.105/intel/intel_bufmgr.h +libdrm-2.4.105/intel/intel_bufmgr_fake.c +libdrm-2.4.105/intel/intel_bufmgr_gem.c +libdrm-2.4.105/intel/intel_bufmgr_priv.h +libdrm-2.4.105/intel/intel_chipset.c +libdrm-2.4.105/intel/intel_chipset.h +libdrm-2.4.105/intel/intel_debug.h +libdrm-2.4.105/intel/intel_decode.c +libdrm-2.4.105/intel/mm.c +libdrm-2.4.105/intel/mm.h +libdrm-2.4.105/intel/test_decode.c +libdrm-2.4.105/intel/uthash.h +libdrm-2.4.105/libdrm_lists.h +libdrm-2.4.105/libsync.h +libdrm-2.4.105/util_double_list.h +libdrm-2.4.105/util_math.h +libdrm-2.4.105/xf86atomic.h +libdrm-2.4.105/xf86drm.c +libdrm-2.4.105/xf86drm.h +libdrm-2.4.105/xf86drmHash.c +libdrm-2.4.105/xf86drmHash.h +libdrm-2.4.105/xf86drmMode.c +libdrm-2.4.105/xf86drmMode.h +libdrm-2.4.105/xf86drmRandom.c +libdrm-2.4.105/xf86drmRandom.h +libdrm-2.4.105/xf86drmSL.c diff --git a/repos/libports/src/lib/libdrm/include/genode_types.h b/repos/libports/src/lib/libdrm/include/genode_types.h new file mode 100644 index 0000000000..ad2c4ba205 --- /dev/null +++ b/repos/libports/src/lib/libdrm/include/genode_types.h @@ -0,0 +1,9 @@ +#ifndef _INCLUDE__GENODE_TYPES_H_ +#define _INCLUDE__GENODE_TYPES_H_ + +#include + +typedef genode_uint32_t uint32_t; +typedef __SIZE_TYPE__ size_t; + +#endif /* _INCLUDE__GENODE_TYPES_H_ */ diff --git a/repos/libports/src/lib/libdrm/include/libdrm_macros.h b/repos/libports/src/lib/libdrm/include/libdrm_macros.h new file mode 100644 index 0000000000..fb310a1dda --- /dev/null +++ b/repos/libports/src/lib/libdrm/include/libdrm_macros.h @@ -0,0 +1,18 @@ +#ifndef _INCLUDE__LIBDRM_MACROS_H_ +#define _INCLUDE__LIBDRM_MACROS_H_ + +#if HAVE_VISIBILITY +# define drm_private __attribute__((visibility("hidden"))) +# define drm_public __attribute__((visibility("default"))) +#else +# define drm_private +# define drm_public +#endif + +#include + +void *drm_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +int drm_munmap(void *addr, size_t length); + + +#endif /* _INCLUDE__LIBDRM_MACROS_H_ */ diff --git a/repos/libports/src/lib/libdrm/include/linux/stddef.h b/repos/libports/src/lib/libdrm/include/linux/stddef.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/repos/libports/src/lib/libdrm/include/linux/types.h b/repos/libports/src/lib/libdrm/include/linux/types.h new file mode 100644 index 0000000000..e69de29bb2 diff --git a/repos/libports/src/lib/libdrm/ioctl_dummy.cc b/repos/libports/src/lib/libdrm/ioctl_dummy.cc new file mode 100644 index 0000000000..907db49d46 --- /dev/null +++ b/repos/libports/src/lib/libdrm/ioctl_dummy.cc @@ -0,0 +1,56 @@ +/* + * \brief DRM ioctl backend dummy + * \author Josef Soentgen + * \date 2021-07-05 + */ + +/* + * Copyright (C) 2021 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 + +extern "C" { +#include +#include +} + + +extern "C" int genode_ioctl(int fd, unsigned long request, void *arg) +{ + (void)fd; + (void)request; + (void)arg; + + Genode::warning(__func__, ": not implemented yet"); + return -1; +} + + +void *drm_mmap(void *addr, size_t length, int prot, int flags, + int fd, off_t offset) +{ + (void)addr; + (void)length; + (void)prot; + (void)flags; + (void)fd; + (void)offset; + + Genode::warning(__func__, ": not implemented yet"); + return (void*)0; +} + + +int drm_munmap(void *addr, size_t length) +{ + (void)addr; + (void)length; + + Genode::warning(__func__, ": not implemented yet"); + return -1; +} diff --git a/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc b/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc new file mode 100644 index 0000000000..b437a83e9b --- /dev/null +++ b/repos/libports/src/lib/libdrm/ioctl_etnaviv.cc @@ -0,0 +1,488 @@ +/* + * \brief DRM ioctl backend + * \author Sebastian Sumpf + * \author Josef Soentgen + * \date 2017-05-10 + */ + +/* + * Copyright (C) 2017-2021 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 +#include +#include +#include +#include + +extern "C" { +#include + +#include +#include +#include +} + + +enum { verbose_ioctl = false }; + + +/** + * Get DRM command number + */ +static unsigned long constexpr command_number(unsigned long request) +{ + return request & 0xffu; +} + + +/** + * Get device specific command number + */ +static unsigned long device_number(unsigned long request) +{ + return command_number(request) - DRM_COMMAND_BASE; +} + + +/** + * Check if request is device command + */ +static bool device_ioctl(unsigned long request) +{ + long const cmd = command_number(request); + return cmd >= DRM_COMMAND_BASE && cmd < DRM_COMMAND_END; +} + + +/** + * Return name of DRM command + */ +const char *command_name(unsigned long request) +{ + if (IOCGROUP(request) != DRM_IOCTL_BASE) + return ""; + + + if (!device_ioctl(request)) { + switch (command_number(request)) { + case command_number(DRM_IOCTL_VERSION): return "DRM_IOCTL_VERSION"; + case command_number(DRM_IOCTL_GEM_CLOSE): return "DRM_IOCTL_GEM_CLOSE"; + case command_number(DRM_IOCTL_GEM_FLINK): return "DRM_IOCTL_GEM_FLINK"; + case command_number(DRM_IOCTL_GEM_OPEN): return "DRM_IOCTL_GEM_OPEN"; + case command_number(DRM_IOCTL_GET_CAP): return "DRM_IOCTL_GET_CAP"; + case command_number(DRM_IOCTL_PRIME_HANDLE_TO_FD): return "DRM_IOCTL_PRIME_HANDLE_TO_FD"; + case command_number(DRM_IOCTL_PRIME_FD_TO_HANDLE): return "DRM_IOCTL_PRIME_FD_TO_HANDLE"; + default: return ""; + } + } + + switch (device_number(request)) { + case DRM_ETNAVIV_GET_PARAM: return "DRM_ETNAVIV_GET_PARAM"; + case DRM_ETNAVIV_GEM_NEW: return "DRM_ETNAVIV_GEM_NEW"; + case DRM_ETNAVIV_GEM_INFO: return "DRM_ETNAVIV_GEM_INFO"; + case DRM_ETNAVIV_GEM_CPU_PREP: return "DRM_ETNAVIV_GEM_CPU_PREP"; + case DRM_ETNAVIV_GEM_CPU_FINI: return "DRM_ETNAVIV_GEM_CPU_FINI"; + case DRM_ETNAVIV_GEM_SUBMIT: return "DRM_ETNAVIV_GEM_SUBMIT"; + case DRM_ETNAVIV_WAIT_FENCE: return "DRM_ETNAVIV_WAIT_FENCE"; + case DRM_ETNAVIV_GEM_USERPTR: return "DRM_ETNAVIV_GEM_USERPTR"; + case DRM_ETNAVIV_GEM_WAIT: return "DRM_ETNAVIV_GEM_WAIT"; + case DRM_ETNAVIV_PM_QUERY_DOM: return "DRM_ETNAVIV_PM_QUERY_DOM"; + case DRM_ETNAVIV_PM_QUERY_SIG: return "DRM_ETNAVIV_PM_QUERY_SIG"; + case DRM_ETNAVIV_NUM_IOCTLS: return "DRM_ETNAVIV_NUM_IOCTLS"; + default: + return ""; + } +} + + +/** + * Check if request is OUT + */ +static bool constexpr req_out(unsigned long request) +{ + return (request & IOC_OUT); +} + + +/** + * Check if request is IN + */ +static bool constexpr req_in(unsigned long request) +{ + return (request & IOC_IN); +} + + +/** + * Convert FreeBSD (libc) I/O control to Linux (DRM driver) + */ +static unsigned long to_linux(unsigned long request) +{ + /* + * FreeBSD and Linux have swapped IN/OUT values. + */ + unsigned long lx = request & 0x0fffffffu; + if (req_out(request)) { lx |= IOC_IN; } + if (req_in (request)) { lx |= IOC_OUT; } + + return lx; +} + + +namespace Drm { + + size_t get_payload_size(drm_etnaviv_gem_submit const &submit); + + // XXX better implement as 'size_t for_each_object(T const *t, unsigned len, FN const &fn, char *dst)' + template void for_each_object(T const *t, unsigned len, FN const &fn) + { + for (unsigned i = 0; i < len; i++) { + T const *obj = &t[i]; + fn(obj); + } + } + + void serialize(drm_etnaviv_gem_submit *submit, char *content); + + size_t get_payload_size(drm_version const &version); + void serialize(drm_version *version, char *content); + void deserialize(drm_version *version, char *content); + +} /* anonymous namespace */ + + +size_t Drm::get_payload_size(drm_etnaviv_gem_submit const &submit) +{ + size_t size = 0; + + size += sizeof (drm_etnaviv_gem_submit_reloc) * submit.nr_relocs; + size += sizeof (drm_etnaviv_gem_submit_bo) * submit.nr_bos; + size += sizeof (drm_etnaviv_gem_submit_pmr) * submit.nr_pmrs; + + return size; +} + + +void Drm::serialize(drm_etnaviv_gem_submit *submit, char *content) +{ + size_t offset = 0; + + /* leave place for object itself first */ + offset += sizeof (*submit); + + /* next are the buffer-objects */ + if (submit->nr_bos) { + size_t const new_start = offset; + + auto copy_bos = [&] (drm_etnaviv_gem_submit_bo const *bo) { + char * const dst = content + offset; + Genode::memcpy(dst, bo, sizeof (*bo)); + offset += sizeof (*bo); + }; + for_each_object((drm_etnaviv_gem_submit_bo*)submit->bos, + submit->nr_bos, copy_bos); + submit->bos = reinterpret_cast<__u64>(new_start); + } + + /* next are the relocs */ + if (submit->nr_relocs) { + size_t const new_start = offset; + + auto copy_relocs = [&] (drm_etnaviv_gem_submit_reloc const *reloc) { + char * const dst = content + offset; + Genode::memcpy(dst, reloc, sizeof (*reloc)); + offset += sizeof (*reloc); + }; + for_each_object((drm_etnaviv_gem_submit_reloc*)submit->relocs, + submit->nr_relocs, copy_relocs); + submit->relocs = reinterpret_cast<__u64>(new_start); + } + + /* next are the pmrs */ + if (submit->nr_pmrs) { + size_t const new_start = offset; + auto copy_pmrs = [&] (drm_etnaviv_gem_submit_pmr const *pmr) { + char * const dst = content + offset; + Genode::memcpy(dst, pmr, sizeof (*pmr)); + offset += sizeof (*pmr); + }; + for_each_object((drm_etnaviv_gem_submit_pmr*)submit->pmrs, + submit->nr_pmrs, copy_pmrs); + submit->pmrs = reinterpret_cast<__u64>(new_start); + } + + /* next is the cmd stream */ + { + size_t const new_start = offset; + + char * const dst = content + offset; + Genode::memcpy(dst, reinterpret_cast(submit->stream), submit->stream_size); + offset += submit->stream_size; + submit->stream = reinterpret_cast<__u64>(new_start); + } + + /* copy submit object last but into the front */ + Genode::memcpy(content, submit, sizeof (*submit)); +} + + +size_t Drm::get_payload_size(drm_version const &version) +{ + size_t size = 0; + size += version.name_len; + size += version.date_len; + size += version.desc_len; + return size; +} + + +void Drm::serialize(drm_version *version, char *content) +{ + size_t offset = 0; + char *start = 0; + offset += sizeof (*version); + + start = (char*)offset; + version->name = start; + offset += version->name_len; + + start = (char*)offset; + version->date = start; + offset += version->date_len; + + start = (char*)offset; + version->desc = start; + offset += version->desc_len; + + Genode::memcpy(content, version, sizeof (*version)); +} + + +void Drm::deserialize(drm_version *version, char *content) +{ + drm_version *cversion = reinterpret_cast(content); + + version->version_major = cversion->version_major; + version->version_minor = cversion->version_minor; + version->version_patchlevel = cversion->version_patchlevel; + + version->name += (unsigned long)version; + version->date += (unsigned long)version; + version->desc += (unsigned long)version; + + cversion->name += (unsigned long)cversion; + cversion->date += (unsigned long)cversion; + cversion->desc += (unsigned long)cversion; + + Genode::copy_cstring(version->name, cversion->name, cversion->name_len); + Genode::copy_cstring(version->date, cversion->date, cversion->date_len); + Genode::copy_cstring(version->desc, cversion->desc, cversion->desc_len); +} + + +class Drm_call +{ + private: + + Genode::Env &_env; + Genode::Heap _heap { _env.ram(), _env.rm() }; + Genode::Allocator_avl _drm_alloc { &_heap }; + Drm::Connection _drm_session { _env, &_drm_alloc, 1024*1024 }; + + public: + + Drm_call(Genode::Env &env) : _env(env) { } + + int ioctl(unsigned long request, void *arg) + { + size_t size = IOCPARM_LEN(request); + + bool const in = req_in(request); + bool const out = req_out(request); + + unsigned long const lx_request = to_linux(request); + + /* + * Adjust packet size for flatten arrays. + */ + if (command_number(request) == DRM_ETNAVIV_GEM_SUBMIT) { + /* account for the arrays */ + drm_etnaviv_gem_submit *submit = + reinterpret_cast(arg); + size_t const payload_size = Drm::get_payload_size(*submit); + size += payload_size; + } else + + /* + * Adjust packet size for user pointer storage. + */ + if (command_number(request) == command_number(DRM_IOCTL_VERSION)) { + drm_version *version = + reinterpret_cast(arg); + size_t const payload_size = Drm::get_payload_size(*version); + size += payload_size; + } + + Drm::Session::Tx::Source &src = *_drm_session.tx(); + Drm::Packet_descriptor p { src.alloc_packet(size), lx_request }; + + /* + * Copy each array flat to the packet buffer and adjust the + * addresses in the submit object. + */ + if (device_number(request) == DRM_ETNAVIV_GEM_SUBMIT) { + drm_etnaviv_gem_submit *submit = + reinterpret_cast(arg); + char *content = src.packet_content(p); + Drm::serialize(submit, content); + } else + + /* + * Copy and adjust user pointer in DRM version object. + */ + if (command_number(request) == command_number(DRM_IOCTL_VERSION)) { + drm_version *version = + reinterpret_cast(arg); + char *content = src.packet_content(p); + Drm::serialize(version, content); + } else + + /* + * The remaining ioctls get the memcpy treament. Hopefully there + * are no user pointers left... + */ + if (in) { + Genode::memcpy(src.packet_content(p), arg, size); + } + + /* + * For the moment we perform a "blocking" packetstream operation + * which could be time-consuming but is easier to debug. Eventually + * it should be replace by a asynchronous operation. + */ + src.submit_packet(p); + p = src.get_acked_packet(); + + if (out && arg) { + /* + * Adjust user pointers back to make the client happy. + */ + if (command_number(request) == command_number(DRM_IOCTL_VERSION)) { + drm_version *version = + reinterpret_cast(arg); + char *content = src.packet_content(p); + Drm::deserialize(version, content); + + } else { + // XXX handle unserializaton in a better way + Genode::memcpy(arg, src.packet_content(p), size); + } + } + + src.release_packet(p); + return p.error(); + } + + void *mmap(unsigned long offset, unsigned long size) + { + Genode::Ram_dataspace_capability cap = _drm_session.object_dataspace(offset, size); + if (!cap.valid()) { + return (void *)-1; + } + + try { + return _env.rm().attach(cap); + } catch (...) { } + + return (void *)-1; + } + + void munmap(void *addr) + { + _env.rm().detach(addr); + } +}; + + +static Genode::Constructible _drm; + + +void drm_init(Genode::Env &env) +{ + _drm.construct(env); +} + + +void drm_complete() +{ + Genode::error(__func__, ": called, not implemented yet"); +} + + +/** + * Dump I/O control request to LOG + */ +static void dump_ioctl(unsigned long request) +{ + using namespace Genode; + + log("ioctl(request=", Hex(request), + (request & 0xe0000000u) == IOC_OUT ? " out" : + (request & 0xe0000000u) == IOC_IN ? " in" : + (request & 0xe0000000u) == IOC_INOUT ? " inout" : " void", + " len=", IOCPARM_LEN(request), + " cmd=", command_name(request), " (", Hex(command_number(request)), ")"); +} + + +/** + * Perfom I/O control request + */ +extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg) +{ + if (verbose_ioctl) + dump_ioctl(request); + + try { + int ret = _drm->ioctl(request, arg); + + if (verbose_ioctl) + Genode::log("returned ", ret); + + return ret; + } catch (...) { } + + return -1; +} + + +/** + * Map DRM buffer-object + */ +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; + + return _drm->mmap(offset, length); +} + + +/** + * Unmap DRM buffer-object + */ +int drm_munmap(void *addr, size_t length) +{ + (void)length; + + _drm->munmap(addr); + return 0; +} diff --git a/repos/libports/src/lib/libdrm/ioctl_iris.cc b/repos/libports/src/lib/libdrm/ioctl_iris.cc new file mode 100644 index 0000000000..75e14cba5c --- /dev/null +++ b/repos/libports/src/lib/libdrm/ioctl_iris.cc @@ -0,0 +1,1190 @@ +/* + * \brief DRM ioctl backend + * \author Sebastian Sumpf + * \author Josef Soentgen + * \author Alexander Boettcher + * \date 2017-05-10 + */ + +/* + * Copyright (C) 2017-2021 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 +#include +#include +#include +#include + +#include +#include + +extern "C" { +#include +#include +#include + +#define DRM_NUMBER(req) ((req) & 0xff) +} + +using Genode::addr_t; +using Genode::Attached_dataspace; +using Genode::Constructible; + +enum { verbose_ioctl = false }; + +namespace Utils +{ + uint64_t limit_to_48bit(uint64_t addr) { + return addr & ((1ULL << 48) - 1); } +} + + +/** + * Get DRM command number + */ +static unsigned long command_number(unsigned long request) +{ + return request & 0xffu; +} + + +/** + * Get device specific command number + */ +static unsigned long device_number(unsigned long request) +{ + return command_number(request) - DRM_COMMAND_BASE; +} + + +/** + * Check if request is device command + */ +static bool device_ioctl(unsigned long request) +{ + unsigned long const cmd = command_number(request); + return cmd >= DRM_COMMAND_BASE && cmd < DRM_COMMAND_END; +} + + +static const char *command_name(unsigned long request) +{ + if (IOCGROUP(request) != DRM_IOCTL_BASE) + return ""; + + + if (!device_ioctl(request)) { + long const cmd = command_number(request); + switch (cmd) { + case DRM_NUMBER(DRM_IOCTL_GEM_CLOSE): return "DRM_IOCTL_GEM_CLOSE"; + case DRM_NUMBER(DRM_IOCTL_GEM_FLINK): return "DRM_IOCTL_GEM_FLINK"; + case DRM_NUMBER(DRM_IOCTL_SYNCOBJ_CREATE): return "DRM_IOCTL_SYNCOBJ_CREATE"; + case DRM_NUMBER(DRM_IOCTL_PRIME_HANDLE_TO_FD): return "DRM_IOCTL_PRIME_HANDLE_TO_FD"; + default: return ""; + } + } + + switch (device_number(request)) { + case DRM_I915_INIT: return "DRM_I915_INIT"; + case DRM_I915_FLUSH: return "DRM_I915_FLUSH"; + case DRM_I915_FLIP: return "DRM_I915_FLIP"; + case DRM_I915_BATCHBUFFER: return "DRM_I915_BATCHBUFFER"; + case DRM_I915_IRQ_EMIT: return "DRM_I915_IRQ_EMIT"; + case DRM_I915_IRQ_WAIT: return "DRM_I915_IRQ_WAIT"; + case DRM_I915_GETPARAM: return "DRM_I915_GETPARAM"; + case DRM_I915_SETPARAM: return "DRM_I915_SETPARAM"; + case DRM_I915_ALLOC: return "DRM_I915_ALLOC"; + case DRM_I915_FREE: return "DRM_I915_FREE"; + case DRM_I915_INIT_HEAP: return "DRM_I915_INIT_HEAP"; + case DRM_I915_CMDBUFFER: return "DRM_I915_CMDBUFFER"; + case DRM_I915_DESTROY_HEAP: return "DRM_I915_DESTROY_HEAP"; + case DRM_I915_SET_VBLANK_PIPE: return "DRM_I915_SET_VBLANK_PIPE"; + case DRM_I915_GET_VBLANK_PIPE: return "DRM_I915_GET_VBLANK_PIPE"; + case DRM_I915_VBLANK_SWAP: return "DRM_I915_VBLANK_SWAP"; + case DRM_I915_HWS_ADDR: return "DRM_I915_HWS_ADDR"; + case DRM_I915_GEM_INIT: return "DRM_I915_GEM_INIT"; + case DRM_I915_GEM_EXECBUFFER: return "DRM_I915_GEM_EXECBUFFER"; + case DRM_I915_GEM_PIN: return "DRM_I915_GEM_PIN"; + case DRM_I915_GEM_UNPIN: return "DRM_I915_GEM_UNPIN"; + case DRM_I915_GEM_BUSY: return "DRM_I915_GEM_BUSY"; + case DRM_I915_GEM_THROTTLE: return "DRM_I915_GEM_THROTTLE"; + case DRM_I915_GEM_ENTERVT: return "DRM_I915_GEM_ENTERVT"; + case DRM_I915_GEM_LEAVEVT: return "DRM_I915_GEM_LEAVEVT"; + case DRM_I915_GEM_CREATE: return "DRM_I915_GEM_CREATE"; + case DRM_I915_GEM_PREAD: return "DRM_I915_GEM_PREAD"; + case DRM_I915_GEM_PWRITE: return "DRM_I915_GEM_PWRITE"; + case DRM_I915_GEM_MMAP: return "DRM_I915_GEM_MMAP"; + case DRM_I915_GEM_SET_DOMAIN: return "DRM_I915_GEM_SET_DOMAIN"; + case DRM_I915_GEM_SW_FINISH: return "DRM_I915_GEM_SW_FINISH"; + case DRM_I915_GEM_SET_TILING: return "DRM_I915_GEM_SET_TILING"; + case DRM_I915_GEM_GET_TILING: return "DRM_I915_GEM_GET_TILING"; + case DRM_I915_GEM_GET_APERTURE: return "DRM_I915_GEM_GET_APERTURE"; + case DRM_I915_GEM_MMAP_GTT: return "DRM_I915_GEM_MMAP_GTT"; + case DRM_I915_GET_PIPE_FROM_CRTC_ID: return "DRM_I915_GET_PIPE_FROM_CRTC_ID"; + case DRM_I915_GEM_MADVISE: return "DRM_I915_GEM_MADVISE"; + case DRM_I915_OVERLAY_PUT_IMAGE: return "DRM_I915_OVERLAY_PUT_IMAGE"; + case DRM_I915_OVERLAY_ATTRS: return "DRM_I915_OVERLAY_ATTRS"; + case DRM_I915_GEM_EXECBUFFER2: return "DRM_I915_GEM_EXECBUFFER2"; + case DRM_I915_REG_READ: return "DRM_I915_REG_READ"; + case DRM_I915_GET_RESET_STATS: return "DRM_I915_GET_RESET_STATS"; + case DRM_I915_GEM_CONTEXT_CREATE: return "DRM_I915_GEM_CONTEXT_CREATE"; + default: + return ""; + } +} + +static void dump_ioctl(unsigned long request) +{ + using namespace Genode; + + log("ioctl(request=", Hex(request), + (request & 0xe0000000) == IOC_OUT ? " out" : + (request & 0xe0000000) == IOC_IN ? " in" : + (request & 0xe0000000) == IOC_INOUT ? " inout" : " void", + " len=", IOCPARM_LEN(request), + " cmd=",command_name(request), " (", Hex(command_number(request)), ")"); +} + + +class Drm_call +{ + private: + + Genode::Env &_env; + Genode::Heap _heap { _env.ram(), _env.rm() }; + Gpu::Connection _gpu_session { _env }; + Gpu::Info _gpu_info { _gpu_session.info() }; + Genode::Blockade _completion_lock { }; + size_t _available_gtt_size { _gpu_info.aperture_size }; + + using Offset = unsigned long; + + struct Gpu_virtual_address { + uint64_t addr; + }; + + struct Buffer_handle; + typedef Genode::Id_space::Element Handle; + typedef Genode::Id_space::Id Handle_id; + + struct Buffer_handle + { + Genode::Dataspace_capability const cap; + Genode::size_t const size; + Handle const handle; + + Constructible buffer_attached { }; + + Genode::Dataspace_capability map_cap { }; + Offset map_offset { 0 }; + + Gpu_virtual_address gpu_vaddr { }; + Gpu::Info::Execution_buffer_sequence seqno { }; + + bool gpu_vaddr_valid { false }; + bool busy { false }; + + Buffer_handle(Genode::Dataspace_capability cap, + Genode::size_t size, + Genode::Id_space &space) + : + cap(cap), size(size), + handle(*this, space) + { + if (!cap.valid() || !size) + Genode::warning("invalid Buffer_handle ?"); + } + + virtual ~Buffer_handle() { } + + bool valid() const { return cap.valid() && size != 0; } + + bool mmap(Genode::Env &env) + { + if (!valid()) + return false; + + if (!buffer_attached.constructed()) + buffer_attached.construct(env.rm(), cap); + + return buffer_attached.constructed(); + } + + addr_t mmap_addr() { + return reinterpret_cast(buffer_attached->local_addr()); + } + }; + + Genode::Id_space _buffer_handles { }; + + using Buffer = Genode::Registered; + + Genode::Registry _buffer_registry { }; + + struct Sync_obj + { + using Sync = Genode::Id_space; + using Id = Sync::Id; + + Sync::Element id; + + Sync_obj(Sync &space) + : id(*this, space) + { } + }; + + Genode::Id_space _sync_objects { }; + + bool _map_buffer_ppgtt(Buffer_handle &buffer, Gpu_virtual_address const vaddr) + { + if (buffer.gpu_vaddr_valid) + Genode::warning(__func__, " already have a gpu virtual address ", + Genode::Hex(buffer.gpu_vaddr.addr), " vs ", + Genode::Hex(vaddr.addr)); + +/* XXX out of cap XXX */ + bool const ppgtt = Genode::retry( + [&]() { return _gpu_session.map_buffer_ppgtt(buffer.cap, + Utils::limit_to_48bit(vaddr.addr)); }, + [&]() { _gpu_session.upgrade_ram(4096); } + ); + + if (!ppgtt) { + Genode::error("could not insert buffer into PPGTT"); + return false; + } + + buffer.gpu_vaddr = vaddr; + buffer.gpu_vaddr_valid = true; + return true; + } + + void _unmap_buffer_ppgtt(Buffer_handle &buffer) + { + if (!buffer.gpu_vaddr_valid) return; + + _gpu_session.unmap_buffer_ppgtt(buffer.cap, Utils::limit_to_48bit(buffer.gpu_vaddr.addr)); + buffer.gpu_vaddr_valid = false; + } + + template + void _alloc_buffer(uint64_t const size, FUNC const &fn) + { + Genode::size_t donate = size; + Genode::Dataspace_capability cap = Genode::retry( + [&] () { return _gpu_session.alloc_buffer(size); }, + [&] () { + _gpu_session.upgrade_ram(donate); + donate /= 4; + }); + + try { + Buffer * buffer = new (&_heap) Buffer(_buffer_registry, cap, size, _buffer_handles); + fn(buffer->handle); + } catch (...) { + _gpu_session.free_buffer(cap); + throw; + } + } + + void _unmap_buffer(Buffer_handle &h) + { + _env.rm().detach(h.map_offset); + h.map_offset = 0; + + _gpu_session.unmap_buffer(h.map_cap); + h.map_cap = Genode::Dataspace_capability(); + + _available_gtt_size += h.size; + } + + int _free_buffer(Handle_id const &id) + { + bool const handled = _apply_buffer(id, [&] (Buffer_handle &bh) { + if (bh.map_cap.valid()) + _unmap_buffer(bh); + + if (bh.gpu_vaddr_valid) { + _gpu_session.unmap_buffer_ppgtt(bh.cap, bh.gpu_vaddr.addr); + bh.gpu_vaddr_valid = false; + } + _gpu_session.free_buffer(bh.cap); + }); + + if (!handled) { + Genode::error(__func__, ": invalid handle ", id.value); + Genode::sleep_forever(); + } + + return handled ? 0 : -1; + } + + Offset _map_buffer(Buffer_handle &bh) + { + Offset offset = 0; + + if (bh.map_cap.valid()) { + offset = bh.map_offset; + return offset; + } + + try { + _gpu_session.upgrade_ram(4096); + bh.map_cap = _gpu_session.map_buffer(bh.cap, true); + bh.map_offset = static_cast(_env.rm().attach(bh.map_cap)); + offset = bh.map_offset; + + _available_gtt_size -= bh.size; + } catch (...) { + if (bh.map_cap.valid()) { _gpu_session.unmap_buffer(bh.map_cap); } + bh.map_cap = Genode::Dataspace_capability(); + Genode::error("could not attach GEM buffer handle: ", bh.handle); + Genode::sleep_forever(); + } + + return offset; + } + + Offset _map_buffer(Handle_id const &id) + { + Offset offset = 0; + + bool handled = _apply_buffer(id, [&] (Buffer_handle &bh) { + offset = _map_buffer(bh); + }); + + if (!handled) { + Genode::error(__func__, ": invalid handle ", id.value); + Genode::sleep_forever(); + } + + return offset; + } + + /******************* + ** lookup buffer ** + *******************/ + + template + bool _apply_buffer(Handle_id const &id, FUNC const &fn) + { + bool found = false; + + _buffer_handles.apply(id, [&](Buffer_handle &bh) { + fn(bh); + found = true; + }); + + return found; + } + + /*************************** + ** execbuffer completion ** + ***************************/ + + void _handle_completion() { + _completion_lock.wakeup(); + } + + Genode::Io_signal_handler _completion_sigh { + _env.ep(), *this, &Drm_call::_handle_completion }; + + + /************ + ** ioctls ** + ************/ + + int _device_gem_get_aperture_size(void *arg) + { + drm_i915_gem_get_aperture * const p = reinterpret_cast(arg); + p->aper_size = _gpu_info.aperture_size; + p->aper_available_size = _available_gtt_size; + Genode::warning(__func__, ": available_gtt_size is not properly accounted"); + return 0; + } + + int _device_gem_create(void *arg) + { + auto const p = reinterpret_cast(arg); + + uint64_t const size = (p->size + 0xfff) & ~0xfff; + + _alloc_buffer(size, [&](Handle const &handle) { + p->size = size; + p->handle = handle.id().value; + + if (verbose_ioctl) { + Genode::error(__func__, ": ", "handle: ", handle.id().value, + " size: ", size); + } + }); + + return 0; + } + + int _device_gem_mmap(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const handle { .value = p->handle }; + + bool map_failed { true }; + + bool handled = _apply_buffer(handle, [&] (Buffer_handle &bh) { + if (bh.mmap(_env)) { + p->addr_ptr = bh.mmap_addr(); + map_failed = false; + } + }); + + if (verbose_ioctl) { + Genode::error(__func__, ": ", "handle: ", handle, + !handled ? " buffer unknown" : "", + map_failed ? " buffer inaccessible" : "", + " flags=", p->flags, + " addr=", Genode::Hex(p->addr_ptr)); + } + + if (!handled || map_failed) + return -1; + + return 0; + } + + int _device_gem_mmap_gtt(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->handle }; + + if (verbose_ioctl) { + Genode::error(__func__, ": ", "handle: ", id.value, + " offset: ", Genode::Hex(p->offset)); + } + + /* + * We always map a buffer when the tiling is set. Since Mesa + * sets the filing first and maps the buffer afterwards we might + * already have a mapping at this point. + */ + p->offset = _map_buffer(id); + + if (verbose_ioctl) { + Genode::error(__func__, ": ", "handle: ", id.value, + " offset: ", Genode::Hex(p->offset), " (mapped)"); + } + return p->offset ? 0 : -1; + } + + char const *_domain_name(uint32_t d) + { + if (d & I915_GEM_DOMAIN_CPU) { return "CPU"; } + if (d & I915_GEM_DOMAIN_GTT) { return "CPU (GTT)"; } + if (d & I915_GEM_DOMAIN_RENDER) { return "GPU (RC)"; } + if (d & I915_GEM_DOMAIN_VERTEX) { return "GPU (VC)"; } + if (d & I915_GEM_DOMAIN_INSTRUCTION) { return "GPU (IC)"; } + if (d & I915_GEM_DOMAIN_SAMPLER) { return "GPU (SC)"; } + return "N/A"; + } + + int _device_gem_set_domain(void *arg) + { + /* XXX check read_domains/write_domain */ + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->handle }; + uint32_t const rd = p->read_domains; + uint32_t const wd = p->write_domain; + + if (verbose_ioctl) { + Genode::error(__func__, ": ", "handle: ", id.value, + " rd: ", _domain_name(rd), + " wd: ", _domain_name(wd)); + } + + return 0; + } + + int _device_getparam(void *arg) + { + drm_i915_getparam_t *p = reinterpret_cast(arg); + int const param = p->param; + int *value = p->value; + + switch (param) { + case I915_PARAM_CHIPSET_ID: + *value = _gpu_info.chip_id; + break; + case I915_PARAM_HAS_CONTEXT_ISOLATION: + case I915_PARAM_HAS_RELAXED_FENCING: + case I915_PARAM_HAS_RELAXED_DELTA: + case I915_PARAM_HAS_EXECBUF2: + case I915_PARAM_HAS_LLC: + *value = 1; + break; + case I915_PARAM_HAS_BSD: + case I915_PARAM_HAS_BLT: + case I915_PARAM_HAS_VEBOX: + case I915_PARAM_HAS_WAIT_TIMEOUT: + case I915_PARAM_HAS_RESOURCE_STREAMER: + case 54 /* I915_PARAM_PERF_REVISION */: + *value = 0; + break; + case I915_PARAM_REVISION: + *value = _gpu_info.revision.value; + return 0; + case I915_PARAM_CS_TIMESTAMP_FREQUENCY: + Genode::error("I915_PARAM_CS_TIMESTAMP_FREQUENCY not supported"); + return -1; + case I915_PARAM_SLICE_MASK: + *value = _gpu_info.slice_mask.value; + return 0; + case I915_PARAM_EU_TOTAL: + *value = _gpu_info.eus.value; + return 0; + case I915_PARAM_SUBSLICE_TOTAL: + *value = _gpu_info.subslices.value; + return 0; + case I915_PARAM_SUBSLICE_MASK: + *value = _gpu_info.subslice_mask.value; + return 0; + case I915_PARAM_MMAP_GTT_VERSION: + *value = 0; /* XXX */ + Genode::warning("I915_PARAM_MMAP_GTT_VERSION ", *value); + return 0; + default: + Genode::error("Unhandled device param:", Genode::Hex(param)); + return -1; + break; + } + return 0; + } + + int _device_gem_context_create(void *arg) + { + static unsigned cnt = 0; + + drm_i915_gem_context_create * const p = reinterpret_cast(arg); + p->ctx_id = _gpu_info.ctx_id + cnt; + Genode::error("create gem context ", p->ctx_id); + cnt ++; + return 0; + } + + int _device_gem_context_set_param(void *arg) + { + auto * const p = reinterpret_cast(arg); + + switch (p->param) { + case I915_CONTEXT_PARAM_PRIORITY: + Genode::error(__func__, " context=", p->ctx_id, " priority:=", p->value); + return 0; + case I915_CONTEXT_PARAM_RECOVERABLE: + Genode::error(__func__, " context=", p->ctx_id, " recoverable:=", p->value); + return 0; + default: + Genode::error(__func__, " ctx=", p->ctx_id, " param=", p->param, " size=", p->size, " value=", Genode::Hex(p->value)); + Genode::error(__func__, " unknown param=", p->param); + return -1; + }; + } + + int _device_gem_context_get_param(void *arg) + { + auto * const p = reinterpret_cast(arg); + + switch (p->param) { + case I915_CONTEXT_PARAM_SSEU: + Genode::error("get ", p->ctx_id, " ", p->param, " ", p->size, " ", Genode::Hex(p->value)); + Genode::error(__func__, " sseu "); + return 0; + default: + Genode::error(__func__, " ctx=", p->ctx_id, " param=", p->param, " size=", p->size, " value=", Genode::Hex(p->value)); + return -1; + } + } + + int _device_gem_set_tiling(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->handle }; + uint32_t const mode = p->tiling_mode; + uint32_t const stride = p->stride; + uint32_t const swizzle = p->swizzle_mode; + + if (verbose_ioctl) { + Genode::error(__func__, ": ", + "handle: ", id.value, " " + "mode: ", mode, " " + "stride: ", stride , " " + "swizzle: ", swizzle); + } + + bool ok = false; + bool handled = _apply_buffer(id, [&] (Buffer_handle &bh) { + if (!bh.cap.valid()) + return; + + /* we need a valid GGTT mapping for fencing */ + if (!bh.map_cap.valid() && !_map_buffer(bh)) + return; + + uint32_t const m = (stride << 16) | (mode == 1 ? 1 : 0); + ok = _gpu_session.set_tiling(bh.map_cap, m); + }); + + if (!handled) + Genode::error(__func__, ": invalid handle: ", id.value); + + return ok ? 0 : -1; + } + + int _device_gem_sw_finish(void *) + { + Genode::error(__func__, " called - unsupported"); + // drm_i915_gem_sw_finish * const p = reinterpret_cast(arg); + // Handle const handle = p->handle; + return 0; + } + + int _device_gem_execbuffer2(void *arg) + { + auto const * const p = reinterpret_cast(arg); + + /* batch-buffer index and cap */ + unsigned const bb_id = (p->flags & I915_EXEC_BATCH_FIRST) ? 0 : p->buffer_count - 1; + + Buffer_handle *command_buffer = nullptr; + + if (verbose_ioctl) { + uint64_t const ctx_id = p->rsvd1; + Genode::log(__func__, + " buffers_ptr: ", Genode::Hex(p->buffers_ptr), + " buffer_count: ", p->buffer_count, + " batch_start_offset: ", Genode::Hex(p->batch_start_offset), + " batch_len: ", p->batch_len, + " dr1: ", Genode::Hex(p->DR1), + " dr4: ", Genode::Hex(p->DR4), + " num_cliprects: ", p->num_cliprects, + " cliprects_ptr: ", Genode::Hex(p->cliprects_ptr), + " flags: ", Genode::Hex(p->flags), + " ctx_id: ", Genode::Hex(ctx_id)); + } + + if (!(p->flags & I915_EXEC_NO_RELOC)) { + Genode::error("no relocation supported"); + return -1; + } + + if (p->flags & I915_EXEC_FENCE_ARRAY) { + bool unsupported = false; + + for (unsigned i = 0; i < p->num_cliprects; i++) { + auto &fence = reinterpret_cast(p->cliprects_ptr)[i]; + + Sync_obj::Id const id { .value = fence.handle }; + _sync_objects.apply(id, [&](Sync_obj &) { + /** + * skipping signal fences should be save as long as + * no one tries to wait for ... + * - fence.flags & I915_EXEC_FENCE_SIGNAL + */ + if (fence.flags & I915_EXEC_FENCE_WAIT) + unsupported = true; + }); + } + + if (unsupported) { + Genode::error("fence wait not supported"); + return -1; + } + } + + auto const obj = + reinterpret_cast(p->buffers_ptr); + + for (uint64_t i = 0; i < p->buffer_count; i++) { + if (verbose_ioctl) { + Genode::log(" obj[", i, "] ", + "handle: ", obj[i].handle, " " + "relocation_count: ", obj[i].relocation_count, " " + "relocs_ptr: ", Genode::Hex(obj[i].relocs_ptr), " " + "alignment: ", Genode::Hex(obj[i].alignment), " " + "offset: ", Genode::Hex(obj[i].offset), " " + "flags: ", Genode::Hex(obj[i].flags)); + } + + if (obj[i].relocation_count > 0) { + Genode::error("no relocation supported"); + return -1; + } + + int ret = -1; + Handle_id const id { .value = obj[i].handle }; + + bool handled = _apply_buffer(id, [&](Buffer_handle &bh) { + if (!bh.valid()) + return; + + if (bh.busy) + Genode::warning("handle: ", obj[i].handle, " reused but is busy"); + + if (bh.gpu_vaddr_valid && bh.gpu_vaddr.addr != obj[i].offset) { + Genode::error("unmap already mapped ", bh.handle, " ", Genode::Hex(bh.gpu_vaddr.addr), "->", Genode::Hex(obj[i].offset)); + _unmap_buffer_ppgtt(bh); + } + + if (!bh.gpu_vaddr_valid) + _map_buffer_ppgtt(bh, Gpu_virtual_address { .addr = obj[i].offset }); + + if (!bh.gpu_vaddr_valid) { + Genode::error("handle: ", obj[i].handle, " gpu_vaddr invalid"); + return; + } + + bh.busy = true; + + if (i == bb_id) + command_buffer = &bh; + + ret = 0; + }); + + if (!handled || ret) { + Genode::error("handle: ", obj[i].handle, " invalid, ret=", ret); + return ret; + } + } + + if (!command_buffer) + return -1; + + command_buffer->seqno = _gpu_session.exec_buffer(command_buffer->cap, + p->batch_len); + + for (uint64_t i = 0; i < p->buffer_count; i++) { + Handle_id const id { .value = obj[i].handle }; + _apply_buffer(id, [&](Buffer_handle &bh) { + bh.seqno = command_buffer->seqno; + }); + } + + return 0; + } + + int _device_gem_busy(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->handle }; + + bool handled = _apply_buffer(id, [&](Buffer_handle const &bh) { + p->busy = bh.busy; + }); + + return handled ? 0 : -1; + } + + int _device_gem_madvise(void *arg) + { + drm_i915_gem_madvise * const p = reinterpret_cast(arg); + // Handle const handle = p->handle; + // uint32_t const madv = p->madv; + /* all buffer are always available */ + p->retained = 1; + return 0; + } + + int _device_gem_wait(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->bo_handle }; + + bool busy = true; + + while (busy) { + bool handled = _apply_buffer(id, [&](Buffer_handle &bh) { + busy = bh.busy; + }); + + if (!handled) { + Genode::error(__func__, ": handle ", p->bo_handle, " invalid"); + return -1; + } + + if (!busy) + break; + + if (p->timeout_ns != -1LL) { + Genode::error(__func__, " not supported ", + " handle:= ", p->bo_handle, + " timeout_ns:= ", Genode::Hex(p->timeout_ns)); + return -1; + } + + wait_for_completion(); + } + + return 0; + } + + int _device_query(void *arg) + { + auto const query = reinterpret_cast(arg); + + if (query->num_items == 1) { + auto const items = reinterpret_cast(query->items_ptr); + Genode::error(__func__, " query_id=", items->query_id, + items->query_id == DRM_I915_QUERY_TOPOLOGY_INFO ? " query_topology_info" : "", + items->query_id == 3 /*DRM_I915_QUERY_PERF_CONFIG*/ ? " query_perf_config" : ""); + } + + Genode::error("device specific iocall DRM_I915_QUERY not supported" + " - num_items=", query->num_items); + + return -1; + } + + int _device_ioctl(unsigned cmd, void *arg) + { + if (!arg) { + errno = EINVAL; + return -1; + } + + 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 _device_gem_wait(arg); + 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); + default: + Genode::error("Unhandled device specific ioctl:", Genode::Hex(cmd)); + break; + } + + return -1; + } + + int _generic_gem_close(void *arg) + { + auto const p = reinterpret_cast(arg); + Handle_id const id { .value = p->handle }; + return _free_buffer(id); + } + + int _generic_gem_flink(void *arg) + { + auto const p = reinterpret_cast(arg); + p->name = prime_fd; + return 0; + } + + int _generic_syncobj_create(void *arg) + { + drm_syncobj_create * const p = reinterpret_cast(arg); + if (p->flags) { + Genode::error(__func__, " unsupported flags"); + errno = EINVAL; + return -1; + } + auto * const obj = new (&_heap) Sync_obj(_sync_objects); + p->handle = obj->id.id().value; + return 0; + } + + int _generic_syncobj_wait(void *arg) + { + auto &p = *reinterpret_cast(arg); + + Genode::error(__func__, " ", p.count_handles, " ", + Genode::Hex(p.handles), + " tiemout_nsec=", p.timeout_nsec, + " flags=", p.flags); + + if (p.count_handles > 1) { + Genode::error(__func__, " count handles > 1 - not supported"); + return -1; + } + + uint32_t * handles = reinterpret_cast(p.handles); + bool ok = false; + + try { + Sync_obj::Id const id { .value = handles[0] }; + _sync_objects.apply(id, [&](Sync_obj &) { + ok = true; + }); + } catch (Sync_obj::Sync::Unknown_id) { + errno = EINVAL; + return -1; + } + + if (ok) { + errno = 62 /* ETIME */; + return -1; + } else + Genode::error("unknown sync object handle ", handles[0]); + + return -1; + } + int _generic_syncobj_destroy(void *arg) + { + auto * const p = reinterpret_cast(arg); + try { + Sync_obj::Id const id { .value = p->handle }; + _sync_objects.apply(id, [&](Sync_obj &obj) { + Genode::destroy(_heap, &obj); + }); + return 0; + } catch (Sync_obj::Sync::Unknown_id) { + errno = EINVAL; + return -1; + } + } + + int _generic_gem_open(void *arg) + { + auto const p = reinterpret_cast(arg); + + Genode::error("generic ioctl DRM_IOCTL_GEM_OPEN not supported ", + p->handle, " name=", Genode::Hex(p->name)); + + return -1; + } + + int _generic_get_cap(void *arg) + { + auto const p = reinterpret_cast(arg); + + if (p->capability == DRM_CAP_PRIME) { + Genode::error("cap ", p->capability, " ", DRM_CAP_PRIME, " XXXXX"); + /* XXX fd == 43 check */ + p->value = DRM_PRIME_CAP_IMPORT; + return 0; + } + + Genode::error("generic ioctl DRM_IOCTL_GET_CAP not supported ", + p->capability); + return -1; + } + + int const prime_fd { 44 }; + Handle_id prime_handle { }; + + int _generic_prime_fd_to_handle(void *arg) + { + auto const p = reinterpret_cast(arg); + if (p->fd != prime_fd) { + Genode::error("generic ioctl DRM_IOCTL_PRIME_FD_TO_HANDLE not supported ", __builtin_return_address(0), " ", p->fd); + return -1; + } + p->handle = prime_handle.value; + return 0; + } + + int _generic_prime_handle_to_fd(void *arg) + { + auto const p = reinterpret_cast(arg); + + Handle_id const handle { .value = p->handle }; + bool handled = _apply_buffer(handle, [&](Buffer_handle const &bh) { + if (!prime_handle.value) + prime_handle = handle; + + if (prime_handle.value != handle.value) + Genode::error("prime handle changed - ignored ", bh.handle); + }); + if (!handled) + return -1; + + p->fd = prime_fd; + return 0; + } + + int _generic_ioctl(unsigned cmd, void *arg) + { + if (!arg) { + errno = EINVAL; + return -1; + } + + switch (cmd) { + case DRM_NUMBER(DRM_IOCTL_GEM_CLOSE): return _generic_gem_close(arg); + case DRM_NUMBER(DRM_IOCTL_GEM_FLINK): return _generic_gem_flink(arg); + case DRM_NUMBER(DRM_IOCTL_SYNCOBJ_CREATE): return _generic_syncobj_create(arg); + case DRM_NUMBER(DRM_IOCTL_SYNCOBJ_WAIT): return _generic_syncobj_wait(arg); + case DRM_NUMBER(DRM_IOCTL_SYNCOBJ_DESTROY): return _generic_syncobj_destroy(arg); + case DRM_NUMBER(DRM_IOCTL_GEM_OPEN): return _generic_gem_open(arg); + case DRM_NUMBER(DRM_IOCTL_GET_CAP): return _generic_get_cap(arg); + case DRM_NUMBER(DRM_IOCTL_PRIME_FD_TO_HANDLE): + return _generic_prime_fd_to_handle(arg); + case DRM_NUMBER(DRM_IOCTL_PRIME_HANDLE_TO_FD): + return _generic_prime_handle_to_fd(arg); + default: + Genode::error("Unhandled generic DRM ioctl:", Genode::Hex(cmd)); + break; + } + + return -1; + } + + public: + + Drm_call(Genode::Env &env, Genode::Entrypoint &signal_ep) + : _env(env), + _completion_sigh(signal_ep, *this, &Drm_call::_handle_completion) + { + /* 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); + } + + bool map_buffer_ggtt(Offset offset, size_t length) + { + bool result = false; + + _buffer_registry.for_each([&] (Buffer_handle &h) { + if (h.map_offset != offset) { return; } + if (length > h.size) { Genode::error("map_buffer_ggtt: size mismatch"); return; } + result = true; + }); + + if (!result) + Genode::error("could not lookup buffer for offset: ", offset); + + return result; + } + + void unmap_buffer(void *addr, size_t length) + { + bool found = false; + + _buffer_registry.for_each([&] (Buffer_handle &bh) { + if (found || !bh.buffer_attached.constructed()) + return; + + if (reinterpret_cast(bh.mmap_addr()) != addr) + return; + + if (bh.buffer_attached->size() != length) { + Genode::warning(__func__, " size mismatch"); + Genode::sleep_forever(); + return; + } + + bh.buffer_attached.destruct(); + found = true; + }); + + if (!found) { + Genode::warning(__func__, " unknown region ", + addr, "+", Genode::Hex(length)); + Genode::sleep_forever(); + } + } + + void unmap_buffer_ggtt(void *addr, size_t length) + { + Offset const offset = Offset(addr); + + bool handled = false; + + _buffer_registry.for_each([&] (Buffer_handle &h) { + if (handled) return; + if (h.map_offset != offset) return; + if (length > h.size) { Genode::error("unmap_buffer_ggtt: size mismatch"); return; } + + if (!h.map_cap.valid()) { + Genode::error("no valid capability found for offset: ", Genode::Hex(offset)); + return; + } + + _unmap_buffer(h); + handled = true; + }); + + if (!handled) { + Genode::error(__func__, ": unknown addr ", addr, "+", Genode::Hex(length)); + Genode::sleep_forever(); + } + } + + int ioctl(unsigned long request, void *arg) + { + bool const device = device_ioctl(request); + return device ? _device_ioctl(device_number(request), arg) + : _generic_ioctl(command_number(request), arg); + } + + void wait_for_completion() { + _completion_lock.block(); + + /* make done buffer objects */ + Gpu::Info gpu_info { _gpu_session.info() }; + + _buffer_registry.for_each([&] (Buffer_handle &h) { + if (!h.busy) return; + if (h.seqno.id > gpu_info.last_completed.id) return; + h.busy = false; + }); + + } +}; + + +static Genode::Constructible _call; + + +void drm_init(Genode::Env &env, Genode::Entrypoint &signal_ep) +{ + _call.construct(env, signal_ep); +} + + +/** + * Mmap buffer object + * + * On Genode the virtual address of MMAP_GTT is stored in the offset. + */ +extern "C" void *drm_mmap(void * /* vaddr */, size_t length, + int /* prot */, int /* flags */, + int /* fd */, off_t offset) +{ + /* sanity check if we got a GTT mapped offset */ + bool const ok = _call->map_buffer_ggtt(offset, length); + return ok ? (void *)offset : nullptr; +} + +/** + * Unmap buffer object + */ +extern "C" int drm_munmap(void *addr, size_t length) +{ + _call->unmap_buffer(addr, length); + return 0; +} + + +extern "C" int genode_ioctl(int /* fd */, unsigned long request, void *arg) +{ + if (verbose_ioctl) { dump_ioctl(request); } + int const ret = _call->ioctl(request, arg); + if (verbose_ioctl) { Genode::log("returned ", ret); } + return ret; +} diff --git a/repos/libports/src/lib/libdrm/patches/util_match.patch b/repos/libports/src/lib/libdrm/patches/util_match.patch new file mode 100644 index 0000000000..c01b235b41 --- /dev/null +++ b/repos/libports/src/lib/libdrm/patches/util_match.patch @@ -0,0 +1,14 @@ +The libc header contains a different ALIGN +macro. +--- a/src/lib/libdrm/util_math.h ++++ b/src/lib/libdrm/util_math.h +@@ -29,6 +29,9 @@ + #define MAX3( A, B, C ) ((A) > (B) ? MAX2(A, C) : MAX2(B, C)) + + #define __align_mask(value, mask) (((value) + (mask)) & ~(mask)) ++#ifdef ALIGN ++#undef ALIGN ++#endif + #define ALIGN(value, alignment) __align_mask(value, (__typeof__(value))((alignment) - 1)) + + #endif /*_UTIL_MATH_H_*/ diff --git a/repos/libports/src/lib/libdrm/patches/xf86drmMode.patch b/repos/libports/src/lib/libdrm/patches/xf86drmMode.patch new file mode 100644 index 0000000000..21a46bedfe --- /dev/null +++ b/repos/libports/src/lib/libdrm/patches/xf86drmMode.patch @@ -0,0 +1,11 @@ +The neads 'u_int' that is pulled in via +--- a/src/lib/libdrm/xf86drmMode.c ++++ b/src/lib/libdrm/xf86drmMode.c +@@ -37,6 +37,7 @@ + #include + #include + #include ++#include + #if HAVE_SYS_SYSCTL_H + #include + #endif