From 6c655321e6b04b8648802e296bb5ca11d290ae68 Mon Sep 17 00:00:00 2001 From: swurl Date: Sat, 31 May 2025 02:33:02 -0400 Subject: Move dead submodules in-tree Signed-off-by: swurl --- externals/libadrenotools/src/driver.cpp | 210 ++++++++++++++++++++++++++++++++ 1 file changed, 210 insertions(+) create mode 100644 externals/libadrenotools/src/driver.cpp (limited to 'externals/libadrenotools/src/driver.cpp') diff --git a/externals/libadrenotools/src/driver.cpp b/externals/libadrenotools/src/driver.cpp new file mode 100644 index 0000000000..4ddee4aaa4 --- /dev/null +++ b/externals/libadrenotools/src/driver.cpp @@ -0,0 +1,210 @@ +// SPDX-License-Identifier: BSD-2-Clause +// Copyright © 2021 Billy Laws + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hook/kgsl.h" +#include "hook/hook_impl_params.h" +#include +#include + +void *adrenotools_open_libvulkan(int dlopenFlags, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, void **userMappingHandle) { + // Bail out if linkernsbypass failed to load, this probably means we're on api < 28 + if (!linkernsbypass_load_status()) + return nullptr; + + // Always use memfd on Q+ since it's guaranteed to work + if (android_get_device_api_level() >= 29) + tmpLibDir = nullptr; + + // Verify that params for specific features are only passed if they are enabled + if (!(featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) && fileRedirectDir) + return nullptr; + + if (!(featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) && (customDriverDir || customDriverName)) + return nullptr; + + if (!(featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) && userMappingHandle) + return nullptr; + + // Verify that params for enabled features are correct + struct stat buf{}; + + if (featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) { + if (!customDriverName || !customDriverDir) + return nullptr; + + if (stat((std::string(customDriverDir) + customDriverName).c_str(), &buf) != 0) + return nullptr; + } + + // Verify that params for enabled features are correct + if (featureFlags & ADRENOTOOLS_DRIVER_FILE_REDIRECT) { + if (!fileRedirectDir) + return nullptr; + + if (stat(fileRedirectDir, &buf) != 0) + return nullptr; + } + + // Create a namespace that can isolate our hook from the classloader namespace + auto hookNs{android_create_namespace("adrenotools-libvulkan", hookLibDir, nullptr, ANDROID_NAMESPACE_TYPE_SHARED, nullptr, nullptr)}; + + // Link it to the default namespace so the hook can use libandroid etc + if (!linkernsbypass_link_namespace_to_default_all_libs(hookNs)) + return nullptr; + + // Preload the hook implementation, otherwise we get a weird issue where despite being in NEEDED of the hook lib the hook's symbols will overwrite ours and cause an infinite loop + auto hookImpl{linkernsbypass_namespace_dlopen("libhook_impl.so", RTLD_NOW, hookNs)}; + if (!hookImpl) + return nullptr; + + // Pass parameters to the hook implementation + auto initHookParam{reinterpret_cast(dlsym(hookImpl, "init_hook_param"))}; + if (!initHookParam) + return nullptr; + + + auto importMapping{[&]() -> adrenotools_gpu_mapping * { + if (featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) { + // This will be leaked, but it's not a big deal since it's only a few bytes + adrenotools_gpu_mapping *mapping{new adrenotools_gpu_mapping{}}; + *userMappingHandle = mapping; + return mapping; + } else { + return nullptr; + } + }()}; + + initHookParam(new HookImplParams(featureFlags, tmpLibDir, hookLibDir, customDriverDir, customDriverName, fileRedirectDir, importMapping)); + + // Load the libvulkan hook into the isolated namespace + if (!linkernsbypass_namespace_dlopen("libmain_hook.so", RTLD_GLOBAL, hookNs)) + return nullptr; + + return linkernsbypass_namespace_dlopen_unique("/system/lib64/libvulkan.so", tmpLibDir, dlopenFlags, hookNs); +} + +bool adrenotools_import_user_mem(void *handle, void *hostPtr, uint64_t size) { + auto importMapping{reinterpret_cast(handle)}; + + kgsl_gpuobj_import_useraddr addr{ + .virtaddr = reinterpret_cast(hostPtr), + }; + + kgsl_gpuobj_import userMemImport{ + .priv = reinterpret_cast(&addr), + .priv_len = size, + .flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT, + .type = KGSL_USER_MEM_TYPE_ADDR, + + }; + + kgsl_gpuobj_info info{}; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return false; + + int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_IMPORT, &userMemImport)}; + if (ret) + goto err; + + info.id = userMemImport.id; + ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info); + if (ret) + goto err; + + importMapping->host_ptr = hostPtr; + importMapping->gpu_addr = info.gpuaddr; + importMapping->size = size; + importMapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work + + close(kgslFd); + return true; + +err: + close(kgslFd); + return false; +} + +bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size) { + auto mapping{reinterpret_cast(handle)}; + + kgsl_gpuobj_alloc gpuobjAlloc{ + .size = *size, + .flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT, + }; + + kgsl_gpuobj_info info{}; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return false; + + int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_ALLOC, &gpuobjAlloc)}; + if (ret) + goto err; + + *size = gpuobjAlloc.mmapsize; + + info.id = gpuobjAlloc.id; + + ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info); + if (ret) + goto err; + + mapping->host_ptr = nullptr; + mapping->gpu_addr = info.gpuaddr; + mapping->size = *size; + mapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work + + close(kgslFd); + return true; + +err: + close(kgslFd); + return false; +} + + +bool adrenotools_mem_cpu_map(void *handle, void *hostPtr, uint64_t size) { + auto mapping{reinterpret_cast(handle)}; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return false; + + mapping->host_ptr = mmap(hostPtr, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, kgslFd, mapping->gpu_addr); + close(kgslFd); + return mapping->host_ptr != nullptr; +} + +bool adrenotools_validate_gpu_mapping(void *handle) { + auto importMapping{reinterpret_cast(handle)}; + return importMapping->gpu_addr == ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC; +} + +void adrenotools_set_turbo(bool turbo) { + uint32_t enable{turbo ? 0U : 1U}; + kgsl_device_getproperty prop{ + .type = KGSL_PROP_PWRCTRL, + .value = reinterpret_cast(&enable), + .sizebytes = sizeof(enable), + }; + + int kgslFd{open("/dev/kgsl-3d0", O_RDWR)}; + if (kgslFd < 0) + return; + + ioctl(kgslFd, IOCTL_KGSL_SETPROPERTY, &prop); + close (kgslFd); +} -- cgit v1.2.3