From 0cc65093e3f8837957fe3b5f627747b5d89cef79 Mon Sep 17 00:00:00 2001 From: yellows8 Date: Mon, 13 Nov 2017 23:27:54 -0500 Subject: [PATCH] Implemented the ioctls which were skipped during nvgfx init. nvgfx init adjustments. Fixed ioctl direction define for nvioctlNvhostAsGpu_MapBufferEx, this now works properly. --- nx/include/switch/gfx/nvioctl.h | 11 +++++ nx/source/gfx/nvgfx.c | 51 +++++++++++++--------- nx/source/gfx/nvioctl.c | 76 ++++++++++++++++++++++++++++++++- 3 files changed, 117 insertions(+), 21 deletions(-) diff --git a/nx/include/switch/gfx/nvioctl.h b/nx/include/switch/gfx/nvioctl.h index f3695d66..cefb906f 100644 --- a/nx/include/switch/gfx/nvioctl.h +++ b/nx/include/switch/gfx/nvioctl.h @@ -36,10 +36,21 @@ typedef struct { u64 gr_compbit_store_base_hw; // 0x0 (not supported) } gpu_characteristics; +typedef struct { + u64 offset; + u32 page_size; + u32 pad; + u64 pages; +} nvioctl_va_region; + +Result nvioctlNvhostCtrlGpu_ZCullGetCtxSize(u32 fd, u32 *out); +Result nvioctlNvhostCtrlGpu_ZCullGetInfo(u32 fd, u32 out[40>>2]); Result nvioctlNvhostCtrlGpu_GetCharacteristics(u32 fd, gpu_characteristics *out); +Result nvioctlNvhostCtrlGpu_GetTpcMasks(u32 fd, u32 inval, u32 out[24>>2]); Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align, u64 *offset); Result nvioctlNvhostAsGpu_MapBufferEx(u32 fd, u32 flags, u32 kind, u32 nvmap_handle, u32 page_size, u64 buffer_offset, u64 mapping_size, u64 *offset); +Result nvioctlNvhostAsGpu_GetVARegions(u32 fd, nvioctl_va_region regions[2]); Result nvioctlNvhostAsGpu_InitializeEx(u32 fd, u32 big_page_size); Result nvioctlNvmap_Create(u32 fd, u32 size, u32 *nvmap_handle); diff --git a/nx/source/gfx/nvgfx.c b/nx/source/gfx/nvgfx.c index 0066734d..1fffa6ba 100644 --- a/nx/source/gfx/nvgfx.c +++ b/nx/source/gfx/nvgfx.c @@ -6,10 +6,14 @@ static bool g_nvgfxInitialized = 0; static u32 g_nvgfx_fd_nvhostctrlgpu; static u32 g_nvgfx_fd_nvhostasgpu; static u32 g_nvgfx_fd_nvmap; -static u32 g_nvgfx_nvmapobj; +static u32 g_nvgfx_nvmapobj0; static gpu_characteristics g_nvgfx_gpu_characteristics; static u64 g_nvgfx_nvhostasgpu_allocspace_offset; +static u32 g_nvgfx_tpcmasks[24>>2]; +static u32 g_nvgfx_zcullctxsize; +static u32 g_nvgfx_zcullinfo[40>>2]; +static nvioctl_va_region g_nvgfx_nvhostasgpu_varegions[2]; static u8 *g_nvgfx_nvmap_mem; size_t g_nvgfx_nvmap_mem_size; @@ -21,16 +25,21 @@ Result nvgfxInitialize(void) { g_nvgfx_fd_nvhostctrlgpu = 0; g_nvgfx_fd_nvhostasgpu = 0; g_nvgfx_fd_nvmap = 0; - g_nvgfx_nvmapobj = 0; + g_nvgfx_nvmapobj0 = 0; memset(&g_nvgfx_gpu_characteristics, 0, sizeof(gpu_characteristics)); + memset(g_nvgfx_tpcmasks, 0, sizeof(g_nvgfx_tpcmasks)); + memset(g_nvgfx_zcullinfo, 0, sizeof(g_nvgfx_zcullinfo)); + memset(g_nvgfx_nvhostasgpu_varegions, 0, sizeof(g_nvgfx_nvhostasgpu_varegions)); g_nvgfx_nvhostasgpu_allocspace_offset = 0; + g_nvgfx_zcullctxsize = 0; - g_nvgfx_nvmap_mem_size = 0x10000; + g_nvgfx_nvmap_mem_size = 0x1000; if (R_SUCCEEDED(rc)) { g_nvgfx_nvmap_mem = memalign(0x1000, g_nvgfx_nvmap_mem_size); if (g_nvgfx_nvmap_mem==NULL) rc = MAKERESULT(MODULE_LIBNX, LIBNX_OUTOFMEM); + if (R_SUCCEEDED(rc)) memset(g_nvgfx_nvmap_mem, 0, g_nvgfx_nvmap_mem_size); } //Officially NVHOST_IOCTL_CTRL_GET_CONFIG is used a lot (here and later), skip that. @@ -38,36 +47,38 @@ Result nvgfxInitialize(void) { if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvhostctrlgpu, "/dev/nvhost-ctrl-gpu"); if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_GetCharacteristics(g_nvgfx_fd_nvhostctrlgpu, &g_nvgfx_gpu_characteristics); - //Officially NVGPU_GPU_IOCTL_GET_TPC_MASKS is used here. + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_GetTpcMasks(g_nvgfx_fd_nvhostctrlgpu, 4, g_nvgfx_tpcmasks); - //Officially NVGPU_GPU_IOCTL_ZCULL_GET_CTX_SIZE and NVGPU_GPU_IOCTL_ZCULL_GET_INFO are used here. + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_ZCullGetCtxSize(g_nvgfx_fd_nvhostctrlgpu, &g_nvgfx_zcullctxsize); + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostCtrlGpu_ZCullGetInfo(g_nvgfx_fd_nvhostctrlgpu, g_nvgfx_zcullinfo); if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvhostasgpu, "/dev/nvhost-as-gpu"); if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_InitializeEx(g_nvgfx_fd_nvhostasgpu, 1); - //NVGPU_AS_IOCTL_GET_VA_REGIONS twice - - if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_AllocSpace(g_nvgfx_fd_nvhostasgpu, 0x10000, 0x1000, 0, 0x1000, &g_nvgfx_nvhostasgpu_allocspace_offset); + //Officially this is used twice here - only use it once here. + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_GetVARegions(g_nvgfx_fd_nvhostasgpu, g_nvgfx_nvhostasgpu_varegions); + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_AllocSpace(g_nvgfx_fd_nvhostasgpu, 0x10000, 0x20000, 0, 0x10000, &g_nvgfx_nvhostasgpu_allocspace_offset); if (R_SUCCEEDED(rc)) rc = nvOpen(&g_nvgfx_fd_nvmap, "/dev/nvmap"); - if (R_SUCCEEDED(rc)) rc = nvioctlNvmap_Create(g_nvgfx_fd_nvmap, g_nvgfx_nvmap_mem_size, &g_nvgfx_nvmapobj); + if (R_SUCCEEDED(rc)) rc = nvioctlNvmap_Create(g_nvgfx_fd_nvmap, g_nvgfx_nvmap_mem_size, &g_nvgfx_nvmapobj0); - if (R_SUCCEEDED(rc)) rc = nvioctlNvmap_Alloc(g_nvgfx_fd_nvmap, g_nvgfx_nvmapobj, 0, 0, 0x20000, 0, g_nvgfx_nvmap_mem); + if (R_SUCCEEDED(rc)) rc = nvioctlNvmap_Alloc(g_nvgfx_fd_nvmap, g_nvgfx_nvmapobj0, 0, 0, 0x20000, 0, g_nvgfx_nvmap_mem); - //Currently broken. - if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_MapBufferEx(g_nvgfx_fd_nvhostasgpu, 4, 0, g_nvgfx_nvmapobj, 0x1000, 0, g_nvgfx_nvmap_mem_size, NULL); - if (R_SUCCEEDED(rc)) rc = -1; - if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_MapBufferEx(g_nvgfx_fd_nvhostasgpu, 4, 0xfe, g_nvgfx_nvmapobj, 0x1000, 0, g_nvgfx_nvmap_mem_size, NULL); + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_MapBufferEx(g_nvgfx_fd_nvhostasgpu, 0, 0, g_nvgfx_nvmapobj0, 0x10000, 0, 0, NULL); + if (R_SUCCEEDED(rc)) rc = nvioctlNvhostAsGpu_MapBufferEx(g_nvgfx_fd_nvhostasgpu, 0, 0xfe, g_nvgfx_nvmapobj0, 0x10000, 0, 0, NULL); + //if (R_SUCCEEDED(rc)) rc = -1; - if (R_FAILED(rc)) nvClose(g_nvgfx_fd_nvmap); - if (R_FAILED(rc)) nvClose(g_nvgfx_fd_nvhostasgpu); - if (R_FAILED(rc)) nvClose(g_nvgfx_fd_nvhostctrlgpu); + if (R_FAILED(rc)) { + nvClose(g_nvgfx_fd_nvmap); + nvClose(g_nvgfx_fd_nvhostasgpu); + nvClose(g_nvgfx_fd_nvhostctrlgpu); - if (g_nvgfx_nvmap_mem) { - free(g_nvgfx_nvmap_mem); - g_nvgfx_nvmap_mem = NULL; + if (g_nvgfx_nvmap_mem) { + free(g_nvgfx_nvmap_mem); + g_nvgfx_nvmap_mem = NULL; + } } if (R_SUCCEEDED(rc)) g_nvgfxInitialized = 1; diff --git a/nx/source/gfx/nvioctl.c b/nx/source/gfx/nvioctl.c index 7cdd6c25..27e84bf1 100644 --- a/nx/source/gfx/nvioctl.c +++ b/nx/source/gfx/nvioctl.c @@ -1,6 +1,40 @@ #include #include +Result nvioctlNvhostCtrlGpu_ZCullGetCtxSize(u32 fd, u32 *out) { + Result rc = 0; + + struct { + u32 out; + } data; + + memset(&data, 0, sizeof(data)); + + rc = nvIoctl(fd, _IOR(0x47, 0x01, data), &data); + if (R_FAILED(rc)) return rc; + + *out = data.out; + + return rc; +} + +Result nvioctlNvhostCtrlGpu_ZCullGetInfo(u32 fd, u32 out[40>>2]) { + Result rc = 0; + + struct { + u32 out[40>>2]; + } data; + + memset(&data, 0, sizeof(data)); + + rc = nvIoctl(fd, _IOR(0x47, 0x02, data), &data); + if (R_FAILED(rc)) return rc; + + memcpy(out, data.out, sizeof(data.out)); + + return rc; +} + Result nvioctlNvhostCtrlGpu_GetCharacteristics(u32 fd, gpu_characteristics *out) { Result rc = 0; @@ -22,6 +56,25 @@ Result nvioctlNvhostCtrlGpu_GetCharacteristics(u32 fd, gpu_characteristics *out) return rc; } +Result nvioctlNvhostCtrlGpu_GetTpcMasks(u32 fd, u32 inval, u32 out[24>>2]) { + Result rc = 0; + + struct { + u32 unk[24>>2]; + } data; + + memset(&data, 0, sizeof(data)); + data.unk[0] = inval; + data.unk[2] = 1;//addr? + + rc = nvIoctl(fd, _IOWR(0x47, 0x06, data), &data); + if (R_FAILED(rc)) return rc; + + memcpy(out, &data.unk, sizeof(data.unk)); + + return rc; +} + Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align, u64 *offset) { Result rc=0; @@ -71,7 +124,7 @@ Result nvioctlNvhostAsGpu_MapBufferEx(u32 fd, u32 flags, u32 kind, u32 nvmap_han data.buffer_offset = buffer_offset; data.mapping_size = mapping_size; - rc = nvIoctl(fd, _IOW(0x41, 0x06, data), &data); + rc = nvIoctl(fd, _IOWR(0x41, 0x06, data), &data); if (R_FAILED(rc)) return rc; if (offset) *offset = data.offset; @@ -79,6 +132,27 @@ Result nvioctlNvhostAsGpu_MapBufferEx(u32 fd, u32 flags, u32 kind, u32 nvmap_han return rc; } +Result nvioctlNvhostAsGpu_GetVARegions(u32 fd, nvioctl_va_region regions[2]) { + Result rc=0; + + struct { + u64 not_used; // (contained output user ptr on linux, ignored) + u32 bufsize; //inout forced to 2*sizeof(struct va_region) + u32 pad; + nvioctl_va_region regions[2];//out + } data; + + memset(&data, 0, sizeof(data)); + data.bufsize = sizeof(data.regions); + + rc = nvIoctl(fd, _IOWR(0x41, 0x08, data), &data); + if (R_FAILED(rc)) return rc; + + memcpy(regions, data.regions, sizeof(data.regions)); + + return rc; +} + Result nvioctlNvhostAsGpu_InitializeEx(u32 fd, u32 big_page_size) { struct { u32 big_page_size; // depends on GPU's available_big_page_sizes; 0=default