From 8afcff21ee9d5fb1a17360858a496244ac218c1e Mon Sep 17 00:00:00 2001 From: Lucas Fryzek Date: Sun, 21 Jul 2024 00:12:12 +0100 Subject: drvemu: Implement device memory allocation --- src/drvemu.c | 116 ++++++++++++++++++++++++++++++++++++++++++++++------------- 1 file changed, 91 insertions(+), 25 deletions(-) (limited to 'src') diff --git a/src/drvemu.c b/src/drvemu.c index 3188ec1..1d64b9f 100644 --- a/src/drvemu.c +++ b/src/drvemu.c @@ -58,6 +58,7 @@ #define MAX_ALLOCATIONS 1024 +#define ARRAY_SIZE(x) ((sizeof x) / (sizeof *x)) #define STR_DETAIL(x) #x #define STR(x) STR_DETAIL(x) #define LOG(msg...) fprintf(stderr, "[DRVEMU] " msg) @@ -75,30 +76,6 @@ static struct memory_allocation allocations[MAX_ALLOCATIONS]; static int false_fd = 10241024; -static int alloc_memory(int heap, size_t size) { - for (size_t i = 0; i < MAX_ALLOCATIONS; i++) { - if (!allocations[i].allocated) { - struct memory_allocation *mem = &allocations[i]; - mem->allocated = true; - // TODO use heaps to get right device addr - mem->device_ptr = 0; - mem->cpu_ptr = malloc(size); - mem->size = size; - return i+1; - } - } - - assert(0); - return -1; -} - -#define create_handle(size, msg) create_handle_helper((size), (msg), __FILE__, __LINE__) -static void *create_handle_helper(int size, const char *msg, const char *file, int line) { - int handle = alloc_memory(0, size); // TODO handle heap correctly here; - LOG("%s:%d Creating handle 0x%x for %s\n", file, line, handle, msg); - return (void*)handle; -} - #define PROLOG(func) \ static typeof(func) *orig_##func = NULL; \ if(!orig_##func) \ @@ -138,6 +115,21 @@ int fcntl(int fd, int op, int arg) { return orig_fcntl(fd, op, arg); } +static const char *pvr_heap_names[] = { + "DRVEMU_INTERNAL", + "SGX_GENERAL_HEAP", + "SGX_TADATA_HEAP", + "SGX_KERNEL_CODE_HEAP", + "SGX_KERNEL_DATA_HEAP", + "SGX_PIXELSHADER_HEAP", + "SGX_VERTEXSHADER_HEAP", + "SGX_PDSPIXEL_CODEDATA_HEAP", + "SGX_PDSVERTEX_CODEDATA_HEAP", + "SGX_SYNCINFO_HEAP", + "SGX_SHARED_3DPARAMETERS_HEAP", + "SGX_PERCONTEXT_3DPARAMETERS_HEAP" +}; + PVRSRV_HEAP_INFO pvr_heaps[] = { { .ui32HeapID = HEAP_ID( PVRSRV_DEVICE_TYPE_SGX, SGX_GENERAL_HEAP_ID), @@ -218,6 +210,49 @@ PVRSRV_HEAP_INFO pvr_heaps[] = { }, }; +static int alloc_memory(int heap_id, size_t size) { + for (size_t i = 0; i < MAX_ALLOCATIONS; i++) { + if (!allocations[i].allocated) { + struct memory_allocation *mem = &allocations[i]; + mem->allocated = true; + // If heap is 0 that is for internal allocs + if (heap_id != 0) { + assert((heap_id-1) < ARRAY_SIZE(pvr_heaps)); + PVRSRV_HEAP_INFO *heap = &pvr_heaps[heap_id-1]; + mem->device_ptr = heap->sDevVAddrBase.uiAddr; + heap->sDevVAddrBase.uiAddr += size; + } else { + mem->device_ptr = 0; + } + mem->cpu_ptr = malloc(size); + mem->size = size; + return i+1; + } + } + + assert(0); + return -1; +} + +static struct memory_allocation *alloc_sync(PVRSRV_CLIENT_SYNC_INFO *sync) { + int handle = alloc_memory(0, 1024); + struct memory_allocation *alloc = &allocations[handle-1]; + sync->hMappingInfo = (void*)handle; + sync->psSyncData = (void*)alloc; + sync->sWriteOpsCompleteDevVAddr.uiAddr = handle; + sync->sReadOpsCompleteDevVAddr.uiAddr = handle; + sync->sReadOps2CompleteDevVAddr.uiAddr = handle; + sync->hKernelSyncInfo = sync->hMappingInfo; + return alloc; +} + +#define create_handle(size, msg) create_handle_helper((size), (msg), __FILE__, __LINE__) +static void *create_handle_helper(int size, const char *msg, const char *file, int line) { + int handle = alloc_memory(0, size); // TODO handle heap correctly here; + LOG("%s:%d Creating handle 0x%x for %s\n", file, line, handle, msg); + return (void*)handle; +} + #define DEV_NAME "pvr" #define DEV_DATE "20110701" #define DEV_DESC "Imagination Technologies PVR DRM" @@ -484,6 +519,37 @@ static bool pvrsrv_ioctl(int fd, PVRSRV_BRIDGE_PACKAGE *bridge_package) { memcpy(out->sHeapInfo, pvr_heaps, sizeof(pvr_heaps)); break; } + case _IOC_NR(PVRSRV_BRIDGE_ALLOC_DEVICEMEM): { + PVRSRV_BRIDGE_IN_ALLOCDEVICEMEM *in = bridge_package->pvParamIn; + PVRSRV_BRIDGE_OUT_ALLOCDEVICEMEM *out = bridge_package->pvParamOut; + out->eError = PVRSRV_OK; + int handle = alloc_memory((int)in->hDevMemHeap, in->uSize); + struct memory_allocation *alloc = &allocations[handle-1]; + out->psKernelMemInfo = (void*)alloc; + out->sClientMemInfo.pvLinAddr = alloc->cpu_ptr; + out->sClientMemInfo.pvLinAddrKM = alloc->cpu_ptr; + out->sClientMemInfo.sDevVAddr.uiAddr = alloc->device_ptr; + // TODO missing flags + out->sClientMemInfo.uAllocSize = alloc->size; + // TODO missing sync + out->sClientMemInfo.hMappingInfo = (void*)handle; + out->sClientMemInfo.hKernelMemInfo = (void*)handle; + out->sClientMemInfo.hResItem = (void*)handle; + out->sClientMemInfo.psNext = NULL; + + + if (in->ui32Attribs & PVRSRV_MEM_NO_SYNCOBJ) { + out->sClientMemInfo.psClientSyncInfo = NULL; + } else { + struct memory_allocation *sync = alloc_sync(&out->sClientSyncInfo); + out->sClientMemInfo.psClientSyncInfo = (void*)sync; + } + + LOG("Allocated 0x%x at 0x%x:0x%x from %s\n", + alloc->size, (uintptr_t)alloc->cpu_ptr, + alloc->device_ptr, pvr_heap_names[(int)in->hDevMemHeap]); + break; + } case _IOC_NR(PVRSRV_BRIDGE_DISCONNECT_SERVICES): case _IOC_NR(PVRSRV_BRIDGE_SGX_RELEASECLIENTINFO): case _IOC_NR(PVRSRV_BRIDGE_CLOSE_DISPCLASS_DEVICE): @@ -587,7 +653,7 @@ int ioctl(int fd, int request, ...) { va_end(args); } - LOG("Got ioctl %d!\n", fd); + //LOG("Got ioctl %d!\n", fd); if (pvr) return spoof_ioctl(fd, request, ptr); -- cgit