From 089572cf1d6104bc1308e82f9619b522495a31df Mon Sep 17 00:00:00 2001 From: Billy Laws Date: Sat, 6 May 2023 14:42:58 +0100 Subject: [PATCH] Rework memory import API --- include/adrenotools/driver.h | 9 ++++---- src/driver.cpp | 41 ++++++++++++++++++++++++------------ 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/include/adrenotools/driver.h b/include/adrenotools/driver.h index b0a1b4a..14fc0ba 100644 --- a/include/adrenotools/driver.h +++ b/include/adrenotools/driver.h @@ -18,23 +18,24 @@ extern "C" { * @param customDriverDir The directory to load a custom GPU driver named according to `customDriverName` from. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags` * @param customDriverName The soname of the custom driver to load. Only used if ADRENOTOOLS_DRIVER_CUSTOM is set in `featureFlags` * @param fileRedirectDir The directory which to redirect all file accesses performed by the driver to. Only used if ADRENOTOOLS_DRIVER_FILE_REDIRECT is set in `featureFlags` + * @param userMappingHandle A pointer to a void* which will be set to the mapping handle if ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT is set in `featureFlags` */ -void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, adrenotools_gpu_mapping *nextGpuMapping); +void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *tmpLibDir, const char *hookLibDir, const char *customDriverDir, const char *customDriverName, const char *fileRedirectDir, void **userMappingHandle); /** * @brief Imports the given CPU mapped memory range into the GSL allocator. The out_mapping should have been passed to adrenotools_open_libvulkan with ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT set in `featureFlags`. This should then be followed by a call to vkAllocateMemory with a matching size which will return a VkDeviceMemory view over the input region - * @param outMapping Output mapping pointer, the same as was passed to adrenotools_open_libvulkan + * @param handle Mapping handle that was returned by adrenotools_open_libvulkan * @param hostPtr The host pointer to import * @param size The size of the region to import * @return True on success */ -bool adrenotools_import_user_mem(adrenotools_gpu_mapping *outMapping, void *hostPtr, uint64_t size); +bool adrenotools_import_user_mem(void *handle, void *hostPtr, uint64_t size); /** * @note This function should be called after adrenotools_open_libvulkan and Vulkan driver init to check if the mapping import hook loaded successfully * @return True if the mapping was successfully imported (or initialization succeeded) */ -bool adrenotools_validate_gpu_mapping(adrenotools_gpu_mapping *mapping); +bool adrenotools_validate_gpu_mapping(void *handle); /** * @brief Provides a way to force the GPU to run at the maximum possible clocks (thermal constraints will still be applied) diff --git a/src/driver.cpp b/src/driver.cpp index 04b7085..435b787 100644 --- a/src/driver.cpp +++ b/src/driver.cpp @@ -15,7 +15,7 @@ #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, adrenotools_gpu_mapping *nextGpuMapping) { +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; @@ -31,7 +31,7 @@ void *adrenotools_open_libvulkan(int dlopenFlags, int featureFlags, const char * if (!(featureFlags & ADRENOTOOLS_DRIVER_CUSTOM) && (customDriverDir || customDriverName)) return nullptr; - if (!(featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) && nextGpuMapping) + if (!(featureFlags & ADRENOTOOLS_DRIVER_GPU_MAPPING_IMPORT) && userMappingHandle) return nullptr; // Verify that params for enabled features are correct @@ -71,7 +71,19 @@ void *adrenotools_open_libvulkan(int dlopenFlags, int featureFlags, const char * if (!initHookParam) return nullptr; - initHookParam(new HookImplParams(featureFlags, tmpLibDir, hookLibDir, customDriverDir, customDriverName, fileRedirectDir, nextGpuMapping)); + + 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)) @@ -80,12 +92,14 @@ void *adrenotools_open_libvulkan(int dlopenFlags, int featureFlags, const char * return linkernsbypass_namespace_dlopen_unique("/system/lib64/libvulkan.so", tmpLibDir, dlopenFlags, hookNs); } -bool adrenotools_import_user_mem(adrenotools_gpu_mapping *outMapping, void *hostPtr, uint64_t size) { +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 user_mem_import{ + kgsl_gpuobj_import userMemImport{ .priv = reinterpret_cast(&addr), .priv_len = size, .flags = KGSL_CACHEMODE_WRITEBACK << KGSL_CACHEMODE_SHIFT | KGSL_MEMFLAGS_IOCOHERENT, @@ -99,19 +113,19 @@ bool adrenotools_import_user_mem(adrenotools_gpu_mapping *outMapping, void *host if (kgslFd < 0) return false; - int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_IMPORT, &user_mem_import)}; + int ret{ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_IMPORT, &userMemImport)}; if (ret) goto err; - info.id = user_mem_import.id; + info.id = userMemImport.id; ret = ioctl(kgslFd, IOCTL_KGSL_GPUOBJ_INFO, &info); if (ret) goto err; - outMapping->host_ptr = hostPtr; - outMapping->gpu_addr = info.gpuaddr; - outMapping->size = size; - outMapping->flags = 0xc2600; //!< Unknown flags, but they are required for the mapping to work + 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; @@ -121,8 +135,9 @@ err: return false; } -bool adrenotools_validate_gpu_mapping(adrenotools_gpu_mapping *mapping) { - return mapping->gpu_addr == ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC; +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) {