From d4f3b7b510b60c8656f4ec77c0a6a94c56ad8b3c Mon Sep 17 00:00:00 2001 From: SolDev69 Date: Fri, 8 Dec 2023 08:52:17 -0500 Subject: [PATCH] patches everything in one commit, woop! --- android-aarch64 | 26 ++ android-arm32 | 26 ++ android-drm-aarch64 | 22 ++ android-drm-arm32 | 22 ++ meson.build | 8 +- src/android_stub/meson.build | 2 +- src/egl/drivers/dri2/platform_android.c | 107 +++++++++ src/freedreno/drm/freedreno_bo.c | 30 ++- src/freedreno/drm/freedreno_device.c | 33 ++- src/freedreno/drm/freedreno_drmif.h | 15 ++ src/freedreno/drm/freedreno_pipe.c | 6 + src/freedreno/drm/freedreno_priv.h | 7 + src/freedreno/drm/kgsl/kgsl_bo.c | 208 ++++++++++++++++ src/freedreno/drm/kgsl/kgsl_device.c | 44 ++++ src/freedreno/drm/kgsl/kgsl_pipe.c | 223 ++++++++++++++++++ src/freedreno/drm/kgsl/kgsl_priv.h | 54 +++++ src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c | 119 ++++++++++ src/freedreno/drm/meson.build | 11 + src/freedreno/drm/msm/msm_bo.c | 1 + src/freedreno/drm/msm/msm_device.c | 2 + src/freedreno/drm/virtio/virtio_bo.c | 1 + src/freedreno/drm/virtio/virtio_device.c | 2 + src/freedreno/ir3/ir3_compiler.c | 3 - src/freedreno/ir3/ir3_disk_cache.c | 2 +- src/freedreno/meson.build | 4 +- .../target-helpers/inline_sw_helper.h | 20 ++ .../drivers/freedreno/freedreno_context.c | 30 ++- .../drivers/freedreno/freedreno_public.h | 41 ++++ .../drivers/freedreno/freedreno_screen.c | 27 +-- src/gallium/drivers/freedreno/meson.build | 1 + src/gallium/drivers/zink/zink_bo.c | 2 +- src/gallium/drivers/zink/zink_screen.c | 19 +- src/gallium/targets/osmesa/meson.build | 4 +- src/util/os_misc.c | 53 ----- src/util/perf/cpu_trace.h | 13 - src/util/u_debug_stack_android.cpp | 56 ----- 36 files changed, 1049 insertions(+), 195 deletions(-) create mode 100644 android-aarch64 create mode 100644 android-arm32 create mode 100644 android-drm-aarch64 create mode 100644 android-drm-arm32 create mode 100644 src/freedreno/drm/kgsl/kgsl_bo.c create mode 100644 src/freedreno/drm/kgsl/kgsl_device.c create mode 100644 src/freedreno/drm/kgsl/kgsl_pipe.c create mode 100644 src/freedreno/drm/kgsl/kgsl_priv.h create mode 100644 src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c create mode 100644 src/gallium/drivers/freedreno/freedreno_public.h diff --git a/android-aarch64 b/android-aarch64 new file mode 100644 index 00000000000..2737a2d01bd --- /dev/null +++ b/android-aarch64 @@ -0,0 +1,26 @@ +[binaries] +ar = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar' +c = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC'] +cpp = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android26-clang++', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC', '-fno-exceptions', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-static-libstdc++'] +c_ld = 'lld' +cpp_ld = 'lld' +strip = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip' +# Android doesn't come with a pkg-config, but we need one for meson to be happy not +# finding all the optional deps it looks for. Use system pkg-config pointing at a +# directory we get to populate with any .pc files we want to add for Android + +# Also, include the plain DRM lib we found earlier. Panfrost relies on it rather heavily, especially when +# interacting with the panfrost DRM module and not kbase + +pkgconfig = ['env', 'PKG_CONFIG_LIBDIR=.:/tmp/drm-static/lib/pkgconfig', '/usr/bin/pkg-config'] + +[host_machine] +system = 'linux' +# cpu_family = 'x86_64' +# cpu = 'amd64' + +# ik this is wrong but workaround sanity check +cpu_family = 'arm' +cpu = 'armv8' + +endian = 'little' diff --git a/android-arm32 b/android-arm32 new file mode 100644 index 00000000000..6bd6af4e902 --- /dev/null +++ b/android-arm32 @@ -0,0 +1,26 @@ +[binaries] +ar = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar' +c = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC'] +cpp = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi26-clang++', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC', '-fno-exceptions', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-static-libstdc++'] +c_ld = 'lld' +cpp_ld = 'lld' +strip = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip' +# Android doesn't come with a pkg-config, but we need one for meson to be happy not +# finding all the optional deps it looks for. Use system pkg-config pointing at a +# directory we get to populate with any .pc files we want to add for Android + +# Also, include the plain DRM lib we found earlier. Panfrost relies on it rather heavily, especially when +# interacting with the panfrost DRM module and not kbase + +pkgconfig = ['env', 'PKG_CONFIG_LIBDIR=.:/tmp/drm-static/lib/pkgconfig', '/usr/bin/pkg-config'] + +[host_machine] +system = 'linux' +# cpu_family = 'x86_64' +# cpu = 'amd64' + +# ik this is wrong but workaround sanity check +cpu_family = 'arm' +cpu = 'armv7' + +endian = 'little' diff --git a/android-drm-aarch64 b/android-drm-aarch64 new file mode 100644 index 00000000000..eb91f638435 --- /dev/null +++ b/android-drm-aarch64 @@ -0,0 +1,22 @@ +[binaries] +ar = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar' +c = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC'] +cpp = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/aarch64-linux-android24-clang++', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC', '-fno-exceptions', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-static-libstdc++'] +c_ld = 'lld' +cpp_ld = 'lld' +strip = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip' +# Android doesn't come with a pkg-config, but we need one for meson to be happy not +# finding all the optional deps it looks for. Use system pkg-config pointing at a +# directory we get to populate with any .pc files we want to add for Android +pkgconfig = ['env', 'PKG_CONFIG_LIBDIR=.', '/usr/bin/pkg-config'] + +[host_machine] +system = 'linux' +# cpu_family = 'x86_64' +# cpu = 'amd64' + +# ik this is wrong but workaround sanity check +cpu_family = 'arm' +cpu = 'armv8' + +endian = 'little' diff --git a/android-drm-arm32 b/android-drm-arm32 new file mode 100644 index 00000000000..5fae96b7d1e --- /dev/null +++ b/android-drm-arm32 @@ -0,0 +1,22 @@ +[binaries] +ar = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-ar' +c = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC'] +cpp = ['ccache', '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/armv7a-linux-androideabi24-clang++', '-O3', '-DVK_USE_PLATFORM_ANDROID_KHR', '-fPIC', '-fno-exceptions', '-fno-unwind-tables', '-fno-asynchronous-unwind-tables', '-static-libstdc++'] +c_ld = 'lld' +cpp_ld = 'lld' +strip = '$ANDROID_NDK_ROOT/toolchains/llvm/prebuilt/linux-x86_64/bin/llvm-strip' +# Android doesn't come with a pkg-config, but we need one for meson to be happy not +# finding all the optional deps it looks for. Use system pkg-config pointing at a +# directory we get to populate with any .pc files we want to add for Android +pkgconfig = ['env', 'PKG_CONFIG_LIBDIR=.', '/usr/bin/pkg-config'] + +[host_machine] +system = 'linux' +# cpu_family = 'x86_64' +# cpu = 'amd64' + +# ik this is wrong but workaround sanity check +cpu_family = 'arm' +cpu = 'armv7' + +endian = 'little' diff --git a/meson.build b/meson.build index 61d76eeab1f..2f6d4ce26c7 100644 --- a/meson.build +++ b/meson.build @@ -189,6 +189,10 @@ foreach gallium_driver : gallium_drivers pre_args += '-DHAVE_@0@'.format(gallium_driver.to_upper()) endforeach +if get_option('freedreno-kmds').contains('kgsl') + pre_args += '-DHAVE_FREEDRENO_KGSL' +endif + with_gallium = gallium_drivers.length() != 0 with_gallium_kmsro = system_has_kms_drm and [ with_gallium_asahi, @@ -252,10 +256,6 @@ if freedreno_kmds.length() != 0 and freedreno_kmds != [ 'msm' ] and with_freedre warning('As a side-effect, Turnip is forced to link with libdrm when built alongside Gallium DRM drivers which platforms such as Android may not have available at runtime.') elif _vulkan_drivers != [ 'freedreno' ] warning('Turnip is forced to link with libdrm when built alongside other Vulkan drivers which platforms such as Android may not have available at runtime.') - else - # If DRM support isn't needed, we can get rid of it since linking - # to libdrm can be a potential compatibility hazard. - system_has_kms_drm = false endif endif diff --git a/src/android_stub/meson.build b/src/android_stub/meson.build index 6097ae8ef07..0e3f27bc4a5 100644 --- a/src/android_stub/meson.build +++ b/src/android_stub/meson.build @@ -1,6 +1,6 @@ if with_android_stub stub_libs = [] - lib_names = ['cutils', 'hardware', 'log', 'nativewindow', 'sync'] + lib_names = ['hardware', 'log', 'nativewindow', 'sync'] if with_libbacktrace lib_names += ['backtrace'] diff --git a/src/egl/drivers/dri2/platform_android.c b/src/egl/drivers/dri2/platform_android.c index b0b327036fe..2682f5f934f 100644 --- a/src/egl/drivers/dri2/platform_android.c +++ b/src/egl/drivers/dri2/platform_android.c @@ -410,6 +410,64 @@ cros_get_buffer_info(struct dri2_egl_display *dri2_dpy, return -EINVAL; } +static int +kgsl_window_buffer_get_buffer_info(struct dri2_egl_display *dri2_dpy, + struct ANativeWindowBuffer *buf, + struct buffer_info *out_buf_info) +{ + /* The below code is tested against the version of gralloc shipped + * with the below properties. Different versions of gralloc could modifiy + * the internal format of the handle requiring the handle_data access to be different + * id: "gralloc" + * name: "Graphics Memory Module" + * author: "Code Aurora Forum" + * module_api_version: 0x100 + * hal_api_version: 0x100 + */ + + /* The below code does not handle the YUV texture case */ + const uint32_t *handle_fds = (uint32_t *)buf->handle->data; + const uint32_t *handle_data = &handle_fds[buf->handle->numFds]; + uint32_t gmsm = ('g' << 24) | ('m' << 16) | ('s' << 8) | 'm'; + int drm_fourcc = 0; + int pitch = 0; + int fds[3]; + int num_fds = get_native_buffer_fds(buf, fds); + + if (num_fds == 2 && buf->handle->numInts >= 2 && handle_data[0] == gmsm) { + drm_fourcc = get_fourcc(buf->format); + if (drm_fourcc == -1) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + return -EINVAL; + } + + pitch = buf->stride * get_format_bpp(buf->format); + if (pitch == 0) { + _eglError(EGL_BAD_PARAMETER, "eglCreateEGLImageKHR"); + return -EINVAL; + } + + *out_buf_info = (struct buffer_info){ + .width = buf->width, + .height = buf->height, + .drm_fourcc = drm_fourcc, + .num_planes = 1, + .fds = { fds[0], -1, -1, -1 }, + .modifier = handle_data[1] & 0x08000000 ? DRM_FORMAT_MOD_QCOM_COMPRESSED : DRM_FORMAT_MOD_LINEAR, + .offsets = { 0, 0, 0, 0 }, + .pitches = { pitch, 0, 0, 0 }, + .yuv_color_space = EGL_ITU_REC601_EXT, + .sample_range = EGL_YUV_NARROW_RANGE_EXT, + .horizontal_siting = EGL_YUV_CHROMA_SITING_0_EXT, + .vertical_siting = EGL_YUV_CHROMA_SITING_0_EXT, + }; + + return 0; + } + + return -EINVAL; +} + static __DRIimage * droid_create_image_from_buffer_info(struct dri2_egl_display *dri2_dpy, struct buffer_info *buf_info, void *priv) @@ -455,6 +513,9 @@ droid_create_image_from_native_buffer(_EGLDisplay *disp, if (!img && !cros_get_buffer_info(dri2_dpy, buf, &buf_info)) img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); + if (!img && !kgsl_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info)) + img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); + if (!img && !native_window_buffer_get_buffer_info(dri2_dpy, buf, &buf_info)) img = droid_create_image_from_buffer_info(dri2_dpy, &buf_info, priv); @@ -1396,9 +1457,46 @@ droid_probe_device(_EGLDisplay *disp, bool swrast) return EGL_TRUE; } +static EGLBoolean droid_open_device_kgsl(_EGLDisplay *disp, bool swrast) +{ + struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); + static const char path[] = "/dev/kgsl-3d0"; + static const char driver_name[] = "kgsl"; + + dri2_dpy->fd_render_gpu = loader_open_device(path); + if (dri2_dpy->fd_render_gpu < 0) { + _eglLog(_EGL_WARNING, "Failed to open kgsl"); + return EGL_FALSE; + } + + dri2_dpy->driver_name = strdup(driver_name); + dri2_dpy->loader_extensions = droid_image_loader_extensions; + if (!dri2_load_driver_dri3(disp)) { + free(dri2_dpy->driver_name); + dri2_dpy->driver_name = NULL; + goto error; + } + + if (!dri2_create_screen(disp)) { + _eglLog(_EGL_WARNING, "DRI2: Failed to create screen"); + droid_unload_driver(disp); + goto error; + } + + return EGL_TRUE; +error: + close(dri2_dpy->fd_render_gpu); + dri2_dpy->fd_render_gpu = -1; + return EGL_FALSE; +} + static EGLBoolean droid_open_device(_EGLDisplay *disp, bool swrast) { +#ifdef HAVE_FREEDRENO_KGSL + if (droid_open_device_kgsl(disp, swrast)) + goto done; +#endif #define MAX_DRM_DEVICES 64 struct dri2_egl_display *dri2_dpy = dri2_egl_display(disp); _EGLDevice *dev_list = _eglGlobal.DeviceList; @@ -1505,6 +1603,15 @@ dri2_initialize_android(_EGLDisplay *disp) dri2_dpy->fd_display_gpu = dri2_dpy->fd_render_gpu; + /* Only add a egl device if this is not the kgsl driver */ + if (strcmp(dri2_dpy->driver_name, "kgsl") != 0) { + dev = _eglAddDevice(dri2_dpy->fd_render_gpu, false); + if (!dev) { + err = "DRI2: failed to find EGLDevice"; + goto cleanup; + } + } + dev = _eglFindDevice(dri2_dpy->fd_render_gpu, false); if (!dev) { err = "DRI2: failed to find EGLDevice"; diff --git a/src/freedreno/drm/freedreno_bo.c b/src/freedreno/drm/freedreno_bo.c index 3c8ed16a59f..38e0a88f0c6 100644 --- a/src/freedreno/drm/freedreno_bo.c +++ b/src/freedreno/drm/freedreno_bo.c @@ -219,7 +219,7 @@ fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size) } struct fd_bo * -fd_bo_from_dmabuf(struct fd_device *dev, int fd) +fd_bo_from_dmabuf_drm(struct fd_device *dev, int fd) { int ret, size; uint32_t handle; @@ -254,6 +254,12 @@ fd_bo_from_dmabuf(struct fd_device *dev, int fd) return bo; } +struct fd_bo * +fd_bo_from_dmabuf(struct fd_device *dev, int fd) +{ + return dev->funcs->bo_from_dmabuf(dev, fd); +} + struct fd_bo * fd_bo_from_name(struct fd_device *dev, uint32_t name) { @@ -430,6 +436,15 @@ fd_bo_fini_fences(struct fd_bo *bo) free(bo->fences); } +void +fd_bo_close_handle_drm(struct fd_device *dev, uint32_t handle) +{ + struct drm_gem_close req = { + .handle = handle, + }; + drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); +} + /** * Helper called by backends bo->funcs->destroy() * @@ -453,10 +468,7 @@ fd_bo_fini_common(struct fd_bo *bo) if (handle) { simple_mtx_lock(&table_lock); - struct drm_gem_close req = { - .handle = handle, - }; - drmIoctl(dev->fd, DRM_IOCTL_GEM_CLOSE, &req); + dev->funcs->bo_close_handle(dev, handle); _mesa_hash_table_remove_key(dev->handle_table, &handle); if (bo->name) _mesa_hash_table_remove_key(dev->name_table, &bo->name); @@ -559,8 +571,8 @@ fd_bo_is_cached(struct fd_bo *bo) return !!(bo->alloc_flags & FD_BO_CACHED_COHERENT); } -static void * -bo_map(struct fd_bo *bo) +void * +fd_bo_map_os_mmap(struct fd_bo *bo) { if (!bo->map) { uint64_t offset; @@ -590,7 +602,7 @@ fd_bo_map(struct fd_bo *bo) if (bo->alloc_flags & FD_BO_NOMAP) return NULL; - return bo_map(bo); + return bo->funcs->map(bo); } void @@ -601,7 +613,7 @@ fd_bo_upload(struct fd_bo *bo, void *src, unsigned off, unsigned len) return; } - memcpy((uint8_t *)bo_map(bo) + off, src, len); + memcpy((uint8_t *)bo->funcs->map(bo) + off, src, len); } bool diff --git a/src/freedreno/drm/freedreno_device.c b/src/freedreno/drm/freedreno_device.c index cff09fd8fbb..9400cbd83b3 100644 --- a/src/freedreno/drm/freedreno_device.c +++ b/src/freedreno/drm/freedreno_device.c @@ -37,22 +37,24 @@ struct fd_device *msm_device_new(int fd, drmVersionPtr version); #ifdef HAVE_FREEDRENO_VIRTIO struct fd_device *virtio_device_new(int fd, drmVersionPtr version); #endif +#ifdef HAVE_FREEDRENO_KGSL +struct fd_device *kgsl_device_new(int fd); +#endif struct fd_device * fd_device_new(int fd) { struct fd_device *dev = NULL; - drmVersionPtr version; + drmVersionPtr version = NULL; bool use_heap = false; - + bool support_use_heap = true; +#ifdef HAVE_LIBDRM /* figure out if we are kgsl or msm drm driver: */ version = drmGetVersion(fd); - if (!version) { - ERROR_MSG("cannot get version: %s", strerror(errno)); - return NULL; - } - - if (!strcmp(version->name, "msm")) { + if (!version) + DEBUG_MSG("cannot get version: %s", strerror(errno)); +#endif + if (version && !strcmp(version->name, "msm")) { DEBUG_MSG("msm DRM device"); if (version->version_major != 1) { ERROR_MSG("unsupported version: %u.%u.%u", version->version_major, @@ -62,7 +64,7 @@ fd_device_new(int fd) dev = msm_device_new(fd, version); #ifdef HAVE_FREEDRENO_VIRTIO - } else if (!strcmp(version->name, "virtio_gpu")) { + } else if (version && !strcmp(version->name, "virtio_gpu")) { DEBUG_MSG("virtio_gpu DRM device"); dev = virtio_device_new(fd, version); /* Only devices that support a hypervisor are a6xx+, so avoid the @@ -71,9 +73,12 @@ fd_device_new(int fd) use_heap = true; #endif #if HAVE_FREEDRENO_KGSL - } else if (!strcmp(version->name, "kgsl")) { + } else { DEBUG_MSG("kgsl DRM device"); dev = kgsl_device_new(fd); + support_use_heap = false; + if (dev) + goto out; #endif } @@ -113,7 +118,7 @@ fd_device_new(int fd) fd_pipe_del(pipe); } - if (use_heap) { + if (support_use_heap && use_heap) { dev->ring_heap = fd_bo_heap_new(dev, RING_FLAGS); dev->default_heap = fd_bo_heap_new(dev, 0); } @@ -226,6 +231,12 @@ fd_dbg(void) return debug_get_option_libgl(); } +uint32_t +fd_get_features(struct fd_device *dev) +{ + return dev->features; +} + bool fd_has_syncobj(struct fd_device *dev) { diff --git a/src/freedreno/drm/freedreno_drmif.h b/src/freedreno/drm/freedreno_drmif.h index 6a20e7ac3dd..081096113ba 100644 --- a/src/freedreno/drm/freedreno_drmif.h +++ b/src/freedreno/drm/freedreno_drmif.h @@ -67,6 +67,13 @@ enum fd_param_id { FD_VA_SIZE, /* GPU virtual address size */ }; +enum fd_reset_status { + FD_RESET_NO_ERROR, + FD_RESET_GUILTY, + FD_RESET_INNOCENT, + FD_RESET_UNKNOWN, +}; + /** * Helper for fence/seqno comparisions which deals properly with rollover. * Returns true if fence 'a' is before fence 'b' @@ -184,6 +191,12 @@ enum fd_version { }; enum fd_version fd_device_version(struct fd_device *dev); +enum fd_features { + FD_FEATURE_DIRECT_RESET = 1, + FD_FEATURE_IMPORT_DMABUF = 2, +}; + +uint32_t fd_get_features(struct fd_device *dev); bool fd_has_syncobj(struct fd_device *dev); /* pipe functions: @@ -205,6 +218,7 @@ int fd_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence); /* timeout in nanosec */ int fd_pipe_wait_timeout(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t timeout); +int fd_pipe_get_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status); /* buffer-object functions: */ @@ -286,6 +300,7 @@ struct fd_bo *fd_bo_from_handle(struct fd_device *dev, uint32_t handle, uint32_t size); struct fd_bo *fd_bo_from_name(struct fd_device *dev, uint32_t name); struct fd_bo *fd_bo_from_dmabuf(struct fd_device *dev, int fd); +struct fd_bo *fd_bo_from_dmabuf_drm(struct fd_device *dev, int fd); void fd_bo_mark_for_dump(struct fd_bo *bo); static inline uint64_t diff --git a/src/freedreno/drm/freedreno_pipe.c b/src/freedreno/drm/freedreno_pipe.c index 13e8ad979e8..9fd443a9631 100644 --- a/src/freedreno/drm/freedreno_pipe.c +++ b/src/freedreno/drm/freedreno_pipe.c @@ -213,6 +213,12 @@ fd_pipe_emit_fence(struct fd_pipe *pipe, struct fd_ringbuffer *ring) return fence; } +int +fd_pipe_get_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status) +{ + return pipe->funcs->reset_status(pipe, status); +} + struct fd_fence * fd_fence_new(struct fd_pipe *pipe, bool use_fence_fd) { diff --git a/src/freedreno/drm/freedreno_priv.h b/src/freedreno/drm/freedreno_priv.h index 564afd5935f..130851ac617 100644 --- a/src/freedreno/drm/freedreno_priv.h +++ b/src/freedreno/drm/freedreno_priv.h @@ -108,6 +108,8 @@ struct fd_device_funcs { */ struct fd_bo *(*bo_from_handle)(struct fd_device *dev, uint32_t size, uint32_t handle); + struct fd_bo *(*bo_from_dmabuf)(struct fd_device *dev, int fd); + void (*bo_close_handle)(struct fd_device *dev, uint32_t handle); struct fd_pipe *(*pipe_new)(struct fd_device *dev, enum fd_pipe_id id, unsigned prio); @@ -204,6 +206,7 @@ struct fd_device { int fd; enum fd_version version; int32_t refcnt; + uint32_t features; /* tables to keep track of bo's, to avoid "evil-twin" fd_bo objects: * @@ -305,6 +308,7 @@ struct fd_pipe_funcs { struct fd_ringbuffer *(*ringbuffer_new_object)(struct fd_pipe *pipe, uint32_t size); struct fd_submit *(*submit_new)(struct fd_pipe *pipe); + int (*reset_status)(struct fd_pipe *pipe, enum fd_reset_status *status); /** * Flush any deferred submits (if deferred submits are supported by @@ -421,6 +425,7 @@ fd_dev_count_deferred_cmds(struct fd_device *dev) struct fd_bo_funcs { int (*offset)(struct fd_bo *bo, uint64_t *offset); + void *(*map)(struct fd_bo *bo); int (*cpu_prep)(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op); int (*madvise)(struct fd_bo *bo, int willneed); uint64_t (*iova)(struct fd_bo *bo); @@ -453,6 +458,7 @@ struct fd_bo_funcs { }; void fd_bo_add_fence(struct fd_bo *bo, struct fd_fence *fence); +void *fd_bo_map_os_mmap(struct fd_bo *bo); enum fd_bo_state { FD_BO_STATE_IDLE, @@ -466,6 +472,7 @@ void fd_bo_fini_fences(struct fd_bo *bo); void fd_bo_fini_common(struct fd_bo *bo); struct fd_bo *fd_bo_new_ring(struct fd_device *dev, uint32_t size); +void fd_bo_close_handle_drm(struct fd_device *dev, uint32_t handle); #define enable_debug 0 /* TODO make dynamic */ diff --git a/src/freedreno/drm/kgsl/kgsl_bo.c b/src/freedreno/drm/kgsl/kgsl_bo.c new file mode 100644 index 00000000000..6e4124589fe --- /dev/null +++ b/src/freedreno/drm/kgsl/kgsl_bo.c @@ -0,0 +1,208 @@ +#include "kgsl_priv.h" +#include "util/os_mman.h" + +static uint64_t +kgsl_bo_iova(struct fd_bo *bo) +{ + struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); + return kgsl_bo->iova; +} + +static void +kgsl_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) +{ + /* This function is a no op for KGSL */ + return; +} + +static int +kgsl_bo_offset(struct fd_bo *bo, uint64_t *offset) +{ + /* from tu_kgsl.c - offset for mmap needs to be */ + /* the returned alloc id shifted over 12 */ + *offset = bo->handle << 12; + return 0; +} + +static int +kgsl_bo_madvise(struct fd_bo *bo, int willneed) +{ + /* KGSL does not support this, so simply return willneed */ + return willneed; +} + +static int +kgsl_bo_cpu_prep(struct fd_bo *bo, struct fd_pipe *pipe, uint32_t op) +{ + /* only need to handle implicit sync here which is a NOP for KGSL */ + return 0; +} + +void +kgsl_bo_close_handle(struct fd_bo *bo) +{ + struct kgsl_gpumem_free_id req = { + .id = bo->handle + }; + + kgsl_pipe_safe_ioctl(bo->dev->fd, IOCTL_KGSL_GPUMEM_FREE_ID, &req); +} + +static void +kgsl_bo_destroy(struct fd_bo *bo) +{ + /* KGSL will immediately delete the BO when we close + * the handle, so wait on all fences to ensure + * the GPU is done using it before we destory it + */ + for (uint32_t i = 0; i < bo->nr_fences; i++) { + struct fd_pipe *pipe = bo->fences[i]->pipe; + pipe->funcs->wait(pipe, bo->fences[i], ~0); + } + + fd_bo_fini_common(bo); +} + +static void * +kgsl_bo_map(struct fd_bo *bo) +{ + struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); + if (!bo->map) { + if (kgsl_bo->bo_type == KGSL_BO_IMPORT) { + /* in `fd_bo_map` if it tries to mmap this BO. mmap logic is copied from + * https://android.googlesource.com/platform/hardware/libhardware/+/master/modules/gralloc/mapper.cpp#44 + */ + bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, kgsl_bo->import_fd, 0); + } else { + uint64_t offset; + int ret; + + ret = bo->funcs->offset(bo, &offset); + if (ret) { + return NULL; + } + + bo->map = os_mmap(0, bo->size, PROT_READ | PROT_WRITE, MAP_SHARED, + bo->dev->fd, offset); + if (bo->map == MAP_FAILED) { + ERROR_MSG("mmap failed: %s", strerror(errno)); + bo->map = NULL; + } + } + + if (bo->map == MAP_FAILED) { + ERROR_MSG("mmap failed: %s", strerror(errno)); + bo->map = NULL; + } + } + return bo->map; +} + +static const struct fd_bo_funcs bo_funcs = { + .iova = kgsl_bo_iova, + .set_name = kgsl_bo_set_name, + .offset = kgsl_bo_offset, + .map = kgsl_bo_map, + .madvise = kgsl_bo_madvise, + .cpu_prep = kgsl_bo_cpu_prep, + .destroy = kgsl_bo_destroy, +}; + +/* Size is not used by KGSL */ +struct fd_bo * +kgsl_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle) +{ + struct fd_bo *bo; + int ret; + struct kgsl_gpuobj_info req = { + .id = handle, + }; + + ret = kgsl_pipe_safe_ioctl(dev->fd, + IOCTL_KGSL_GPUOBJ_INFO, &req); + + if (ret) { + ERROR_MSG("Failed to get handle info (%s)", strerror(errno)); + return NULL; + } + + struct kgsl_bo *kgsl_bo = calloc(1, sizeof(*kgsl_bo)); + if (!kgsl_bo) + return NULL; + + bo = &kgsl_bo->base; + bo->dev = dev; + bo->size = req.size; + bo->handle = req.id; + bo->funcs = &bo_funcs; + + kgsl_bo->iova = req.gpuaddr; + + fd_bo_init_common(bo, dev); + + return bo; +} + +struct fd_bo * +kgsl_bo_from_dmabuf(struct fd_device *dev, int fd) +{ + struct fd_bo *bo; + struct kgsl_gpuobj_import_dma_buf import_dmabuf = { + .fd = fd, + }; + struct kgsl_gpuobj_import req = { + .priv = (uintptr_t)&import_dmabuf, + .priv_len = sizeof(import_dmabuf), + .flags = 0, + .type = KGSL_USER_MEM_TYPE_DMABUF, + }; + int ret; + + ret = kgsl_pipe_safe_ioctl(dev->fd, + IOCTL_KGSL_GPUOBJ_IMPORT, &req); + + if (ret) { + ERROR_MSG("Failed to import dma-buf (%s)", strerror(errno)); + return NULL; + } + + bo = fd_bo_from_handle(dev, req.id, 0); + + struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); + kgsl_bo->bo_type = KGSL_BO_IMPORT; + kgsl_bo->import_fd = fd; + + return bo; +} + +struct fd_bo * +kgsl_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags) +{ + int ret; + struct fd_bo *bo; + struct kgsl_gpumem_alloc_id req = { + .size = size, + }; + + if (flags & FD_BO_GPUREADONLY) + req.flags |= KGSL_MEMFLAGS_GPUREADONLY; + + ret = kgsl_pipe_safe_ioctl(dev->fd, IOCTL_KGSL_GPUMEM_ALLOC_ID, &req); + + if (ret) { + ERROR_MSG("GPUMEM_ALLOC_ID failed (%s)", strerror(errno)); + return NULL; + } + + bo = kgsl_bo_from_handle(dev, size, req.id); + + struct kgsl_bo *kgsl_bo = to_kgsl_bo(bo); + kgsl_bo->bo_type = KGSL_BO_NATIVE; + + if (!bo) { + ERROR_MSG("Failed to allocate buffer object"); + return NULL; + } + + return bo; +} diff --git a/src/freedreno/drm/kgsl/kgsl_device.c b/src/freedreno/drm/kgsl/kgsl_device.c new file mode 100644 index 00000000000..702b6666731 --- /dev/null +++ b/src/freedreno/drm/kgsl/kgsl_device.c @@ -0,0 +1,44 @@ +#include "kgsl_priv.h" + +static const struct fd_device_funcs funcs = { + .bo_new = kgsl_bo_new, + .pipe_new = kgsl_pipe_new, + .bo_from_handle = kgsl_bo_from_handle, + .bo_from_dmabuf = kgsl_bo_from_dmabuf, + .bo_close_handle = kgsl_bo_close_handle, + .destroy = kgsl_device_destroy, +}; + +struct fd_device * +kgsl_device_new(int fd) +{ + struct kgsl_device *kgsl_dev; + struct fd_device *dev; + struct kgsl_devinfo info; + + /* Try to read the device info to detect if the FD is really KGSL */ + if(kgsl_get_prop(fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) + return NULL; + + kgsl_dev = calloc(1, sizeof(*kgsl_dev)); + if (!kgsl_dev) + return NULL; + + dev = &kgsl_dev->base; + dev->funcs = &funcs; + dev->fd = fd; + dev->version = FD_VERSION_ROBUSTNESS; + dev->features = FD_FEATURE_DIRECT_RESET | FD_FEATURE_IMPORT_DMABUF; + + /* async submit_queue used for softpin deffered submits */ + util_queue_init(&dev->submit_queue, "sq", 8, 1, 0, NULL); + + dev->bo_size = sizeof(struct kgsl_bo); + + return dev; +} + +static void +kgsl_device_destroy(struct fd_device *dev) +{ +} diff --git a/src/freedreno/drm/kgsl/kgsl_pipe.c b/src/freedreno/drm/kgsl/kgsl_pipe.c new file mode 100644 index 00000000000..7adec108dd0 --- /dev/null +++ b/src/freedreno/drm/kgsl/kgsl_pipe.c @@ -0,0 +1,223 @@ +#include "kgsl_priv.h" +#include "freedreno_ringbuffer_sp.h" + +/* TODO this function is borrowed from turnip, can it be shared in some way? */ +int +kgsl_pipe_safe_ioctl(int fd, unsigned long request, void *arg) +{ + int ret; + + do { + ret = ioctl(fd, request, arg); + } while (ret == -1 && (errno == EINTR || errno == EAGAIN)); + + return ret; +} + +/* TODO this function is borrowed from turnip, can it be shared in some way? + * safe_ioctl is not enough as restarted waits would not adjust the timeout + * which could lead to waiting substantially longer than requested + */ +static int +wait_timestamp_safe(int fd, + unsigned int context_id, + unsigned int timestamp, + int64_t timeout_ms) +{ + int64_t start_time = os_time_get_nano(); + struct kgsl_device_waittimestamp_ctxtid wait = { + .context_id = context_id, + .timestamp = timestamp, + .timeout = timeout_ms, + }; + + while (true) { + int ret = kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_WAITTIMESTAMP_CTXTID, &wait); + + if (ret == -1 && (errno == EINTR || errno == EAGAIN)) { + int64_t current_time = os_time_get_nano(); + + /* update timeout to consider time that has passed since the start */ + timeout_ms -= (current_time - start_time) / 1000000; + if (timeout_ms <= 0) { + errno = ETIME; + return -1; + } + + wait.timeout = (unsigned int) timeout_ms; + start_time = current_time; + } else { + return ret; + } + } +} + +int +kgsl_get_prop(int fd, unsigned int type, void *value, size_t size) +{ + struct kgsl_device_getproperty getprop = { + .type = type, + .value = value, + .sizebytes = size, + }; + + return kgsl_pipe_safe_ioctl(fd, IOCTL_KGSL_DEVICE_GETPROPERTY, &getprop); +} + +static int +kgsl_pipe_get_param(struct fd_pipe *pipe, enum fd_param_id param, + uint64_t *value) +{ + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + switch (param) { + case FD_DEVICE_ID: + case FD_GPU_ID: + *value = kgsl_pipe->dev_id.gpu_id; + return 0; + case FD_GMEM_SIZE: + *value = kgsl_pipe->gmem_size; + return 0; + case FD_GMEM_BASE: + *value = kgsl_pipe->gmem_base; + return 0; + case FD_CHIP_ID: + *value = kgsl_pipe->dev_id.chip_id; + return 0; + case FD_NR_PRIORITIES: + /* Take from kgsl kmd source code, if device is a4xx or newer + * it has KGSL_PRIORITY_MAX_RB_LEVELS=4 priorities otherwise it just has one. + * https://android.googlesource.com/kernel/msm/+/refs/tags/android-13.0.0_r0.21/drivers/gpu/msm/kgsl.h#56 + */ + *value = kgsl_pipe->dev_id.gpu_id >= 400 ? 4 : 1; + return 0; + case FD_MAX_FREQ: + /* Explicity fault on MAX_FREQ as we don't have a way to convert + * timestamp values from KGSL into time values. If we use the default + * path an error message would be generated when this is simply an + * unsupported feature. + */ + return -1; + default: + ERROR_MSG("invalid param id: %d", param); + return -1; + } +} + +static int +kgsl_pipe_set_param(struct fd_pipe *pipe, uint32_t param, uint64_t value) +{ + ERROR_MSG("kgsl_pipe_set_param not implemented"); + return -1; +} + +static int +kgsl_pipe_wait(struct fd_pipe *pipe, const struct fd_fence *fence, uint64_t timeout) +{ + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + return wait_timestamp_safe(pipe->dev->fd, kgsl_pipe->queue_id, fence->kfence, timeout); +} + +static void +kgsl_pipe_destroy(struct fd_pipe *pipe) +{ + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + struct kgsl_drawctxt_destroy req = { + .drawctxt_id = kgsl_pipe->queue_id, + }; + + fd_pipe_sp_ringpool_fini(pipe); + kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_DRAWCTXT_DESTROY, &req); + free(kgsl_pipe); +} + +static int +kgsl_reset_status(struct fd_pipe *pipe, enum fd_reset_status *status) +{ + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + uint32_t value = kgsl_pipe->queue_id; + int ret = kgsl_get_prop(pipe->dev->fd, KGSL_PROP_GPU_RESET_STAT, &value, sizeof(value)); + + if (!ret) { + switch (value) { + case KGSL_CTX_STAT_NO_ERROR: + *status = FD_RESET_NO_ERROR; + break; + case KGSL_CTX_STAT_GUILTY_CONTEXT_RESET_EXT: + *status = FD_RESET_GUILTY; + break; + case KGSL_CTX_STAT_INNOCENT_CONTEXT_RESET_EXT: + *status = FD_RESET_INNOCENT; + break; + case KGSL_CTX_STAT_UNKNOWN_CONTEXT_RESET_EXT: + default: + *status = FD_RESET_UNKNOWN; + break; + } + } + + return ret; +} + +static const struct fd_pipe_funcs pipe_funcs = { + .ringbuffer_new_object = fd_ringbuffer_sp_new_object, + .submit_new = kgsl_submit_sp_new, + .reset_status = kgsl_reset_status, + .flush = fd_pipe_sp_flush, + .wait = kgsl_pipe_wait, + .get_param = kgsl_pipe_get_param, + .set_param = kgsl_pipe_set_param, + .destroy = kgsl_pipe_destroy, +}; + +struct fd_pipe *kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, + uint32_t prio) +{ + struct kgsl_pipe *kgsl_pipe = NULL; + struct fd_pipe *pipe = NULL; + kgsl_pipe = calloc(1, sizeof(*kgsl_pipe)); + if (!kgsl_pipe) { + ERROR_MSG("allocation failed"); + goto fail; + } + + pipe = &kgsl_pipe->base; + pipe->dev = dev; + pipe->funcs = &pipe_funcs; + + struct kgsl_devinfo info; + if(kgsl_get_prop(dev->fd, KGSL_PROP_DEVICE_INFO, &info, sizeof(info))) + goto fail; + + uint64_t gmem_iova; + if(kgsl_get_prop(dev->fd, KGSL_PROP_UCHE_GMEM_VADDR, &gmem_iova, sizeof(gmem_iova))) + goto fail; + + kgsl_pipe->dev_id.gpu_id = + ((info.chip_id >> 24) & 0xff) * 100 + + ((info.chip_id >> 16) & 0xff) * 10 + + ((info.chip_id >> 8) & 0xff); + + kgsl_pipe->dev_id.chip_id = info.chip_id; + kgsl_pipe->gmem_size = info.gmem_sizebytes; + kgsl_pipe->gmem_base = gmem_iova; + + struct kgsl_drawctxt_create req = { + .flags = KGSL_CONTEXT_SAVE_GMEM | + KGSL_CONTEXT_NO_GMEM_ALLOC | + KGSL_CONTEXT_PREAMBLE, + }; + + int ret = kgsl_pipe_safe_ioctl(dev->fd, IOCTL_KGSL_DRAWCTXT_CREATE, &req); + if(ret) + goto fail; + + kgsl_pipe->queue_id = req.drawctxt_id; + + fd_pipe_sp_ringpool_init(pipe); + + return pipe; +fail: + if (pipe) + fd_pipe_del(pipe); + return NULL; +} diff --git a/src/freedreno/drm/kgsl/kgsl_priv.h b/src/freedreno/drm/kgsl/kgsl_priv.h new file mode 100644 index 00000000000..aea48f801e9 --- /dev/null +++ b/src/freedreno/drm/kgsl/kgsl_priv.h @@ -0,0 +1,54 @@ +#ifndef KGSL_PRIV_H +#define KGSL_PRIV_H +#include "../freedreno_priv.h" + +/* TODO the KGSL kernel interface should probably be moved */ +/* into someplace common that both turnip and freedreno can use */ +#include "../../vulkan/msm_kgsl.h" + +int kgsl_get_prop(int fd, unsigned int type, void *value, size_t size); + +struct kgsl_device { + struct fd_device base; +}; +FD_DEFINE_CAST(fd_device, kgsl_device); + +struct fd_device *kgsl_device_new(int fd); +static void kgsl_device_destroy(struct fd_device *dev); + +struct kgsl_pipe { + struct fd_pipe base; + + struct fd_dev_id dev_id; + + uint32_t gmem_size; + uint64_t gmem_base; + uint32_t queue_id; +}; +FD_DEFINE_CAST(fd_pipe, kgsl_pipe); + +struct fd_pipe *kgsl_pipe_new(struct fd_device *dev, enum fd_pipe_id id, + uint32_t prio); +int kgsl_pipe_safe_ioctl(int fd, unsigned long request, void *arg); +struct fd_submit *kgsl_submit_sp_new(struct fd_pipe *pipe); + +struct kgsl_bo { + struct fd_bo base; + const char *name; + uint64_t iova; + uint32_t queue_id; + int import_fd; // fd for imported buffers + + enum { + KGSL_BO_NATIVE, + KGSL_BO_IMPORT, + } bo_type; +}; +FD_DEFINE_CAST(fd_bo, kgsl_bo); + +struct fd_bo *kgsl_bo_new(struct fd_device *dev, uint32_t size, uint32_t flags); +struct fd_bo *kgsl_bo_from_dmabuf(struct fd_device *dev, int fd); +struct fd_bo *kgsl_bo_from_handle(struct fd_device *dev, uint32_t size, uint32_t handle); +void kgsl_bo_close_handle(struct fd_bo *bo); + +#endif diff --git a/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c b/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c new file mode 100644 index 00000000000..e8b2842ac3d --- /dev/null +++ b/src/freedreno/drm/kgsl/kgsl_ringbuffer_sp.c @@ -0,0 +1,119 @@ +#include "kgsl_priv.h" +#include "freedreno_ringbuffer_sp.h" + +static int +timestamp_to_fd(struct fd_pipe *pipe, uint32_t timestamp) +{ + int fd; + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + struct kgsl_timestamp_event event = { + .type = KGSL_TIMESTAMP_EVENT_FENCE, + .context_id = kgsl_pipe->queue_id, + .timestamp = timestamp, + .priv = &fd, + .len = sizeof(fd), + }; + + int ret = kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_TIMESTAMP_EVENT, &event); + if (ret) + return -1; + + return fd; +} + +static int +flush_submit_list(struct list_head *submit_list) +{ + struct fd_submit_sp *fd_submit = to_fd_submit_sp(last_submit(submit_list)); + struct fd_pipe *pipe = fd_submit->base.pipe; + struct kgsl_pipe *kgsl_pipe = to_kgsl_pipe(pipe); + unsigned nr_cmds = 0; + + + MESA_TRACE_FUNC(); + + foreach_submit (submit, submit_list) { + assert(submit->pipe == &kgsl_pipe->base); + nr_cmds += to_fd_ringbuffer_sp(submit->primary)->u.nr_cmds; + } + + struct kgsl_command_object cmds[nr_cmds]; + unsigned cmd_idx = 0; + foreach_submit_safe (submit, submit_list) { + struct fd_ringbuffer_sp *deferred_primary = + to_fd_ringbuffer_sp(submit->primary); + + for (unsigned i = 0; i < deferred_primary->u.nr_cmds; i++) { + struct fd_bo *ring_bo = deferred_primary->u.cmds[i].ring_bo; + + cmds[cmd_idx++] = (struct kgsl_command_object) { + .offset = 0, + .gpuaddr = ring_bo->iova + submit_offset(ring_bo, deferred_primary->offset), + .size = deferred_primary->u.cmds[i].size, + .flags = KGSL_CMDLIST_IB, + .id = ring_bo->handle, + }; + } + + if (submit == last_submit(submit_list)) { + DEBUG_MSG("merged %u submits", cmd_idx); + break; + } + + list_del(&submit->node); + fd_submit_del(submit); + } + + struct kgsl_cmd_syncpoint_fence sync_fence = { + .fd = fd_submit->in_fence_fd, + }; + + struct kgsl_command_syncpoint sync = { + .type = KGSL_CMD_SYNCPOINT_TYPE_FENCE, + .size = sizeof(sync_fence), + .priv = (uintptr_t) &sync_fence, + }; + + + struct kgsl_gpu_command req = { + .flags = KGSL_CMDBATCH_SUBMIT_IB_LIST, + .context_id = kgsl_pipe->queue_id, + .cmdlist = (uintptr_t) cmds, + .numcmds = cmd_idx, + .cmdsize = sizeof(struct kgsl_command_object), + .synclist = (uintptr_t) &sync, + .syncsize = sizeof(struct kgsl_command_syncpoint), + .numsyncs = sync_fence.fd != -1 ? 1 : 0, + }; + + int ret = kgsl_pipe_safe_ioctl(pipe->dev->fd, IOCTL_KGSL_GPU_COMMAND, &req); + + if (ret) { + ERROR_MSG("submit failed %d (%s)", ret, strerror(errno)); + goto fail; + } + + fd_submit->out_fence->kfence = req.timestamp; + + if (fd_submit->out_fence->use_fence_fd) { + int fd = timestamp_to_fd(pipe, req.timestamp); + if (fd < 0) { + ERROR_MSG("Failed to create sync file for timestamp (%s)", strerror(errno)); + goto fail; + } + + fd_submit->out_fence->fence_fd = fd; + } + + if (fd_submit->in_fence_fd != -1) + close(fd_submit->in_fence_fd); + +fail: + return ret; +} + +struct fd_submit * +kgsl_submit_sp_new(struct fd_pipe *pipe) +{ + return fd_submit_sp_new(pipe, flush_submit_list); +} diff --git a/src/freedreno/drm/meson.build b/src/freedreno/drm/meson.build index 4f56e826b0e..c2d21f6083e 100644 --- a/src/freedreno/drm/meson.build +++ b/src/freedreno/drm/meson.build @@ -62,6 +62,17 @@ if freedreno_kmds.contains('virtio') libfreedreno_drm_includes += inc_virtio_gpu endif +libfreedreno_kgsl_files = files( + 'kgsl/kgsl_device.c', + 'kgsl/kgsl_bo.c', + 'kgsl/kgsl_pipe.c', + 'kgsl/kgsl_ringbuffer_sp.c', +) + +if freedreno_kmds.contains('kgsl') + libfreedreno_drm_files += libfreedreno_kgsl_files +endif + libfreedreno_drm = static_library( 'freedreno_drm', [ diff --git a/src/freedreno/drm/msm/msm_bo.c b/src/freedreno/drm/msm/msm_bo.c index 22db5cc1fdd..32d9ce01875 100644 --- a/src/freedreno/drm/msm/msm_bo.c +++ b/src/freedreno/drm/msm/msm_bo.c @@ -138,6 +138,7 @@ msm_bo_set_name(struct fd_bo *bo, const char *fmt, va_list ap) static const struct fd_bo_funcs funcs = { .offset = msm_bo_offset, + .map = fd_bo_map_os_mmap, .cpu_prep = msm_bo_cpu_prep, .madvise = msm_bo_madvise, .iova = msm_bo_iova, diff --git a/src/freedreno/drm/msm/msm_device.c b/src/freedreno/drm/msm/msm_device.c index 4e353c1375c..605808a3d4b 100644 --- a/src/freedreno/drm/msm/msm_device.c +++ b/src/freedreno/drm/msm/msm_device.c @@ -38,6 +38,8 @@ msm_device_destroy(struct fd_device *dev) static const struct fd_device_funcs funcs = { .bo_new = msm_bo_new, .bo_from_handle = msm_bo_from_handle, + .bo_from_dmabuf = fd_bo_from_dmabuf_drm, + .bo_close_handle = fd_bo_close_handle_drm, .pipe_new = msm_pipe_new, .destroy = msm_device_destroy, }; diff --git a/src/freedreno/drm/virtio/virtio_bo.c b/src/freedreno/drm/virtio/virtio_bo.c index f5c1ace788c..bb1f4b9c379 100644 --- a/src/freedreno/drm/virtio/virtio_bo.c +++ b/src/freedreno/drm/virtio/virtio_bo.c @@ -274,6 +274,7 @@ virtio_bo_finalize(struct fd_bo *bo) static const struct fd_bo_funcs funcs = { .offset = virtio_bo_offset, .cpu_prep = virtio_bo_cpu_prep, + .map = fd_bo_map_os_mmap, .madvise = virtio_bo_madvise, .iova = virtio_bo_iova, .set_name = virtio_bo_set_name, diff --git a/src/freedreno/drm/virtio/virtio_device.c b/src/freedreno/drm/virtio/virtio_device.c index 6b3efd29a5a..67a6a282984 100644 --- a/src/freedreno/drm/virtio/virtio_device.c +++ b/src/freedreno/drm/virtio/virtio_device.c @@ -42,6 +42,8 @@ virtio_device_destroy(struct fd_device *dev) static const struct fd_device_funcs funcs = { .bo_new = virtio_bo_new, .bo_from_handle = virtio_bo_from_handle, + .bo_from_dmabuf = fd_bo_from_dmabuf_drm, + .bo_close_handle = fd_bo_close_handle_drm, .pipe_new = virtio_pipe_new, .flush = virtio_execbuf_flush, .destroy = virtio_device_destroy, diff --git a/src/freedreno/ir3/ir3_compiler.c b/src/freedreno/ir3/ir3_compiler.c index 34b08b2fe0b..93ba36f9b72 100644 --- a/src/freedreno/ir3/ir3_compiler.c +++ b/src/freedreno/ir3/ir3_compiler.c @@ -307,9 +307,6 @@ ir3_compiler_create(struct fd_device *dev, const struct fd_dev_id *dev_id, if (compiler->gen >= 5 && !(ir3_shader_debug & IR3_DBG_NOFP16)) compiler->nir_options.support_16bit_alu = true; - if (!options->disable_cache) - ir3_disk_cache_init(compiler); - return compiler; } diff --git a/src/freedreno/ir3/ir3_disk_cache.c b/src/freedreno/ir3/ir3_disk_cache.c index a7c39556956..2f16baafeab 100644 --- a/src/freedreno/ir3/ir3_disk_cache.c +++ b/src/freedreno/ir3/ir3_disk_cache.c @@ -56,7 +56,7 @@ ir3_disk_cache_init(struct ir3_compiler *compiler) build_id_find_nhdr_for_addr(ir3_disk_cache_init); assert(note && build_id_length(note) == 20); /* sha1 */ - const uint8_t *id_sha1 = build_id_data(note); + const uint8_t *id_sha1 = "1"; assert(id_sha1); char timestamp[41]; diff --git a/src/freedreno/meson.build b/src/freedreno/meson.build index a5cdefbd01b..97090a09338 100644 --- a/src/freedreno/meson.build +++ b/src/freedreno/meson.build @@ -28,8 +28,8 @@ rnn_path = rnn_src_path + ':' + get_option('prefix') + '/' + rnn_install_path dep_lua = dependency('lua54', 'lua53', 'lua52', 'lua', required: false, fallback : ['lua', 'lua_dep'], version: '>=5.2') -dep_libarchive = dependency('libarchive', fallback : ['libarchive', 'libarchive_dep'], required: false) -dep_libxml2 = dependency('libxml-2.0', fallback: ['libxml2', 'libxml2_dep'], required: false) +dep_libarchive = dependency('libarchive', required: false) +dep_libxml2 = dependency('libxml-2.0', required: false) prog_gzip = find_program('gzip', required: false) install_fd_decode_tools = dep_libxml2.found() and prog_gzip.found() and \ diff --git a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h index ddb67b3a25a..4b09b177aa4 100644 --- a/src/gallium/auxiliary/target-helpers/inline_sw_helper.h +++ b/src/gallium/auxiliary/target-helpers/inline_sw_helper.h @@ -29,6 +29,14 @@ #include "d3d12/d3d12_public.h" #endif +#ifdef GALLIUM_ZINK +#include "zink/zink_public.h" +#endif + +#ifdef GALLIUM_FREEDRENO +#include "freedreno/freedreno_public.h" +#endif + static inline struct pipe_screen * sw_screen_create_named(struct sw_winsys *winsys, const char *driver) { @@ -62,6 +70,18 @@ sw_screen_create_named(struct sw_winsys *winsys, const char *driver) screen = d3d12_create_dxcore_screen(winsys, NULL); #endif +#if defined(GALLIUM_FREEDRENO) + if(screen == NULL && strcmp(driver, "freedreno") == 0) { + int kbase_device_fd = open("/dev/kgsl-3d0", O_RDWR | O_CLOEXEC | O_NONBLOCK); + if (kbase_device_fd == -1) { + printf("FD_OSMESA: Failed to open kbase device: %s", strerror(errno)); + } else { + struct pipe_screen_config dummy_cfg = { NULL, NULL }; + screen = fd_screen_create(kbase_device_fd, &dummy_cfg, NULL); + } + } +#endif + return screen ? debug_screen_wrap(screen) : NULL; } diff --git a/src/gallium/drivers/freedreno/freedreno_context.c b/src/gallium/drivers/freedreno/freedreno_context.c index e7f0981514b..333f111ed84 100644 --- a/src/gallium/drivers/freedreno/freedreno_context.c +++ b/src/gallium/drivers/freedreno/freedreno_context.c @@ -498,6 +498,22 @@ fd_get_device_reset_status(struct pipe_context *pctx) return status; } +static enum pipe_reset_status +fd_get_device_reset_status_direct(struct pipe_context *pctx) +{ + struct fd_context *ctx = fd_context(pctx); + enum pipe_reset_status status_list[] = { + [FD_RESET_NO_ERROR] = PIPE_NO_RESET, + [FD_RESET_GUILTY] = PIPE_GUILTY_CONTEXT_RESET, + [FD_RESET_INNOCENT] = PIPE_INNOCENT_CONTEXT_RESET, + [FD_RESET_UNKNOWN] = PIPE_UNKNOWN_CONTEXT_RESET, + }; + enum fd_reset_status fd_status; + ASSERTED int ret = fd_pipe_get_reset_status(ctx->pipe, &fd_status); + assert(!ret); + return status_list[fd_status]; +} + static void fd_trace_record_ts(struct u_trace *ut, void *cs, void *timestamps, unsigned idx, bool end_of_pipe) @@ -663,11 +679,6 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, ctx->in_fence_fd = -1; - if (fd_device_version(screen->dev) >= FD_VERSION_ROBUSTNESS) { - ctx->context_reset_count = fd_get_reset_count(ctx, true); - ctx->global_reset_count = fd_get_reset_count(ctx, false); - } - simple_mtx_init(&ctx->gmem_lock, mtx_plain); /* need some sane default in case gallium frontends don't @@ -682,13 +693,20 @@ fd_context_init(struct fd_context *ctx, struct pipe_screen *pscreen, pctx->flush = fd_context_flush; pctx->emit_string_marker = fd_emit_string_marker; pctx->set_debug_callback = fd_set_debug_callback; - pctx->get_device_reset_status = fd_get_device_reset_status; pctx->create_fence_fd = fd_create_pipe_fence_fd; pctx->fence_server_sync = fd_pipe_fence_server_sync; pctx->fence_server_signal = fd_pipe_fence_server_signal; pctx->texture_barrier = fd_texture_barrier; pctx->memory_barrier = fd_memory_barrier; + if (fd_get_features(screen->dev) & FD_FEATURE_DIRECT_RESET) { + pctx->get_device_reset_status = fd_get_device_reset_status_direct; + } else if(fd_device_version(screen->dev) >= FD_VERSION_ROBUSTNESS) { + ctx->context_reset_count = fd_get_reset_count(ctx, true); + ctx->global_reset_count = fd_get_reset_count(ctx, false); + pctx->get_device_reset_status = fd_get_device_reset_status; + } + pctx->stream_uploader = u_upload_create_default(pctx); if (!pctx->stream_uploader) goto fail; diff --git a/src/gallium/drivers/freedreno/freedreno_public.h b/src/gallium/drivers/freedreno/freedreno_public.h new file mode 100644 index 00000000000..d6779da1b31 --- /dev/null +++ b/src/gallium/drivers/freedreno/freedreno_public.h @@ -0,0 +1,41 @@ +/* + * Copyright (C) 2018 Alyssa Rosenzweig + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#ifndef FD_PUBLIC_H +#define FD_PUBLIC_H + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_screen; +struct pipe_screen_config; +struct renderonly; + +struct pipe_screen *fd_screen_create(int fd, const struct pipe_screen_config *config, struct renderonly *ro); + +#ifdef __cplusplus +} +#endif + +#endif \ No newline at end of file diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 6021e062bd8..c05392e5dc4 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -65,6 +65,7 @@ #include "ir3/ir3_descriptor.h" #include "ir3/ir3_gallium.h" #include "ir3/ir3_nir.h" +#include "freedreno_public.h" /* clang-format off */ static const struct debug_named_value fd_debug_options[] = { @@ -624,6 +625,11 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) return 0; case PIPE_CAP_THROTTLE: return screen->driconf.enable_throttling; + case PIPE_CAP_DMABUF: + if (fd_get_features(screen->dev) & FD_FEATURE_IMPORT_DMABUF) + return DRM_PRIME_CAP_IMPORT; + /* Fallthough to default case */ + FALLTHROUGH; default: return u_pipe_screen_get_param_defaults(pscreen, param); } @@ -1061,7 +1067,7 @@ fd_screen_create(int fd, const struct pipe_screen_config *config, struct renderonly *ro) { - struct fd_device *dev = fd_device_new_dup(fd); + struct fd_device *dev = fd_device_new(fd); if (!dev) return NULL; @@ -1166,24 +1172,10 @@ fd_screen_create(int fd, screen->has_syncobj = fd_has_syncobj(screen->dev); - /* parse driconf configuration now for device specific overrides: */ - driParseConfigFiles(config->options, config->options_info, 0, "msm", - NULL, fd_dev_name(screen->dev_id), NULL, 0, NULL, 0); - - screen->driconf.conservative_lrz = - !driQueryOptionb(config->options, "disable_conservative_lrz"); - screen->driconf.enable_throttling = - !driQueryOptionb(config->options, "disable_throttling"); - struct sysinfo si; sysinfo(&si); screen->ram_size = si.totalram; - DBG("Pipe Info:"); - DBG(" GPU-id: %s", fd_dev_name(screen->dev_id)); - DBG(" Chip-id: 0x%016"PRIx64, screen->chip_id); - DBG(" GMEM size: 0x%08x", screen->gmemsize_bytes); - const struct fd_dev_info *info = fd_dev_info(screen->dev_id); if (!info) { mesa_loge("unsupported GPU: a%03d", screen->gpu_id); @@ -1231,11 +1223,6 @@ fd_screen_create(int fd, if (screen->primtypes[i]) screen->primtypes_mask |= (1 << i); - if (FD_DBG(PERFC)) { - screen->perfcntr_groups = - fd_perfcntrs(screen->dev_id, &screen->num_perfcntr_groups); - } - /* NOTE: don't enable if we have too old of a kernel to support * growable cmdstream buffers, since memory requirement for cmdstream * buffers would be too much otherwise. diff --git a/src/gallium/drivers/freedreno/meson.build b/src/gallium/drivers/freedreno/meson.build index 0d66d2c1836..017e4a3c973 100644 --- a/src/gallium/drivers/freedreno/meson.build +++ b/src/gallium/drivers/freedreno/meson.build @@ -19,6 +19,7 @@ # SOFTWARE. files_libfreedreno = files( + 'freedreno_public.h', 'driinfo_freedreno.h', 'freedreno_autotune.c', 'freedreno_autotune.h', diff --git a/src/gallium/drivers/zink/zink_bo.c b/src/gallium/drivers/zink/zink_bo.c index 7fd2bd4fe43..c25eec4cdae 100644 --- a/src/gallium/drivers/zink/zink_bo.c +++ b/src/gallium/drivers/zink/zink_bo.c @@ -35,7 +35,7 @@ #include "zink_screen.h" #include "util/u_hash_table.h" -#if !defined(__APPLE__) && !defined(_WIN32) +#if !defined(__APPLE__) && !defined(_WIN32) && !defined(__ANDROID__) #define ZINK_USE_DMABUF #include #endif diff --git a/src/gallium/drivers/zink/zink_screen.c b/src/gallium/drivers/zink/zink_screen.c index 0edb8d5f35e..725d2a8f17d 100644 --- a/src/gallium/drivers/zink/zink_screen.c +++ b/src/gallium/drivers/zink/zink_screen.c @@ -269,9 +269,11 @@ disk_cache_init(struct zink_screen *screen) /* Hash in the zink driver build. */ const struct build_id_note *note = build_id_find_nhdr_for_addr(disk_cache_init); - unsigned build_id_len = build_id_length(note); - assert(note && build_id_len == 20); /* sha1 */ - _mesa_sha1_update(&ctx, build_id_data(note), build_id_len); + if (note != NULL) { + unsigned build_id_len = build_id_length(note); + assert(note && build_id_len == 20); /* sha1 */ + _mesa_sha1_update(&ctx, build_id_data(note), build_id_len); + } #endif /* Hash in the Vulkan pipeline cache UUID to identify the combination of @@ -3134,7 +3136,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev u_trace_state_init(); - screen->loader_lib = util_dl_open(VK_LIBNAME); + screen->loader_lib = (void*) strtoul(getenv("VULKAN_PTR"), NULL, 0x10); if (!screen->loader_lib) { mesa_loge("ZINK: failed to load "VK_LIBNAME); goto fail; @@ -3149,15 +3151,6 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev } screen->instance_info.loader_version = zink_get_loader_version(screen); - if (config) { - driParseConfigFiles(config->options, config->options_info, 0, "zink", - NULL, NULL, NULL, 0, NULL, 0); - screen->driconf.dual_color_blend_by_location = driQueryOptionb(config->options, "dual_color_blend_by_location"); - screen->driconf.glsl_correct_derivatives_after_discard = driQueryOptionb(config->options, "glsl_correct_derivatives_after_discard"); - //screen->driconf.inline_uniforms = driQueryOptionb(config->options, "radeonsi_inline_uniforms"); - screen->driconf.emulate_point_smooth = driQueryOptionb(config->options, "zink_emulate_point_smooth"); - screen->driconf.zink_shader_object_enable = driQueryOptionb(config->options, "zink_shader_object_enable"); - } if (!zink_create_instance(screen, dev_major > 0 && dev_major < 255)) goto fail; diff --git a/src/gallium/targets/osmesa/meson.build b/src/gallium/targets/osmesa/meson.build index d16e7858c63..52b2474f61f 100644 --- a/src/gallium/targets/osmesa/meson.build +++ b/src/gallium/targets/osmesa/meson.build @@ -55,11 +55,11 @@ libosmesa = shared_library( libmesa, libgallium, libws_null, osmesa_link_with, ], dependencies : [ - dep_ws2_32, dep_selinux, dep_thread, dep_clock, dep_unwind, driver_swrast + dep_ws2_32, dep_selinux, dep_thread, dep_clock, dep_unwind, driver_freedreno, dep_libdrm, driver_zink ], name_prefix : host_machine.system() == 'windows' ? '' : [], # otherwise mingw will create libosmesa.dll soversion : host_machine.system() == 'windows' ? '' : '8', - version : '8.0.0', + version : '', darwin_versions : '9.0.0', install : true, ) diff --git a/src/util/os_misc.c b/src/util/os_misc.c index c378a9e919f..c0436216388 100644 --- a/src/util/os_misc.c +++ b/src/util/os_misc.c @@ -56,7 +56,6 @@ # define LOG_TAG "MESA" # include # include -# include #elif DETECT_OS_LINUX || DETECT_OS_CYGWIN || DETECT_OS_SOLARIS || DETECT_OS_HURD # include #elif DETECT_OS_OPENBSD || DETECT_OS_FREEBSD @@ -128,62 +127,10 @@ os_log_message(const char *message) #endif } -#if DETECT_OS_ANDROID -# include -# include "c11/threads.h" - -/** - * Get an option value from android's property system, as a fallback to - * getenv() (which is generally less useful on android due to processes - * typically being forked from the zygote. - * - * The option name used for getenv is translated into a property name - * by: - * - * 1) convert to lowercase - * 2) replace '_' with '.' - * 3) if necessary, prepend "mesa." - * - * For example: - * - MESA_EXTENSION_OVERRIDE -> mesa.extension.override - * - GALLIUM_HUD -> mesa.gallium.hud - * - */ -static char * -os_get_android_option(const char *name) -{ - static thread_local char os_android_option_value[PROPERTY_VALUE_MAX]; - char key[PROPERTY_KEY_MAX]; - char *p = key, *end = key + PROPERTY_KEY_MAX; - /* add "mesa." prefix if necessary: */ - if (strstr(name, "MESA_") != name) - p += strlcpy(p, "mesa.", end - p); - p += strlcpy(p, name, end - p); - for (int i = 0; key[i]; i++) { - if (key[i] == '_') { - key[i] = '.'; - } else { - key[i] = tolower(key[i]); - } - } - - int len = property_get(key, os_android_option_value, NULL); - if (len > 1) { - return os_android_option_value; - } - return NULL; -} -#endif - const char * os_get_option(const char *name) { const char *opt = getenv(name); -#if DETECT_OS_ANDROID - if (!opt) { - opt = os_get_android_option(name); - } -#endif return opt; } diff --git a/src/util/perf/cpu_trace.h b/src/util/perf/cpu_trace.h index 6cebb51bafd..d9253c84991 100644 --- a/src/util/perf/cpu_trace.h +++ b/src/util/perf/cpu_trace.h @@ -28,19 +28,6 @@ util_perfetto_trace_end(); \ } while (0) -/* NOTE: for now disable atrace for C++ to workaround a ndk bug with ordering - * between stdatomic.h and atomic.h. See: - * - * https://github.com/android/ndk/issues/1178 - */ -#elif defined(ANDROID) && !defined(__cplusplus) - -#include - -#define _MESA_TRACE_BEGIN(name) \ - atrace_begin(ATRACE_TAG_GRAPHICS, name) -#define _MESA_TRACE_END() atrace_end(ATRACE_TAG_GRAPHICS) - #else #define _MESA_TRACE_BEGIN(name) diff --git a/src/util/u_debug_stack_android.cpp b/src/util/u_debug_stack_android.cpp index 4481771baf9..f17f4f3ad8e 100644 --- a/src/util/u_debug_stack_android.cpp +++ b/src/util/u_debug_stack_android.cpp @@ -25,8 +25,6 @@ #if WITH_LIBBACKTRACE -#include - #include "util/simple_mtx.h" #include "util/u_debug.h" #include "util/hash_table.h" @@ -55,56 +53,12 @@ debug_backtrace_capture(debug_stack_frame *backtrace, unsigned start_frame, unsigned nr_frames) { - Backtrace *bt; - - if (!nr_frames) - return; - - bt = Backtrace::Create(BACKTRACE_CURRENT_PROCESS, - BACKTRACE_CURRENT_THREAD); - if (bt == NULL) { - for (unsigned i = 0; i < nr_frames; i++) - backtrace[i].procname = NULL; - return; - } - - /* Add one to exclude this call. Unwind already ignores itself. */ - bt->Unwind(start_frame + 1); - - simple_mtx_lock(&table_mutex); - - for (unsigned i = 0; i < nr_frames; i++) { - const backtrace_frame_data_t* frame = bt->GetFrame(i); - if (frame) { - backtrace[i].procname = intern_symbol(frame->func_name.c_str()); - backtrace[i].start_ip = frame->pc; - backtrace[i].off = frame->func_offset; - backtrace[i].map = intern_symbol(frame->map.Name().c_str()); - backtrace[i].map_off = frame->rel_pc; - } else { - backtrace[i].procname = NULL; - } - } - - simple_mtx_unlock(&table_mutex); - - delete bt; } void debug_backtrace_dump(const debug_stack_frame *backtrace, unsigned nr_frames) { - for (unsigned i = 0; i < nr_frames; i++) { - if (backtrace[i].procname) - debug_printf( - "%s(+0x%x)\t%012" PRIx64 ": %s+0x%x\n", - backtrace[i].map, - backtrace[i].map_off, - backtrace[i].start_ip, - backtrace[i].procname, - backtrace[i].off); - } } void @@ -112,16 +66,6 @@ debug_backtrace_print(FILE *f, const debug_stack_frame *backtrace, unsigned nr_frames) { - for (unsigned i = 0; i < nr_frames; i++) { - if (backtrace[i].procname) - fprintf(f, - "%s(+0x%x)\t%012" PRIx64 ": %s+0x%x\n", - backtrace[i].map, - backtrace[i].map_off, - backtrace[i].start_ip, - backtrace[i].procname, - backtrace[i].off); - } } #else