Introduce new API for placed memory allocations

Useful for WOW64, where allocations need to be done in the lower 32-bits
of the AS.
This commit is contained in:
Billy Laws 2023-06-30 18:04:16 +01:00
parent a5dfbe8b4f
commit c4bc94c03e
3 changed files with 71 additions and 2 deletions

View file

@ -24,7 +24,7 @@ extern "C" {
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
* @brief Imports the given CPU mapped memory range into the GSL allocator. 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 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
@ -32,6 +32,22 @@ void *adrenotools_open_libvulkan(int dlopenMode, int featureFlags, const char *t
*/
bool adrenotools_import_user_mem(void *handle, void *hostPtr, uint64_t size);
/**
* @brief Maps GPU memory and imports it into the GSL allocator. This should then be followed by a call to adrenotools_mem_cpu_map to map the memory on the CPU, then finally vkAllocateMemory with a matching size
* @param handle Mapping handle that was returned by adrenotools_open_libvulkan
* @param size Pointer to a variable containing the size of the region to import, will be updated to contain the required size of the region to allocate CPU side
* @return true on success
*/
bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size);
/**
* @brief Maps the last mapping allocated using adrenotools_mem_gpu_allocate into the given host memory region, such that vkAllocateMemory can then be called
* @param handle Mapping handle that was returned by adrenotools_open_libvulkan
* @param hostPtr A pointer to where the mapping should be mapped
* @param size The size of the mapping. MUST be equal to the size returned by adrenotools_mem_gpu_allocate
*/
bool adrenotools_mem_cpu_map(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)

View file

@ -5,6 +5,7 @@
#include <string_view>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <dlfcn.h>
#include <fcntl.h>
#include <android/api-level.h>
@ -135,6 +136,58 @@ err:
return false;
}
bool adrenotools_mem_gpu_allocate(void *handle, uint64_t *size) {
auto mapping{reinterpret_cast<adrenotools_gpu_mapping *>(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<adrenotools_gpu_mapping *>(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<adrenotools_gpu_mapping *>(handle)};
return importMapping->gpu_addr == ADRENOTOOLS_GPU_MAPPING_SUCCEEDED_MAGIC;

View file

@ -12,7 +12,7 @@ extern "C" {
void init_hook_param(const void *param);
void init_gsl(void *alloc, void *free);
void init_gsl(void *alloc, void *alloc64, void *free);
void *hook_android_dlopen_ext(const char *filename, int flags, const android_dlextinfo *extinfo);