From 5cad71213b1ef1f6711b04cbfeafebc12ed22db7 Mon Sep 17 00:00:00 2001 From: plutoo Date: Mon, 1 Jan 2018 22:28:12 +0100 Subject: [PATCH] Cache version values, fix guard paging of threads on 2.0.0+ --- nx/source/kernel/thread.c | 6 +++--- nx/source/kernel/version.c | 30 ++++++++++++++++++++++++------ nx/source/kernel/virtmem.c | 14 ++++++++------ 3 files changed, 35 insertions(+), 15 deletions(-) diff --git a/nx/source/kernel/thread.c b/nx/source/kernel/thread.c index c4f4c01e..cb4edbd6 100644 --- a/nx/source/kernel/thread.c +++ b/nx/source/kernel/thread.c @@ -48,8 +48,8 @@ Result threadCreate( } else { // todo: svcMapMemory returns 0xDC01 - void* stack_mirror = stack;//virtmemReserveMap(stack_sz); - //rc = svcMapMemory(stack_mirror, stack, stack_sz); + void* stack_mirror = virtmemReserveMap(stack_sz); + rc = svcMapMemory(stack_mirror, stack, stack_sz); if (R_SUCCEEDED(rc)) { @@ -82,7 +82,7 @@ Result threadCreate( args->reent->_stderr = cur->_stderr; // Set up child thread's TLS segment - size_t tls_load_sz = __tdata_lma_end-__tdata_lma; + size_t tls_load_sz = __tdata_lma_end - __tdata_lma; size_t tls_bss_sz = tls_sz - tls_load_sz; if (tls_load_sz) memcpy(args->tls, __tdata_lma, tls_load_sz); diff --git a/nx/source/kernel/version.c b/nx/source/kernel/version.c index 414164fa..3ce44c00 100644 --- a/nx/source/kernel/version.c +++ b/nx/source/kernel/version.c @@ -1,17 +1,35 @@ // Copyright 2017 plutoo #include +static bool g_IsAbove200; +static bool g_IsAbove300; +static bool g_IsAbove400; +static bool g_HasCached = 0; + +static void _CacheValues() +{ + // This is actually thread safe, might cache twice but that's fine. + if (!g_HasCached) + { + u64 tmp; + g_IsAbove200 = (svcGetInfo(&tmp, 12, INVALID_HANDLE, 0) != 0xF001); + g_IsAbove300 = (svcGetInfo(&tmp, 18, INVALID_HANDLE, 0) != 0xF001); + g_IsAbove400 = (svcGetInfo(&tmp, 19, INVALID_HANDLE, 0) != 0xF001); + g_HasCached = true; + } +} + bool kernelAbove200() { - u64 tmp; - return svcGetInfo(&tmp, 12, INVALID_HANDLE, 0) != 0xF001; + _CacheValues(); + return g_IsAbove200; } bool kernelAbove300() { - u64 tmp; - return svcGetInfo(&tmp, 18, INVALID_HANDLE, 0) != 0xF001; + _CacheValues(); + return g_IsAbove300; } bool kernelAbove400() { - u64 tmp; - return svcGetInfo(&tmp, 19, INVALID_HANDLE, 0) != 0xF001; + _CacheValues(); + return g_IsAbove300; } diff --git a/nx/source/kernel/virtmem.c b/nx/source/kernel/virtmem.c index 8747c3d2..bc244049 100644 --- a/nx/source/kernel/virtmem.c +++ b/nx/source/kernel/virtmem.c @@ -6,9 +6,9 @@ typedef struct { } VirtualRegion; enum { - REGION_MAP =0, + REGION_STACK=0, REGION_HEAP=1, - REGION_UNK =2, + REGION_NEW_STACK=2, REGION_MAX }; @@ -46,7 +46,7 @@ void virtmemSetup() { g_AddressSpace.end = 0x100000000ull; } - if (R_FAILED(_GetRegionFromInfo(&g_Region[REGION_MAP], 2, 3))) { + if (R_FAILED(_GetRegionFromInfo(&g_Region[REGION_STACK], 2, 3))) { fatalSimple(MAKERESULT(MODULE_LIBNX, LIBNX_BADGETINFO)); } @@ -56,7 +56,7 @@ void virtmemSetup() { // Failure is OK, happens on 1.0.0 // In that case, g_UnkRegion will default to (0, 0). - _GetRegionFromInfo(&g_Region[REGION_UNK], 14, 15); + _GetRegionFromInfo(&g_Region[REGION_NEW_STACK], 14, 15); } void* virtmemReserve(size_t size) { @@ -137,6 +137,8 @@ void* virtmemReserveMap(size_t size) size = (size + 0xFFF) &~ 0xFFF; + int region_idx = kernelAbove200() ? REGION_NEW_STACK : REGION_STACK; + u64 addr = g_CurrentMapAddr; while (1) { @@ -144,8 +146,8 @@ void* virtmemReserveMap(size_t size) addr += 0x1000; // Make sure we stay inside the reserved map region. - if (!_InRegion(&g_Region[REGION_MAP], addr)) { - addr = g_Region[REGION_MAP].start; + if (!_InRegion(&g_Region[region_idx], addr)) { + addr = g_Region[region_idx].start; } // Query information about address.