From 0ee6277be975b1d1b2e76ff02e13c3e512735ddd Mon Sep 17 00:00:00 2001 From: Alula Date: Tue, 17 Mar 2026 10:59:11 +0100 Subject: [PATCH] kern: write thread handle to tls +0x110 on creation --- libraries/libmesosphere/source/kern_k_process.cpp | 3 +++ libraries/libmesosphere/source/svc/kern_svc_thread.cpp | 3 +++ .../include/vapours/svc/arch/arm/svc_thread_local_region.hpp | 3 ++- .../include/vapours/svc/arch/arm64/svc_thread_local_region.hpp | 3 ++- 4 files changed, 10 insertions(+), 2 deletions(-) diff --git a/libraries/libmesosphere/source/kern_k_process.cpp b/libraries/libmesosphere/source/kern_k_process.cpp index 0d1d4b6dc..c11cf0c42 100644 --- a/libraries/libmesosphere/source/kern_k_process.cpp +++ b/libraries/libmesosphere/source/kern_k_process.cpp @@ -976,6 +976,9 @@ namespace ams::kern { /* Set the thread arguments. */ main_thread->GetContext().SetArguments(0, thread_handle); + /* Pass the thread handle to the thread local region. */ + static_cast(main_thread->GetThreadLocalRegionHeapAddress())->thread_handle = thread_handle; + /* Update our state. */ this->ChangeState((state == State_Created) ? State_Running : State_RunningAttached); ON_RESULT_FAILURE_2 { this->ChangeState(state); }; diff --git a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp index 6f74dd145..14af1bb11 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_thread.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_thread.cpp @@ -66,6 +66,9 @@ namespace ams::kern::svc { /* Add the thread to the handle table. */ R_TRY(process.GetHandleTable().Add(out, thread)); + /* Pass the thread handle to the thread local region. */ + static_cast(thread->GetThreadLocalRegionHeapAddress())->thread_handle = *out; + R_SUCCEED(); } diff --git a/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp index 9fdd954af..69caab7c4 100644 --- a/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp +++ b/libraries/libvapours/include/vapours/svc/arch/arm/svc_thread_local_region.hpp @@ -27,8 +27,9 @@ namespace ams::svc::arch::arm { volatile u16 interrupt_flag; volatile u8 cache_maintenance_flag; volatile s64 thread_cpu_time; + volatile ams::svc::Handle thread_handle; /* TODO: Should we bother adding the Nintendo aarch32 thread local context here? */ - uintptr_t TODO[(0x200 - 0x110) / sizeof(uintptr_t)]; + uintptr_t TODO[(0x200 - 0x114) / sizeof(uintptr_t)]; }; ALWAYS_INLINE ThreadLocalRegion *GetThreadLocalRegion() { diff --git a/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp index f3146dcbf..390d3cb0f 100644 --- a/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp +++ b/libraries/libvapours/include/vapours/svc/arch/arm64/svc_thread_local_region.hpp @@ -27,8 +27,9 @@ namespace ams::svc::arch::arm64 { volatile u16 interrupt_flag; volatile u8 cache_maintenance_flag; volatile s64 thread_cpu_time; + volatile ams::svc::Handle thread_handle; /* TODO: How should we handle libnx vs Nintendo user thread local space? */ - uintptr_t TODO[(0x200 - 0x110) / sizeof(uintptr_t)]; + uintptr_t TODO[(0x200 - 0x114) / sizeof(uintptr_t)]; }; static_assert(__builtin_offsetof(ThreadLocalRegion, disable_count) == 0x100); static_assert(__builtin_offsetof(ThreadLocalRegion, interrupt_flag) == 0x102);