diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index 1bff53a909..17b83a5fb0 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -91,7 +91,7 @@ void ArmNce::UnlockThreadParameters(NativeExecutionParameters* nep) { #ifndef _WIN32 YUZU_NAKED YUZU_NO_INLINE -HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, NativeExecutionParameters* tpidr) { +HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(thread_id tid, NativeExecutionParameters* tpidr) { // x0 - tid // x1 - tpidr @@ -124,7 +124,7 @@ HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, NativeExecutio } YUZU_NAKED_END #else -HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(void* tid, NativeExecutionParameters *tpidr) { +HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(thread_id tid, NativeExecutionParameters *tpidr) { RaiseException(ExceptionLevelChangeSignal, 0, 0, nullptr); // TODO: pass tpidr through arguments? __builtin_unreachable(); } @@ -357,7 +357,7 @@ NativeExecutionParameters* ArmNce::RestoreGuestContext(void* raw_context) { nep->host_stack_limit = tib->StackLimit; // Set guest stack base/limit for CET tib->StackBase = nep->guest_stack_base; - tib->StartLimit = nep->guest_stack_limit; + tib->StackLimit = nep->guest_stack_limit; #endif // Return the new thread-local storage pointer. @@ -382,9 +382,10 @@ void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) { #ifdef _WIN32 // Restore stack base/limit for CET + // TODO: store this in Context instead of NEP? auto tib = (PNT_TIB)NtCurrentTeb(); - tib->StackBase = nep->host_stack_base; - tib->StartLimit = nep->host_stack_limit; + tib->StackBase = GetGuestParameters()->host_stack_base; + tib->StackLimit = GetGuestParameters()->host_stack_limit; #endif // Restore host callee-saved registers. @@ -462,11 +463,12 @@ HaltReason ArmNce::RunThread(Kernel::KThread* thread) { ASSERT(pthread_setspecific(ContextKey, thread_params) == 0); #elif defined(_WIN32) ASSERT_MSG(TlsSetValue(ContextKey, thread_params), "Failed to set TLS value: id {}, error {}", ContextKey, GetLastError()); - ASSERT_MSG(TlsSetValue(NCEStorage, thread_params->native_context->cpu_registers[18]), + ASSERT_MSG(TlsSetValue(NCEStorage, reinterpret_cast(thread_params->native_context->cpu_registers[18])), "Failed to set TLS value: id {}, error {}", ContextKey, GetLastError()); - thread_params->guest_stack_base = thread->GetOwnerProcess()->GetPageTable().GetStackRegionStart() + thread->GetOwnerProcess()->GetPageTable().GetStackRegionSize(); - thread_params->guest_stack_limit = thread->GetOwnerProcess()->GetPageTable().GetStackRegionStart(); + thread_params->guest_stack_base = reinterpret_cast(GetInteger( + thread->GetOwnerProcess()->GetPageTable().GetStackRegionStart() + thread->GetOwnerProcess()->GetPageTable().GetStackRegionSize())); + thread_params->guest_stack_limit = reinterpret_cast(GetInteger(thread->GetOwnerProcess()->GetPageTable().GetStackRegionStart())); #endif // Move non-critical operations outside the locked section @@ -563,27 +565,27 @@ LONG WINAPI ArmNce::VectoredExceptionHandler(PEXCEPTION_POINTERS info) { #ifdef __APPLE__ // https://github.com/apple-oss-distributions/libpthread/blob/42d026df5b07825070f60134b980a1ec2552dfee/src/pthread_tsd.c#L418-L435 +// Equivalent to pthread_key_create but allows for setting a specific key value. +// Used in internal WebKit and certain Apple programs to define and use a reserved key. extern "C" int pthread_key_init_np(int, void (*)(void *)); #endif void ArmNce::Initialize() { -#ifdef __APPLE__ - if (m_thread_id == -1) { - m_thread_id = pthread_mach_thread_np(pthread_self()); - } - ASSERT(pthread_key_init_np(ContextKey, [](void*) -> void {}) == 0); -#elif defined(__linux__) - if (m_thread_id == -1) { + if (m_thread_id == NULL_THREAD_ID) { + +#if defined(__APPLE__) + m_thread_id = pthread_mach_thread_np(pthread_self()); + ASSERT(pthread_key_init_np(ContextKey, [](void*) -> void {}) == 0); +#elif defined(__linux) m_thread_id = gettid(); - } #elif defined(_WIN32) - if (m_thread_id == nullptr) { DuplicateHandle(GetCurrentProcess(), GetCurrentThread(), GetCurrentProcess(), &m_thread_id, 0, false, DUPLICATE_SAME_ACCESS); - } #endif + } + #ifndef _WIN32 // Configure signal stack. if (!m_stack) { @@ -700,7 +702,7 @@ void ArmNce::SignalInterrupt(Kernel::KThread* thread) { :: "r"(static_cast(m_thread_id)), "r"(static_cast(SIGURG)) : "x0", "x1", "x16", "memory", "cc"); #elif defined(_WIN32) - // TODO: use SetThreadState to emulate BreakFromRunCodeSignalHandler + // TODO: use Get/SetThreadState to emulate BreakFromRunCodeSignalHandler SuspendThread(m_thread_id); UnlockThreadParameters(params); #endif diff --git a/src/core/arm/nce/arm_nce.h b/src/core/arm/nce/arm_nce.h index 97137d375a..3a1739b2ed 100644 --- a/src/core/arm/nce/arm_nce.h +++ b/src/core/arm/nce/arm_nce.h @@ -45,10 +45,11 @@ constexpr u64 TlsSlots = offsetof(TEB, TlsSlots); struct NativeExecutionParameters { -#if (defined(__APPLE__) || defined(_WIN32)) && HAS_NCE +#if defined(__APPLE__) || defined(_WIN32) // Are we in actual guest code? bool is_actually_running{}; #endif + // Are we in any stage of performing guest operations? bool is_running{}; u32 magic{Common::MakeMagic('Y', 'U', 'Z', 'U')}; @@ -58,10 +59,10 @@ struct NativeExecutionParameters { GuestContext* native_context{}; #ifdef _WIN32 - u64 guest_stack_base; - u64 guest_stack_limit; - u64 host_stack_base; - u64 host_stack_limit; + void* guest_stack_base; + void* guest_stack_limit; + void* host_stack_base; + void* host_stack_limit; #endif }; @@ -94,6 +95,17 @@ public: void LockThread(Kernel::KThread* thread) override; void UnlockThread(Kernel::KThread* thread) override; +#ifdef __linux__ + typedef pid_t thread_id; + static constexpr thread_id NULL_THREAD_ID = -1; +#elif __APPLE__ + typedef mach_port_t thread_id; + static constexpr thread_id NULL_THREAD_ID = -1U; +#elif _WIN32 + typedef HANDLE thread_id; + static constexpr thread_id NULL_THREAD_ID = nullptr; +#endif + protected: const Kernel::DebugWatchpoint* HaltedWatchpoint() const override { return nullptr; @@ -106,18 +118,16 @@ private: static NativeExecutionParameters* GetGuestParameters(); static HaltReason ReturnToRunCodeByTrampoline(NativeExecutionParameters* tpidr, u64 trampoline_addr); -#ifndef _WIN32 - static HaltReason ReturnToRunCodeByExceptionLevelChange(int tid, NativeExecutionParameters* tpidr); -#else - static HaltReason ReturnToRunCodeByExceptionLevelChange(void* tid, void* tpidr); - static LONG VectoredExceptionHandler(PEXCEPTION_POINTERS info); -#endif + static HaltReason ReturnToRunCodeByExceptionLevelChange(thread_id tid, NativeExecutionParameters* tpidr); static void ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void* info, void* raw_context); static void BreakFromRunCodeSignalHandler(int sig, void* info, void* raw_context); static void GuestMemoryFaultSignalHandler(int sig, void* info, void* raw_context); static bool HandleFailedGuestFault(GuestContext* ctx, void* info, void* raw_context); +#ifdef _WIN32 + static LONG VectoredExceptionHandler(PEXCEPTION_POINTERS info); +#endif static void LockThreadParameters(NativeExecutionParameters* tpidr); static void UnlockThreadParameters(NativeExecutionParameters* tpidr); @@ -130,11 +140,7 @@ public: // Members set on initialization. std::size_t m_core_index{}; -#ifndef _WIN32 - pid_t m_thread_id{-1}; -#else - void* m_thread_id{}; -#endif + thread_id m_thread_id{NULL_THREAD_ID}; // Core context. GuestContext m_guest_ctx{}; diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index abb34c68ff..fb7d4b8a11 100644 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -21,7 +21,6 @@ #include "common/logging.h" #include "common/settings.h" #include "common/random.h" -#include "core/arm/nce/arm_nce.h" #include "core/core.h" #include "core/cpu_manager.h" #include "core/hardware_properties.h" @@ -43,6 +42,10 @@ #include "core/hle/result.h" #include "core/memory.h" +#ifdef HAS_NCE +#include "core/arm/nce/arm_nce.h" +#endif + namespace { constexpr inline s32 TerminatingThreadPriority = Kernel::Svc::SystemThreadPriorityHighest - 1;