From 115ad8e16a69c8823118f210654fc9ea70a03213 Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Sun, 10 May 2015 18:43:59 -0500
Subject: [PATCH] fixup! Set the TLS address in the scheduler

---
 src/core/arm/arm_interface.h       | 3 +--
 src/core/arm/dyncom/arm_dyncom.cpp | 5 +----
 src/core/arm/dyncom/arm_dyncom.h   | 2 +-
 src/core/core.h                    | 2 --
 src/core/hle/kernel/thread.cpp     | 7 +++++--
 src/core/hle/kernel/thread.h       | 2 ++
 6 files changed, 10 insertions(+), 11 deletions(-)

diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 976c339e86..85ed2c698d 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -99,9 +99,8 @@ public:
      * @param stack_top Pointer to the top of the stack
      * @param entry_point Entry point for execution
      * @param arg User argument for thread
-     * @param tls_address Address of the Thread Local Storage for the thread
      */
-    virtual void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg, u32 tls_address) = 0;
+    virtual void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) = 0;
 
     /**
      * Saves the current CPU context
diff --git a/src/core/arm/dyncom/arm_dyncom.cpp b/src/core/arm/dyncom/arm_dyncom.cpp
index 1de1d2612f..0072ae533f 100644
--- a/src/core/arm/dyncom/arm_dyncom.cpp
+++ b/src/core/arm/dyncom/arm_dyncom.cpp
@@ -90,14 +90,13 @@ void ARM_DynCom::ExecuteInstructions(int num_instructions) {
     AddTicks(ticks_executed);
 }
 
-void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg, u32 tls_address) {
+void ARM_DynCom::ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) {
     memset(&context, 0, sizeof(Core::ThreadContext));
 
     context.cpu_registers[0] = arg;
     context.pc = entry_point;
     context.sp = stack_top;
     context.cpsr = 0x1F; // Usermode
-    context.tls = tls_address;
 }
 
 void ARM_DynCom::SaveContext(Core::ThreadContext& ctx) {
@@ -124,8 +123,6 @@ void ARM_DynCom::LoadContext(const Core::ThreadContext& ctx) {
 
     state->VFP[1] = ctx.fpscr;
     state->VFP[2] = ctx.fpexc;
-
-    SetCP15Register(CP15_THREAD_URO, ctx.tls);
 }
 
 void ARM_DynCom::PrepareReschedule() {
diff --git a/src/core/arm/dyncom/arm_dyncom.h b/src/core/arm/dyncom/arm_dyncom.h
index b3fd708f16..2488c879c0 100644
--- a/src/core/arm/dyncom/arm_dyncom.h
+++ b/src/core/arm/dyncom/arm_dyncom.h
@@ -27,7 +27,7 @@ public:
 
     void AddTicks(u64 ticks) override;
 
-    void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg, u32 tls_address) override;
+    void ResetContext(Core::ThreadContext& context, u32 stack_top, u32 entry_point, u32 arg) override;
     void SaveContext(Core::ThreadContext& ctx) override;
     void LoadContext(const Core::ThreadContext& ctx) override;
 
diff --git a/src/core/core.h b/src/core/core.h
index 215b5a49f2..278f0f1ccd 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -21,8 +21,6 @@ struct ThreadContext {
     u32 fpu_registers[32];
     u32 fpscr;
     u32 fpexc;
-
-    u32 tls;
 };
 
 extern ARM_Interface*   g_app_core;     ///< ARM11 application core
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 61199c12aa..5de8f9a73d 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -197,6 +197,7 @@ static void SwitchContext(Thread* new_thread) {
         new_thread->current_priority = new_thread->nominal_priority;
 
         Core::g_app_core->LoadContext(new_thread->context);
+        Core::g_app_core->SetCP15Register(CP15_THREAD_URO, new_thread->GetTLSAddress());
     } else {
         current_thread = nullptr;
     }
@@ -406,9 +407,11 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
 
     ASSERT_MSG(tls_address < Memory::TLS_AREA_VADDR_END, "Too many threads");
 
+    thread->tls_address = tls_address;
+
     // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
     // to initialize the context
-    Core::g_app_core->ResetContext(thread->context, stack_top, entry_point, arg, tls_address);
+    Core::g_app_core->ResetContext(thread->context, stack_top, entry_point, arg);
 
     ready_queue.push_back(thread->current_priority, thread.get());
     thread->status = THREADSTATUS_READY;
@@ -500,7 +503,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
 }
 
 VAddr Thread::GetTLSAddress() const {
-    return context.tls;
+    return tls_address;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 17bb69f459..6891c8c2f7 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -156,6 +156,8 @@ public:
 
     s32 processor_id;
 
+    VAddr tls_address; ///< Address of the Thread Local Storage of the thread
+
     /// Mutexes currently held by this thread, which will be released when it exits.
     boost::container::flat_set<SharedPtr<Mutex>> held_mutexes;