From 6280e1ba586ac6ad02565cf1f3a61f166e1adeac Mon Sep 17 00:00:00 2001 From: plutoo Date: Sat, 14 Oct 2017 15:00:52 +0200 Subject: [PATCH] Introducing shmem --- nx/include/switch.h | 1 + nx/include/switch/kernel/shmem.h | 15 ++++++ nx/include/switch/svc.h | 28 +++++------ nx/source/kernel/shmem.c | 85 ++++++++++++++++++++++++++++++++ nx/source/kernel/svc.s | 22 ++++++++- 5 files changed, 133 insertions(+), 18 deletions(-) create mode 100644 nx/include/switch/kernel/shmem.h create mode 100644 nx/source/kernel/shmem.c diff --git a/nx/include/switch.h b/nx/include/switch.h index 62374e46..4c5ff2d3 100644 --- a/nx/include/switch.h +++ b/nx/include/switch.h @@ -15,6 +15,7 @@ extern "C" { #include #include +#include #include #include #include diff --git a/nx/include/switch/kernel/shmem.h b/nx/include/switch/kernel/shmem.h new file mode 100644 index 00000000..d41c1326 --- /dev/null +++ b/nx/include/switch/kernel/shmem.h @@ -0,0 +1,15 @@ +typedef struct { + Handle MemHandle; + size_t Size; + Permission Perm; + void* MappedAddr; +} SharedMemory; + +Result shmemCreate(SharedMemory* s, size_t size, Permission local_perm, Permission remote_perm); +void shmemLoadRemote(SharedMemory* t, Handle handle, size_t size, Permission perm); + +Result shmemMap(SharedMemory* t); +Result shmemUnmap(SharedMemory* t); +void* shmemGetAddr(SharedMemory* t); + +Result shmemClose(SharedMemory* t); diff --git a/nx/include/switch/svc.h b/nx/include/switch/svc.h index 058918a4..e714c84d 100644 --- a/nx/include/switch/svc.h +++ b/nx/include/switch/svc.h @@ -19,25 +19,18 @@ static inline void* armGetTls(void) { } typedef struct { - u64 base_addr; - u64 size; - u32 memorytype; - u32 memoryattribute; - u32 perm; - u32 devicerefcount; - u32 ipcrefcount; - u32 padding; + u64 base_addr; + u64 size; + u32 memorytype; + u32 memoryattribute; + u32 perm; + u32 devicerefcount; + u32 ipcrefcount; + u32 padding; } MemInfo; typedef struct { - u64 X0; - u64 X1; - u64 X2; - u64 X3; - u64 X4; - u64 X5; - u64 X6; - u64 X7; + u64 X[8]; } __attribute__((packed)) SecmonArgs; Result svcSetHeapSize(void** out_addr, u64 size); @@ -51,6 +44,8 @@ void NORETURN svcExitThread(); Result svcSleepThread(u64 nano); Result svcClearEvent(Handle handle); Result svcCloseHandle(Handle handle); +Result svcMapSharedMemory(Handle handle, void* addr, size_t size, u32 perm); +Result svcUnmapSharedMemory(Handle handle, void* addr, size_t size); Result svcCreateTransferMemory(Handle* out, void* addr, size_t size, u32 perm); Result svcWaitSynchronization(s32* index, const Handle* handles, s32 handleCount, u64 timeout); Result svcArbitrateLock(u32 wait_tag, u32* tag_location, u32 self_tag); @@ -62,6 +57,7 @@ Result svcGetInfo(u64* out, u64 id0, Handle handle, u64 id1); Result svcCreateSession(Handle *server_handle, Handle *client_handle, u32 unk0, u64 unk1);//unk* are normally 0? Result svcAcceptSession(Handle *session_handle, Handle port_handle); Result svcReplyAndReceive(s32* index, const Handle* handles, s32 handleCount, Handle replyTarget, u64 timeout); +Result svcCreateSharedMemory(Handle* out, size_t size, u32 local_perm, u32 other_perm); Result svcMapTransferMemory(Handle tmem_handle, void* addr, size_t size, u32 perm); Result svcUnmapTransferMemory(Handle tmem_handle, void* addr, size_t size); Result svcQueryPhysicalAddress(u64 out[3], u64 virtaddr); diff --git a/nx/source/kernel/shmem.c b/nx/source/kernel/shmem.c new file mode 100644 index 00000000..aa5c51a5 --- /dev/null +++ b/nx/source/kernel/shmem.c @@ -0,0 +1,85 @@ +// Copyright 2017 plutoo +#include +#include + +Result shmemCreate(SharedMemory* s, size_t size, Permission local_perm, Permission remote_perm) +{ + Result rc; + + s->MemHandle = INVALID_HANDLE; + s->Size = size; + s->MappedAddr = NULL; + s->Perm = local_perm; + + rc = svcCreateSharedMemory(&s->MemHandle, size, local_perm, remote_perm); + + return rc; +} + +void shmemLoadRemote(SharedMemory* s, Handle handle, size_t size, Permission perm) +{ + s->MemHandle = handle; + s->Size = size; + s->MappedAddr = NULL; + s->Perm = perm; +} + +Result shmemMap(SharedMemory* s) +{ + Result rc = 0; + + if (s->MappedAddr == NULL) + { + void* addr = virtmemReserve(s->Size); + + rc = svcMapSharedMemory(s->MemHandle, addr, s->Size, s->Perm); + + if (R_SUCCEEDED(rc)) { + s->MappedAddr = addr; + } + else { + virtmemFree(addr, s->Size); + } + } + else { + rc = LIBNX_ALREADYMAPPED; + } + + return rc; +} + +Result shmemUnmap(SharedMemory* s) +{ + Result rc; + + rc = svcUnmapSharedMemory(s->MemHandle, s->MappedAddr, s->Size); + + if (R_SUCCEEDED(rc)) { + s->MappedAddr = NULL; + } + + return rc; +} + +void* shmemGetAddr(SharedMemory* s) { + return s->MappedAddr; +} + +Result shmemClose(SharedMemory* s) +{ + Result rc = 0; + + if (s->MappedAddr != NULL) { + rc = shmemUnmap(s); + } + + if (R_SUCCEEDED(rc)) { + if (s->MemHandle != INVALID_HANDLE) { + rc = svcCloseHandle(s->MemHandle); + } + + s->MemHandle = INVALID_HANDLE; + } + + return rc; +} diff --git a/nx/source/kernel/svc.s b/nx/source/kernel/svc.s index 71d509a0..cca821fa 100644 --- a/nx/source/kernel/svc.s +++ b/nx/source/kernel/svc.s @@ -71,8 +71,13 @@ SVC_BEGIN svcClearEvent ret SVC_END -SVC_BEGIN svcCloseHandle - svc 0x16 +SVC_BEGIN svcMapSharedMemory + svc 0x13 + ret +SVC_END + +SVC_BEGIN svcUnmapSharedMemory + svc 0x14 ret SVC_END @@ -84,6 +89,11 @@ SVC_BEGIN svcCreateTransferMemory ret SVC_END +SVC_BEGIN svcCloseHandle + svc 0x16 + ret +SVC_END + SVC_BEGIN svcWaitSynchronization str x0, [sp, #-16]! svc 0x18 @@ -152,6 +162,14 @@ SVC_BEGIN svcReplyAndReceive ret SVC_END +SVC_BEGIN svcCreateSharedMemory + str x0, [sp, #-16]! + svc 0x50 + ldr x2, [sp], #16 + str w1, [x2] + ret +SVC_END + SVC_BEGIN svcMapTransferMemory svc 0x51 ret