From eb6f55d880f2c749d651290a3d1b6e8682563a67 Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Sun, 7 Jul 2019 04:13:56 -0400
Subject: [PATCH 1/2] kernel/process: Move main thread stack allocation to its
 own function

Keeps this particular set of behavior isolated to its own function.
---
 src/core/hle/kernel/process.cpp | 26 ++++++++++++++------------
 src/core/hle/kernel/process.h   |  3 +++
 2 files changed, 17 insertions(+), 12 deletions(-)

diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index f45ef05f69..90d579b5cf 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -186,19 +186,9 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
 }
 
 void Process::Run(s32 main_thread_priority, u64 stack_size) {
-    // The kernel always ensures that the given stack size is page aligned.
-    main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
-
-    // Allocate and map the main thread stack
-    // TODO(bunnei): This is heap area that should be allocated by the kernel and not mapped as part
-    // of the user address space.
-    const VAddr mapping_address = vm_manager.GetTLSIORegionEndAddress() - main_thread_stack_size;
-    vm_manager
-        .MapMemoryBlock(mapping_address, std::make_shared<std::vector<u8>>(main_thread_stack_size),
-                        0, main_thread_stack_size, MemoryState::Stack)
-        .Unwrap();
-
+    AllocateMainThreadStack(stack_size);
     vm_manager.LogLayout();
+
     ChangeStatus(ProcessStatus::Running);
 
     SetupMainThread(*this, kernel, main_thread_priority);
@@ -327,4 +317,16 @@ void Process::ChangeStatus(ProcessStatus new_status) {
     WakeupAllWaitingThreads();
 }
 
+void Process::AllocateMainThreadStack(u64 stack_size) {
+    // The kernel always ensures that the given stack size is page aligned.
+    main_thread_stack_size = Common::AlignUp(stack_size, Memory::PAGE_SIZE);
+
+    // Allocate and map the main thread stack
+    const VAddr mapping_address = vm_manager.GetTLSIORegionEndAddress() - main_thread_stack_size;
+    vm_manager
+        .MapMemoryBlock(mapping_address, std::make_shared<std::vector<u8>>(main_thread_stack_size),
+                        0, main_thread_stack_size, MemoryState::Stack)
+        .Unwrap();
+}
+
 } // namespace Kernel
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 83ea02beec..492d8ea4f9 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -280,6 +280,9 @@ private:
     /// a process signal.
     void ChangeStatus(ProcessStatus new_status);
 
+    /// Allocates the main thread stack for the process, given the stack size in bytes.
+    void AllocateMainThreadStack(u64 stack_size);
+
     /// Memory manager for this process.
     Kernel::VMManager vm_manager;
 

From 56c7912159e210e009228f83e6c3ead3e5c99d4b Mon Sep 17 00:00:00 2001
From: Lioncash <mathew1800@gmail.com>
Date: Sun, 7 Jul 2019 04:19:16 -0400
Subject: [PATCH 2/2] kernel/process: Allocate the process' TLS region during
 initialization

Prior to execution within a process beginning, the process establishes
its own TLS region for uses (as far as I can tell) related to exception
handling.

Now that TLS creation was decoupled from threads themselves, we can add
this behavior to our Process class. This is also good, as it allows us
to remove a stub within svcGetInfo, namely querying the address of that
region.
---
 src/core/hle/kernel/process.cpp | 5 +++++
 src/core/hle/kernel/process.h   | 8 ++++++++
 src/core/hle/kernel/svc.cpp     | 4 +---
 3 files changed, 14 insertions(+), 3 deletions(-)

diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 90d579b5cf..73ee1eb0f9 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -187,6 +187,8 @@ ResultCode Process::LoadFromMetadata(const FileSys::ProgramMetadata& metadata) {
 
 void Process::Run(s32 main_thread_priority, u64 stack_size) {
     AllocateMainThreadStack(stack_size);
+    tls_region_address = CreateTLSRegion();
+
     vm_manager.LogLayout();
 
     ChangeStatus(ProcessStatus::Running);
@@ -218,6 +220,9 @@ void Process::PrepareForTermination() {
     stop_threads(system.Scheduler(2).GetThreadList());
     stop_threads(system.Scheduler(3).GetThreadList());
 
+    FreeTLSRegion(tls_region_address);
+    tls_region_address = 0;
+
     ChangeStatus(ProcessStatus::Exited);
 }
 
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 492d8ea4f9..afde9567e2 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -135,6 +135,11 @@ public:
         return mutex;
     }
 
+    /// Gets the address to the process' dedicated TLS region.
+    VAddr GetTLSRegionAddress() const {
+        return tls_region_address;
+    }
+
     /// Gets the current status of the process
     ProcessStatus GetStatus() const {
         return status;
@@ -341,6 +346,9 @@ private:
     /// variable related facilities.
     Mutex mutex;
 
+    /// Address indicating the location of the process' dedicated TLS region.
+    VAddr tls_region_address = 0;
+
     /// Random values for svcGetInfo RandomEntropy
     std::array<u64, RANDOM_ENTROPY_SIZE> random_entropy{};
 
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 332573a955..7621171279 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -831,9 +831,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
             return RESULT_SUCCESS;
 
         case GetInfoType::UserExceptionContextAddr:
-            LOG_WARNING(Kernel_SVC,
-                        "(STUBBED) Attempted to query user exception context address, returned 0");
-            *result = 0;
+            *result = process->GetTLSRegionAddress();
             return RESULT_SUCCESS;
 
         case GetInfoType::TotalPhysicalMemoryAvailableWithoutMmHeap: