diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index b3ddebb3d4..21ddc2f7dc 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -28,20 +28,32 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
     shared_memory->permissions = permissions;
     shared_memory->other_permissions = other_permissions;
 
-    auto& vm_manager = shared_memory->owner_process->vm_manager;
+    if (address == 0) {
+        shared_memory->backing_block = std::make_shared<std::vector<u8>>(size);
+        shared_memory->backing_block_offset = 0;
 
-    // The memory is already available and mapped in the owner process.
-    auto vma = vm_manager.FindVMA(address);
-    ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
-    ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
+        // Refresh the address mappings for the current process.
+        if (Core::CurrentProcess() != nullptr) {
+            Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(
+                shared_memory->backing_block.get());
+        }
+    } else {
+        auto& vm_manager = shared_memory->owner_process->vm_manager;
 
-    // The returned VMA might be a bigger one encompassing the desired address.
-    auto vma_offset = address - vma->first;
-    ASSERT_MSG(vma_offset + size <= vma->second.size,
-               "Shared memory exceeds bounds of mapped block");
+        // The memory is already available and mapped in the owner process.
+        auto vma = vm_manager.FindVMA(address);
+        ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
+        ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
+
+        // The returned VMA might be a bigger one encompassing the desired address.
+        auto vma_offset = address - vma->first;
+        ASSERT_MSG(vma_offset + size <= vma->second.size,
+                   "Shared memory exceeds bounds of mapped block");
+
+        shared_memory->backing_block = vma->second.backing_block;
+        shared_memory->backing_block_offset = vma->second.offset + vma_offset;
+    }
 
-    shared_memory->backing_block = vma->second.backing_block;
-    shared_memory->backing_block_offset = vma->second.offset + vma_offset;
     shared_memory->base_address = address;
 
     return shared_memory;
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index ea9554cbb5..b9022feae2 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -339,6 +339,17 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
         tls_slots.emplace_back(0); // The page is completely available at the start
         available_page = tls_slots.size() - 1;
         available_slot = 0; // Use the first slot in the new page
+
+        // Allocate some memory from the end of the linear heap for this region.
+        const size_t offset = thread->tls_memory->size();
+        thread->tls_memory->insert(thread->tls_memory->end(), Memory::PAGE_SIZE, 0);
+
+        auto& vm_manager = owner_process->vm_manager;
+        vm_manager.RefreshMemoryBlockMappings(thread->tls_memory.get());
+
+        vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
+                                  thread->tls_memory, 0, Memory::PAGE_SIZE,
+                                  MemoryState::ThreadLocal);
     }
 
     // Mark the slot as used
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index 146955e132..adc804248e 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -265,6 +265,8 @@ public:
 private:
     Thread();
     ~Thread() override;
+
+    std::shared_ptr<std::vector<u8>> tls_memory = std::make_shared<std::vector<u8>>();
 };
 
 /**