Stylechanges to binder, and implemented gpu address space

This commit is contained in:
plutooo 2018-02-26 05:27:55 +01:00 committed by fincs
parent cd753b1b58
commit 04751087ca
10 changed files with 167 additions and 95 deletions

View File

@ -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"

View File

@ -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);

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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();

View File

@ -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);

View File

@ -0,0 +1,38 @@
#include <switch.h>
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);
}

View File

@ -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;
}