From 04751087ca41b3f83767eda0b99910c1fba748cf Mon Sep 17 00:00:00 2001 From: plutooo Date: Mon, 26 Feb 2018 05:27:55 +0100 Subject: [PATCH] Stylechanges to binder, and implemented gpu address space --- nx/include/switch.h | 6 +- nx/include/switch/display/binder.h | 23 +++-- nx/include/switch/display/parcel.h | 2 +- nx/include/switch/nvidia/address_space.h | 22 ++++ nx/source/display/binder.c | 124 ++++++++++++----------- nx/source/display/buffer_producer.c | 32 +++--- nx/source/display/gfx.c | 6 +- nx/source/display/parcel.c | 2 +- nx/source/nvidia/address_space.c | 38 +++++++ nx/source/nvidia/ioctl/nvhost-as-gpu.c | 7 +- 10 files changed, 167 insertions(+), 95 deletions(-) create mode 100644 nx/include/switch/nvidia/address_space.h create mode 100644 nx/source/nvidia/address_space.c diff --git a/nx/include/switch.h b/nx/include/switch.h index fd6f4742..ca828383 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -69,10 +69,12 @@ extern "C" { #include "switch/display/binder.h" #include "switch/display/parcel.h" #include "switch/display/buffer_producer.h" -#include "switch/display/ioctl.h" -#include "switch/display/nvioctl.h" #include "switch/display/nvgfx.h" +#include "switch/nvidia/ioctl.h" +#include "switch/nvidia/nvmap.h" +#include "switch/nvidia/address_space.h" + #include "switch/audio/driver.h" #include "switch/runtime/env.h" diff --git a/nx/include/switch/display/binder.h b/nx/include/switch/display/binder.h index 44e87cde..c54eff61 100644 --- a/nx/include/switch/display/binder.h +++ b/nx/include/switch/display/binder.h @@ -6,24 +6,25 @@ typedef struct { bool created; bool initialized; - Handle sessionHandle; + Handle session_handle; s32 id; - Handle nativeHandle; - size_t ipcBufferSize; - bool hasTransactAuto; + Handle native_handle; + size_t ipc_buffer_size; + bool has_transact_auto; } Binder; -// binderExitSession will not close the sessionHandle since it's user-specified via binderCreateSession and may be used elsewhere. -void binderCreateSession(Binder *session, Handle sessionHandle, s32 ID); -Result binderInitSession(Binder *session, u32 unk0); -void binderExitSession(Binder *session); +// Note: binderClose will not close the session_handle provided to binderCreate. +void binderCreate(Binder* b, Handle session_handle, s32 id); +void binderClose(Binder* b); + +Result binderInitSession(Binder* b, u32 unk0); Result binderTransactParcel( - Binder *session, u32 code, + Binder* b, u32 code, void* parcel_data, size_t parcel_data_size, void* parcel_reply, size_t parcel_reply_size, u32 flags); -Result binderAdjustRefcount(Binder *session, s32 addval, s32 type); -Result binderGetNativeHandle(Binder *session, u32 unk0, Handle *handle_out); +Result binderAdjustRefcount(Binder* b, s32 addval, s32 type); +Result binderGetNativeHandle(Binder* b, u32 unk0, Handle *handle_out); diff --git a/nx/include/switch/display/parcel.h b/nx/include/switch/display/parcel.h index 2fab1de3..328cfe9b 100644 --- a/nx/include/switch/display/parcel.h +++ b/nx/include/switch/display/parcel.h @@ -14,7 +14,7 @@ typedef struct { u32 pos; } Parcel; -void parcelInitialize(Parcel *ctx); +void parcelCreate(Parcel *ctx); Result parcelTransact(Binder *session, u32 code, Parcel *in_parcel, Parcel *reply_parcel); void* parcelWriteData(Parcel *ctx, void* data, size_t data_size); diff --git a/nx/include/switch/nvidia/address_space.h b/nx/include/switch/nvidia/address_space.h new file mode 100644 index 00000000..e3a6b02d --- /dev/null +++ b/nx/include/switch/nvidia/address_space.h @@ -0,0 +1,22 @@ +#pragma once + +typedef struct { + u32 fd; +} NvAddressSpace; + +typedef enum { + NvPageSize_4K = 0x1000, + NvPageSize_64K = 0x10000 +} NvPageSize; + +typedef u64 iova_t; + + +Result nvasCreate(NvAddressSpace* a); +Result nvasClose(NvAddressSpace* a); + +Result nvasReserveAlign(NvAddressSpace* a, NvPageSize align, u32 pages, NvPageSize page_sz, iova_t* iova_out); +Result nvasReserveAtFixedAddr(NvAddressSpace* a, iova_t addr, u32 pages, NvPageSize page_sz); +Result nvasReserveFull(NvAddressSpace* a); + +Result nvasMapBuffer(NvAddressSpace* a, Nvmap* buffer, NvmapKind kind, iova_t* iova_out); diff --git a/nx/source/display/binder.c b/nx/source/display/binder.c index d82a16e4..9011c754 100644 --- a/nx/source/display/binder.c +++ b/nx/source/display/binder.c @@ -5,94 +5,99 @@ #include "kernel/detect.h" #include "display/binder.h" -void binderCreateSession(Binder *session, Handle sessionHandle, s32 id) +void binderCreate(Binder* b, Handle session_handle, s32 id) { - memset(session, 0, sizeof(Binder)); - session->created = 1; - session->sessionHandle = sessionHandle; - session->id = id; - session->nativeHandle = INVALID_HANDLE; - session->hasTransactAuto = 0; + memset(b, 0, sizeof(Binder)); + b->created = true; + b->session_handle = session_handle; + b->id = id; + b->native_handle = INVALID_HANDLE; + b->has_transact_auto = false; } -Result binderInitSession(Binder *session, u32 unk0) +Result binderInitSession(Binder* b, u32 unk0) { Result rc = 0; - if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - if (session->initialized) return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + if (!b->created) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - rc = binderAdjustRefcount(session, 1, 0); + if (b->initialized) + return MAKERESULT(Module_Libnx, LibnxError_AlreadyInitialized); + + rc = binderAdjustRefcount(b, 1, 0); if (R_FAILED(rc)) return rc; - rc = binderAdjustRefcount(session, 1, 1); + rc = binderAdjustRefcount(b, 1, 1); if (R_FAILED(rc)) { - binderAdjustRefcount(session, -1, 0); + binderAdjustRefcount(b, -1, 0); return rc; } - rc = binderGetNativeHandle(session, unk0, &session->nativeHandle); + rc = binderGetNativeHandle(b, unk0, &b->native_handle); if (R_FAILED(rc)) { - binderAdjustRefcount(session, -1, 1); - binderAdjustRefcount(session, -1, 0); + binderAdjustRefcount(b, -1, 1); + binderAdjustRefcount(b, -1, 0); return rc; } - // When the output nativeHandle is 0 the Binder ID is probably invalid. - if (session->nativeHandle == 0) { - binderAdjustRefcount(session, -1, 1); - binderAdjustRefcount(session, -1, 0); + // When the output native_handle is 0 the Binder ID is probably invalid. + if (b->native_handle == 0) { + binderAdjustRefcount(b, -1, 1); + binderAdjustRefcount(b, -1, 0); return MAKERESULT(Module_Libnx, LibnxError_BadInput); } - session->initialized = 1; + b->initialized = true; - rc = ipcQueryPointerBufferSize(session->sessionHandle, &session->ipcBufferSize); + rc = ipcQueryPointerBufferSize(b->session_handle, &b->ipc_buffer_size); if (R_FAILED(rc)) { - binderExitSession(session); + binderClose(b); return rc; } // Use TransactParcelAuto when available. if (kernelAbove300()) - session->hasTransactAuto = 1; + b->has_transact_auto = true; return rc; } -void binderExitSession(Binder *session) +void binderExitSession(Binder* b) { - if (!session->created) return; + if (!b->created) + return; - if (session->initialized) { - binderAdjustRefcount(session, -1, 1); - binderAdjustRefcount(session, -1, 0); + if (b->initialized) { + binderAdjustRefcount(b, -1, 1); + binderAdjustRefcount(b, -1, 0); - if (session->nativeHandle != INVALID_HANDLE) { - svcCloseHandle(session->nativeHandle); - session->nativeHandle = INVALID_HANDLE; + if (b->native_handle != INVALID_HANDLE) { + svcCloseHandle(b->native_handle); + b->native_handle = INVALID_HANDLE; } } - session->sessionHandle = INVALID_HANDLE; - session->id = 0; + b->session_handle = INVALID_HANDLE; + b->id = 0; - session->created = 0; - session->initialized = 0; + b->created = false; + b->initialized = false; } static Result _binderTransactParcel( - Binder *session, u32 code, + Binder* b, u32 code, void* parcel_data, size_t parcel_data_size, void* parcel_reply, size_t parcel_reply_size, u32 flags) { - if (!session->created || !session->initialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (!b->created || !b->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); IpcCommand c; ipcInitialize(&c); @@ -111,11 +116,11 @@ static Result _binderTransactParcel( raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 0; - raw->session_id = session->id; + raw->session_id = b->id; raw->code = code; raw->flags = flags; - Result rc = ipcDispatch(session->sessionHandle); + Result rc = ipcDispatch(b->session_handle); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -133,12 +138,13 @@ static Result _binderTransactParcel( } static Result _binderTransactParcelAuto( - Binder *session, u32 code, + Binder* b, u32 code, void* parcel_data, size_t parcel_data_size, void* parcel_reply, size_t parcel_reply_size, u32 flags) { - if (!session->created || !session->initialized) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (!b->created || !b->initialized) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); IpcCommand c; ipcInitialize(&c); @@ -151,17 +157,17 @@ static Result _binderTransactParcelAuto( u32 flags; } *raw; - ipcAddSendSmart(&c, session->ipcBufferSize, parcel_data, parcel_data_size, 0); - ipcAddRecvSmart(&c, session->ipcBufferSize, parcel_reply, parcel_reply_size, 0); + ipcAddSendSmart(&c, b->ipc_buffer_size, parcel_data, parcel_data_size, 0); + ipcAddRecvSmart(&c, b->ipc_buffer_size, parcel_reply, parcel_reply_size, 0); raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 3; - raw->session_id = session->id; + raw->session_id = b->id; raw->code = code; raw->flags = flags; - Result rc = ipcDispatch(session->sessionHandle); + Result rc = ipcDispatch(b->session_handle); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -179,24 +185,25 @@ static Result _binderTransactParcelAuto( } Result binderTransactParcel( - Binder *session, u32 code, + Binder* b, u32 code, void* parcel_data, size_t parcel_data_size, void* parcel_reply, size_t parcel_reply_size, u32 flags) { Result rc = 0; - if (session->hasTransactAuto) - rc = _binderTransactParcelAuto(session, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); + if (b->has_transact_auto) + rc = _binderTransactParcelAuto(b, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); else - rc = _binderTransactParcel(session, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); + rc = _binderTransactParcel(b, code, parcel_data, parcel_data_size, parcel_reply, parcel_reply_size, flags); return rc; } -Result binderAdjustRefcount(Binder *session, s32 addval, s32 type) +Result binderAdjustRefcount(Binder* b, s32 addval, s32 type) { - if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (!b->created) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); IpcCommand c; ipcInitialize(&c); @@ -212,11 +219,11 @@ Result binderAdjustRefcount(Binder *session, s32 addval, s32 type) raw = ipcPrepareHeader(&c, sizeof(*raw)); raw->magic = SFCI_MAGIC; raw->cmd_id = 1; - raw->session_id = session->id; + raw->session_id = b->id; raw->addval = addval; raw->type = type; - Result rc = ipcDispatch(session->sessionHandle); + Result rc = ipcDispatch(b->session_handle); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; @@ -233,9 +240,10 @@ Result binderAdjustRefcount(Binder *session, s32 addval, s32 type) return rc; } -Result binderGetNativeHandle(Binder *session, u32 inval, Handle *handle_out) +Result binderGetNativeHandle(Binder* b, u32 inval, Handle *handle_out) { - if (!session->created) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); + if (!b->created) + return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); IpcCommand c; ipcInitialize(&c); @@ -251,10 +259,10 @@ Result binderGetNativeHandle(Binder *session, u32 inval, Handle *handle_out) raw->magic = SFCI_MAGIC; raw->cmd_id = 2; - raw->session_id = session->id; + raw->session_id = b->id; raw->inval = inval; - Result rc = ipcDispatch(session->sessionHandle); + Result rc = ipcDispatch(b->session_handle); if (R_SUCCEEDED(rc)) { IpcParsedCommand r; diff --git a/nx/source/display/buffer_producer.c b/nx/source/display/buffer_producer.c index 915e2cf8..d6b035ab 100644 --- a/nx/source/display/buffer_producer.c +++ b/nx/source/display/buffer_producer.c @@ -50,8 +50,8 @@ Result bqRequestBuffer(s32 bufferIdx, BqGraphicBuffer *buf) if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, bufferIdx); @@ -91,8 +91,8 @@ Result bqDequeueBuffer(bool async, u32 width, u32 height, s32 format, u32 usage, if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); @@ -135,8 +135,8 @@ Result bqDetachBuffer(s32 slot) if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, slot); @@ -158,8 +158,8 @@ Result bqQueueBuffer(s32 buf, BqQueueBufferInput *input, BqQueueBufferOutput *ou if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, buf); @@ -187,8 +187,8 @@ Result bqQuery(s32 what, s32* value) if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, what); @@ -214,8 +214,8 @@ Result bqConnect(s32 api, bool producerControlledByApp, BqQueueBufferOutput *out if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); @@ -246,8 +246,8 @@ Result bqDisconnect(s32 api) if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, api); @@ -270,8 +270,8 @@ Result bqGraphicBufferInit(s32 buf, BqGraphicBuffer *input) if (g_bqBinderSession == NULL) return MAKERESULT(Module_Libnx, LibnxError_NotInitialized); - parcelInitialize(&parcel); - parcelInitialize(&parcel_reply); + parcelCreate(&parcel); + parcelCreate(&parcel_reply); parcelWriteInterfaceToken(&parcel, g_bq_InterfaceDescriptor); parcelWriteInt32(&parcel, buf); diff --git a/nx/source/display/gfx.c b/nx/source/display/gfx.c index 31c65bef..7d030c2a 100644 --- a/nx/source/display/gfx.c +++ b/nx/source/display/gfx.c @@ -235,7 +235,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L if (R_SUCCEEDED(rc)) rc = _gfxGetNativeWindowID(g_gfxNativeWindow, g_gfxNativeWindow_Size, &g_gfxNativeWindow_ID); if (R_SUCCEEDED(rc)) { - binderCreateSession(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxNativeWindow_ID); + binderCreate(&g_gfxBinderSession, viGetSession_IHOSBinderDriverRelay()->handle, g_gfxNativeWindow_ID); rc = binderInitSession(&g_gfxBinderSession, 0x0f); } @@ -291,7 +291,7 @@ static Result _gfxInit(ViServiceType servicetype, const char *DisplayName, u32 L nvgfxExit(); bqExit(); - binderExitSession(&g_gfxBinderSession); + binderClose(&g_gfxBinderSession); nvExit(); viCloseLayer(&g_gfxLayer); @@ -361,7 +361,7 @@ void gfxExit(void) nvgfxExit(); bqExit(); - binderExitSession(&g_gfxBinderSession); + binderClose(&g_gfxBinderSession); nvExit(); diff --git a/nx/source/display/parcel.c b/nx/source/display/parcel.c index 47c843d7..03edb36d 100644 --- a/nx/source/display/parcel.c +++ b/nx/source/display/parcel.c @@ -11,7 +11,7 @@ typedef struct { u32 objects_off; } ParcelHeader; -void parcelInitialize(Parcel *ctx) +void parcelCreate(Parcel *ctx) { memset(ctx, 0, sizeof(Parcel)); ctx->capacity = sizeof(ctx->payload); diff --git a/nx/source/nvidia/address_space.c b/nx/source/nvidia/address_space.c new file mode 100644 index 00000000..0d029b90 --- /dev/null +++ b/nx/source/nvidia/address_space.c @@ -0,0 +1,38 @@ +#include + +Result nvasCreate(NvAddressSpace* a) +{ + Result rc = nvOpen(&a->fd, "/dev/nvhost-as-gpu"); + + if (R_SUCCEEDED(rc)) + { + rc = nvioctlNvhostAsGpu_InitializeEx(a->fd, 1, 0x100); + + if (R_FAILED(rc)) + nvasClose(a); + } + + return rc; +} + +Result nvasClose(NvAddressSpace* a) +{ + nvClose(a->fd); + a->fd = -1; +} + +Result nvasReserveAlign(NvAddressSpace* a, NvPageSize align, u32 pages, NvPageSize page_sz, iova_t* iova_out) { + return nvioctlNvhostAsGpu_AllocSpace(a->fd, pages, page_sz, 0, align, iova_out); +} + +Result nvasReserveAtFixedAddr(NvAddressSpace* a, iova_t addr, u32 pages, NvPageSize page_sz) { + return nvioctlNvhostAsGpu_AllocSpace(a->fd, pages, page_sz, 1, addr, NULL); +} + +Result nvasReserveFull(NvAddressSpace* a) { + return nvasReserveAlign(a, NvPageSize_64K, 0x10000, NvPageSize_64K, NULL); +} + +Result nvasMapBuffer(NvAddressSpace* a, Nvmap* buffer, NvmapKind kind, iova_t* iova_out) { + return nvioctlNvhostAsGpu_MapBufferEx(a->fd, 0, kind, buffer->fd, 0, 0, buffer->size, 0, iova_out); +} diff --git a/nx/source/nvidia/ioctl/nvhost-as-gpu.c b/nx/source/nvidia/ioctl/nvhost-as-gpu.c index cf54dcc1..af26cc02 100644 --- a/nx/source/nvidia/ioctl/nvhost-as-gpu.c +++ b/nx/source/nvidia/ioctl/nvhost-as-gpu.c @@ -15,7 +15,7 @@ Result nvioctlNvhostAsGpu_BindChannel(u32 fd, u32 channel_fd) { return nvIoctl(fd, _NV_IOW(0x41, 0x01, data), &data); } -Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align, u64 *offset) { +Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags, u64 align_or_offset, u64 *offset) { Result rc = 0; struct { @@ -33,12 +33,13 @@ Result nvioctlNvhostAsGpu_AllocSpace(u32 fd, u32 pages, u32 page_size, u32 flags data.pages = pages; data.page_size = page_size; data.flags = flags; - data.align = align; + data.align = align_or_offset; rc = nvIoctl(fd, _NV_IOWR(0x41, 0x02, data), &data); if (R_FAILED(rc)) return rc; - *offset = data.offset; + if (offset != NULL) + *offset = data.offset; return rc; }