summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel
diff options
context:
space:
mode:
authorGravatar Lioncash2018-08-02 23:37:44 -0400
committerGravatar Lioncash2018-08-03 11:22:47 -0400
commit26de4bb521b1ace7af76eff4f6956cb23ac0d58c (patch)
tree904a93d00abf5bde2742499fb3d60a3aa1521820 /src/core/hle/kernel
parentMerge pull request #892 from lioncash/global (diff)
downloadyuzu-26de4bb521b1ace7af76eff4f6956cb23ac0d58c.tar.gz
yuzu-26de4bb521b1ace7af76eff4f6956cb23ac0d58c.tar.xz
yuzu-26de4bb521b1ace7af76eff4f6956cb23ac0d58c.zip
core/memory: Get rid of 3DS leftovers
Removes leftover code from citra that isn't needed.
Diffstat (limited to 'src/core/hle/kernel')
-rw-r--r--src/core/hle/kernel/kernel.cpp6
-rw-r--r--src/core/hle/kernel/kernel.h2
-rw-r--r--src/core/hle/kernel/memory.cpp90
-rw-r--r--src/core/hle/kernel/memory.h34
-rw-r--r--src/core/hle/kernel/process.cpp78
-rw-r--r--src/core/hle/kernel/process.h17
-rw-r--r--src/core/hle/kernel/shared_memory.cpp63
-rw-r--r--src/core/hle/kernel/shared_memory.h3
-rw-r--r--src/core/hle/kernel/thread.cpp33
9 files changed, 24 insertions, 302 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 3eb4f465c..1b0cd0abf 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -4,7 +4,6 @@
4 4
5#include "core/hle/kernel/handle_table.h" 5#include "core/hle/kernel/handle_table.h"
6#include "core/hle/kernel/kernel.h" 6#include "core/hle/kernel/kernel.h"
7#include "core/hle/kernel/memory.h"
8#include "core/hle/kernel/process.h" 7#include "core/hle/kernel/process.h"
9#include "core/hle/kernel/resource_limit.h" 8#include "core/hle/kernel/resource_limit.h"
10#include "core/hle/kernel/thread.h" 9#include "core/hle/kernel/thread.h"
@@ -15,9 +14,7 @@ namespace Kernel {
15unsigned int Object::next_object_id; 14unsigned int Object::next_object_id;
16 15
17/// Initialize the kernel 16/// Initialize the kernel
18void Init(u32 system_mode) { 17void Init() {
19 Kernel::MemoryInit(system_mode);
20
21 Kernel::ResourceLimitsInit(); 18 Kernel::ResourceLimitsInit();
22 Kernel::ThreadingInit(); 19 Kernel::ThreadingInit();
23 Kernel::TimersInit(); 20 Kernel::TimersInit();
@@ -37,7 +34,6 @@ void Shutdown() {
37 34
38 Kernel::TimersShutdown(); 35 Kernel::TimersShutdown();
39 Kernel::ResourceLimitsShutdown(); 36 Kernel::ResourceLimitsShutdown();
40 Kernel::MemoryShutdown();
41} 37}
42 38
43} // namespace Kernel 39} // namespace Kernel
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 2bc45d7db..131311472 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -9,7 +9,7 @@
9namespace Kernel { 9namespace Kernel {
10 10
11/// Initialize the kernel with the specified system mode. 11/// Initialize the kernel with the specified system mode.
12void Init(u32 system_mode); 12void Init();
13 13
14/// Shutdown the kernel 14/// Shutdown the kernel
15void Shutdown(); 15void Shutdown();
diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp
deleted file mode 100644
index a7f3c3c5a..000000000
--- a/src/core/hle/kernel/memory.cpp
+++ /dev/null
@@ -1,90 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <cinttypes>
7#include <memory>
8#include <utility>
9#include <vector>
10#include "common/assert.h"
11#include "common/common_types.h"
12#include "common/logging/log.h"
13#include "core/hle/kernel/memory.h"
14#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/vm_manager.h"
16#include "core/memory.h"
17
18////////////////////////////////////////////////////////////////////////////////////////////////////
19
20namespace Kernel {
21
22MemoryRegionInfo memory_regions[3];
23
24/// Size of the APPLICATION, SYSTEM and BASE memory regions (respectively) for each system
25/// memory configuration type.
26static const u32 memory_region_sizes[8][3] = {
27 // Old 3DS layouts
28 {0x04000000, 0x02C00000, 0x01400000}, // 0
29 {/* This appears to be unused. */}, // 1
30 {0x06000000, 0x00C00000, 0x01400000}, // 2
31 {0x05000000, 0x01C00000, 0x01400000}, // 3
32 {0x04800000, 0x02400000, 0x01400000}, // 4
33 {0x02000000, 0x04C00000, 0x01400000}, // 5
34
35 // New 3DS layouts
36 {0x07C00000, 0x06400000, 0x02000000}, // 6
37 {0x0B200000, 0x02E00000, 0x02000000}, // 7
38};
39
40void MemoryInit(u32 mem_type) {
41 // TODO(yuriks): On the n3DS, all o3DS configurations (<=5) are forced to 6 instead.
42 ASSERT_MSG(mem_type <= 5, "New 3DS memory configuration aren't supported yet!");
43 ASSERT(mem_type != 1);
44
45 // The kernel allocation regions (APPLICATION, SYSTEM and BASE) are laid out in sequence, with
46 // the sizes specified in the memory_region_sizes table.
47 VAddr base = 0;
48 for (int i = 0; i < 3; ++i) {
49 memory_regions[i].base = base;
50 memory_regions[i].size = memory_region_sizes[mem_type][i];
51 memory_regions[i].used = 0;
52 memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>();
53 // Reserve enough space for this region of FCRAM.
54 // We do not want this block of memory to be relocated when allocating from it.
55 memory_regions[i].linear_heap_memory->reserve(memory_regions[i].size);
56
57 base += memory_regions[i].size;
58 }
59
60 // We must've allocated the entire FCRAM by the end
61 ASSERT(base == Memory::FCRAM_SIZE);
62}
63
64void MemoryShutdown() {
65 for (auto& region : memory_regions) {
66 region.base = 0;
67 region.size = 0;
68 region.used = 0;
69 region.linear_heap_memory = nullptr;
70 }
71}
72
73MemoryRegionInfo* GetMemoryRegion(MemoryRegion region) {
74 switch (region) {
75 case MemoryRegion::APPLICATION:
76 return &memory_regions[0];
77 case MemoryRegion::SYSTEM:
78 return &memory_regions[1];
79 case MemoryRegion::BASE:
80 return &memory_regions[2];
81 default:
82 UNREACHABLE();
83 }
84}
85
86void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {}
87
88void MapSharedPages(VMManager& address_space) {}
89
90} // namespace Kernel
diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h
deleted file mode 100644
index 1d05b8871..000000000
--- a/src/core/hle/kernel/memory.h
+++ /dev/null
@@ -1,34 +0,0 @@
1// Copyright 2014 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <vector>
9
10#include "common/common_types.h"
11
12namespace Kernel {
13
14class VMManager;
15enum class MemoryRegion : u16;
16struct AddressMapping;
17
18struct MemoryRegionInfo {
19 u64 base; // Not an address, but offset from start of FCRAM
20 u64 size;
21 u64 used;
22
23 std::shared_ptr<std::vector<u8>> linear_heap_memory;
24};
25
26void MemoryInit(u32 mem_type);
27void MemoryShutdown();
28MemoryRegionInfo* GetMemoryRegion(MemoryRegion region);
29
30void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping);
31void MapSharedPages(VMManager& address_space);
32
33extern MemoryRegionInfo memory_regions[3];
34} // namespace Kernel
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp
index 0c0506085..5403ceef5 100644
--- a/src/core/hle/kernel/process.cpp
+++ b/src/core/hle/kernel/process.cpp
@@ -8,7 +8,6 @@
8#include "common/common_funcs.h" 8#include "common/common_funcs.h"
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "core/hle/kernel/errors.h" 10#include "core/hle/kernel/errors.h"
11#include "core/hle/kernel/memory.h"
12#include "core/hle/kernel/process.h" 11#include "core/hle/kernel/process.h"
13#include "core/hle/kernel/resource_limit.h" 12#include "core/hle/kernel/resource_limit.h"
14#include "core/hle/kernel/thread.h" 13#include "core/hle/kernel/thread.h"
@@ -125,14 +124,6 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
125 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, 124 std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size,
126 MemoryState::Mapped) 125 MemoryState::Mapped)
127 .Unwrap(); 126 .Unwrap();
128 misc_memory_used += stack_size;
129 memory_region->used += stack_size;
130
131 // Map special address mappings
132 MapSharedPages(vm_manager);
133 for (const auto& mapping : address_mappings) {
134 HandleSpecialMapping(vm_manager, mapping);
135 }
136 127
137 vm_manager.LogLayout(); 128 vm_manager.LogLayout();
138 status = ProcessStatus::Running; 129 status = ProcessStatus::Running;
@@ -141,17 +132,13 @@ void Process::Run(VAddr entry_point, s32 main_thread_priority, u32 stack_size) {
141} 132}
142 133
143void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { 134void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
144 memory_region = GetMemoryRegion(flags.memory_region); 135 const auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
145 136 MemoryState memory_state) {
146 auto MapSegment = [&](CodeSet::Segment& segment, VMAPermission permissions,
147 MemoryState memory_state) {
148 auto vma = vm_manager 137 auto vma = vm_manager
149 .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset, 138 .MapMemoryBlock(segment.addr + base_addr, module_->memory, segment.offset,
150 segment.size, memory_state) 139 segment.size, memory_state)
151 .Unwrap(); 140 .Unwrap();
152 vm_manager.Reprotect(vma, permissions); 141 vm_manager.Reprotect(vma, permissions);
153 misc_memory_used += segment.size;
154 memory_region->used += segment.size;
155 }; 142 };
156 143
157 // Map CodeSet segments 144 // Map CodeSet segments
@@ -160,20 +147,6 @@ void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) {
160 MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::CodeMutable); 147 MapSegment(module_->data, VMAPermission::ReadWrite, MemoryState::CodeMutable);
161} 148}
162 149
163VAddr Process::GetLinearHeapAreaAddress() const {
164 // Starting from system version 8.0.0 a new linear heap layout is supported to allow usage of
165 // the extra RAM in the n3DS.
166 return kernel_version < 0x22C ? Memory::LINEAR_HEAP_VADDR : Memory::NEW_LINEAR_HEAP_VADDR;
167}
168
169VAddr Process::GetLinearHeapBase() const {
170 return GetLinearHeapAreaAddress() + memory_region->base;
171}
172
173VAddr Process::GetLinearHeapLimit() const {
174 return GetLinearHeapBase() + memory_region->size;
175}
176
177ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { 150ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) {
178 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END || 151 if (target < Memory::HEAP_VADDR || target + size > Memory::HEAP_VADDR_END ||
179 target + size < target) { 152 target + size < target) {
@@ -206,7 +179,6 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission per
206 vm_manager.Reprotect(vma, perms); 179 vm_manager.Reprotect(vma, perms);
207 180
208 heap_used = size; 181 heap_used = size;
209 memory_region->used += size;
210 182
211 return MakeResult<VAddr>(heap_end - size); 183 return MakeResult<VAddr>(heap_end - size);
212} 184}
@@ -226,52 +198,6 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
226 return result; 198 return result;
227 199
228 heap_used -= size; 200 heap_used -= size;
229 memory_region->used -= size;
230
231 return RESULT_SUCCESS;
232}
233
234ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) {
235 UNIMPLEMENTED();
236 return {};
237}
238
239ResultCode Process::LinearFree(VAddr target, u32 size) {
240 auto& linheap_memory = memory_region->linear_heap_memory;
241
242 if (target < GetLinearHeapBase() || target + size > GetLinearHeapLimit() ||
243 target + size < target) {
244
245 return ERR_INVALID_ADDRESS;
246 }
247
248 if (size == 0) {
249 return RESULT_SUCCESS;
250 }
251
252 VAddr heap_end = GetLinearHeapBase() + (u32)linheap_memory->size();
253 if (target + size > heap_end) {
254 return ERR_INVALID_ADDRESS_STATE;
255 }
256
257 ResultCode result = vm_manager.UnmapRange(target, size);
258 if (result.IsError())
259 return result;
260
261 linear_heap_used -= size;
262 memory_region->used -= size;
263
264 if (target + size == heap_end) {
265 // End of linear heap has been freed, so check what's the last allocated block in it and
266 // reduce the size.
267 auto vma = vm_manager.FindVMA(target);
268 ASSERT(vma != vm_manager.vma_map.end());
269 ASSERT(vma->second.type == VMAType::Free);
270 VAddr new_end = vma->second.base;
271 if (new_end >= GetLinearHeapBase()) {
272 linheap_memory->resize(new_end - GetLinearHeapBase());
273 }
274 }
275 201
276 return RESULT_SUCCESS; 202 return RESULT_SUCCESS;
277} 203}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 1204026be..98d8da35e 100644
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -53,7 +53,6 @@ union ProcessFlags {
53enum class ProcessStatus { Created, Running, Exited }; 53enum class ProcessStatus { Created, Running, Exited };
54 54
55class ResourceLimit; 55class ResourceLimit;
56struct MemoryRegionInfo;
57 56
58struct CodeSet final : public Object { 57struct CodeSet final : public Object {
59 static SharedPtr<CodeSet> Create(std::string name); 58 static SharedPtr<CodeSet> Create(std::string name);
@@ -163,12 +162,11 @@ public:
163 // This makes deallocation and reallocation of holes fast and keeps process memory contiguous 162 // This makes deallocation and reallocation of holes fast and keeps process memory contiguous
164 // in the emulator address space, allowing Memory::GetPointer to be reasonably safe. 163 // in the emulator address space, allowing Memory::GetPointer to be reasonably safe.
165 std::shared_ptr<std::vector<u8>> heap_memory; 164 std::shared_ptr<std::vector<u8>> heap_memory;
166 // The left/right bounds of the address space covered by heap_memory.
167 VAddr heap_start = 0, heap_end = 0;
168
169 u64 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0;
170 165
171 MemoryRegionInfo* memory_region = nullptr; 166 // The left/right bounds of the address space covered by heap_memory.
167 VAddr heap_start = 0;
168 VAddr heap_end = 0;
169 u64 heap_used = 0;
172 170
173 /// The Thread Local Storage area is allocated as processes create threads, 171 /// The Thread Local Storage area is allocated as processes create threads,
174 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part 172 /// each TLS area is 0x200 bytes, so one page (0x1000) is split up in 8 parts, and each part
@@ -179,16 +177,9 @@ public:
179 177
180 std::string name; 178 std::string name;
181 179
182 VAddr GetLinearHeapAreaAddress() const;
183 VAddr GetLinearHeapBase() const;
184 VAddr GetLinearHeapLimit() const;
185
186 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms); 180 ResultVal<VAddr> HeapAllocate(VAddr target, u64 size, VMAPermission perms);
187 ResultCode HeapFree(VAddr target, u32 size); 181 ResultCode HeapFree(VAddr target, u32 size);
188 182
189 ResultVal<VAddr> LinearAllocate(VAddr target, u32 size, VMAPermission perms);
190 ResultCode LinearFree(VAddr target, u32 size);
191
192 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size); 183 ResultCode MirrorMemory(VAddr dst_addr, VAddr src_addr, u64 size);
193 184
194 ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size); 185 ResultCode UnmapMemory(VAddr dst_addr, VAddr src_addr, u64 size);
diff --git a/src/core/hle/kernel/shared_memory.cpp b/src/core/hle/kernel/shared_memory.cpp
index a5b11bd87..b3ddebb3d 100644
--- a/src/core/hle/kernel/shared_memory.cpp
+++ b/src/core/hle/kernel/shared_memory.cpp
@@ -8,7 +8,6 @@
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/kernel/errors.h" 10#include "core/hle/kernel/errors.h"
11#include "core/hle/kernel/memory.h"
12#include "core/hle/kernel/shared_memory.h" 11#include "core/hle/kernel/shared_memory.h"
13#include "core/memory.h" 12#include "core/memory.h"
14 13
@@ -29,51 +28,22 @@ SharedPtr<SharedMemory> SharedMemory::Create(SharedPtr<Process> owner_process, u
29 shared_memory->permissions = permissions; 28 shared_memory->permissions = permissions;
30 shared_memory->other_permissions = other_permissions; 29 shared_memory->other_permissions = other_permissions;
31 30
32 if (address == 0) { 31 auto& vm_manager = shared_memory->owner_process->vm_manager;
33 // We need to allocate a block from the Linear Heap ourselves. 32
34 // We'll manually allocate some memory from the linear heap in the specified region. 33 // The memory is already available and mapped in the owner process.
35 MemoryRegionInfo* memory_region = GetMemoryRegion(region); 34 auto vma = vm_manager.FindVMA(address);
36 auto& linheap_memory = memory_region->linear_heap_memory; 35 ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
37 36 ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
38 ASSERT_MSG(linheap_memory->size() + size <= memory_region->size, 37
39 "Not enough space in region to allocate shared memory!"); 38 // The returned VMA might be a bigger one encompassing the desired address.
40 39 auto vma_offset = address - vma->first;
41 shared_memory->backing_block = linheap_memory; 40 ASSERT_MSG(vma_offset + size <= vma->second.size,
42 shared_memory->backing_block_offset = linheap_memory->size(); 41 "Shared memory exceeds bounds of mapped block");
43 // Allocate some memory from the end of the linear heap for this region.
44 linheap_memory->insert(linheap_memory->end(), size, 0);
45 memory_region->used += size;
46
47 shared_memory->linear_heap_phys_address =
48 Memory::FCRAM_PADDR + memory_region->base +
49 static_cast<PAddr>(shared_memory->backing_block_offset);
50
51 // Increase the amount of used linear heap memory for the owner process.
52 if (shared_memory->owner_process != nullptr) {
53 shared_memory->owner_process->linear_heap_used += size;
54 }
55
56 // Refresh the address mappings for the current process.
57 if (Core::CurrentProcess() != nullptr) {
58 Core::CurrentProcess()->vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
59 }
60 } else {
61 auto& vm_manager = shared_memory->owner_process->vm_manager;
62 // The memory is already available and mapped in the owner process.
63 auto vma = vm_manager.FindVMA(address);
64 ASSERT_MSG(vma != vm_manager.vma_map.end(), "Invalid memory address");
65 ASSERT_MSG(vma->second.backing_block, "Backing block doesn't exist for address");
66
67 // The returned VMA might be a bigger one encompassing the desired address.
68 auto vma_offset = address - vma->first;
69 ASSERT_MSG(vma_offset + size <= vma->second.size,
70 "Shared memory exceeds bounds of mapped block");
71
72 shared_memory->backing_block = vma->second.backing_block;
73 shared_memory->backing_block_offset = vma->second.offset + vma_offset;
74 }
75 42
43 shared_memory->backing_block = vma->second.backing_block;
44 shared_memory->backing_block_offset = vma->second.offset + vma_offset;
76 shared_memory->base_address = address; 45 shared_memory->base_address = address;
46
77 return shared_memory; 47 return shared_memory;
78} 48}
79 49
@@ -124,11 +94,6 @@ ResultCode SharedMemory::Map(Process* target_process, VAddr address, MemoryPermi
124 94
125 VAddr target_address = address; 95 VAddr target_address = address;
126 96
127 if (base_address == 0 && target_address == 0) {
128 // Calculate the address at which to map the memory block.
129 target_address = Memory::PhysicalToVirtualAddress(linear_heap_phys_address).value();
130 }
131
132 // Map the memory block into the target process 97 // Map the memory block into the target process
133 auto result = target_process->vm_manager.MapMemoryBlock( 98 auto result = target_process->vm_manager.MapMemoryBlock(
134 target_address, backing_block, backing_block_offset, size, MemoryState::Shared); 99 target_address, backing_block, backing_block_offset, size, MemoryState::Shared);
diff --git a/src/core/hle/kernel/shared_memory.h b/src/core/hle/kernel/shared_memory.h
index 8a6f68529..c50fee615 100644
--- a/src/core/hle/kernel/shared_memory.h
+++ b/src/core/hle/kernel/shared_memory.h
@@ -111,9 +111,6 @@ public:
111 SharedPtr<Process> owner_process; 111 SharedPtr<Process> owner_process;
112 /// Address of shared memory block in the owner process if specified. 112 /// Address of shared memory block in the owner process if specified.
113 VAddr base_address; 113 VAddr base_address;
114 /// Physical address of the shared memory block in the linear heap if no address was specified
115 /// during creation.
116 PAddr linear_heap_phys_address;
117 /// Backing memory for this shared memory block. 114 /// Backing memory for this shared memory block.
118 std::shared_ptr<std::vector<u8>> backing_block; 115 std::shared_ptr<std::vector<u8>> backing_block;
119 /// Offset into the backing block for this shared memory. 116 /// Offset into the backing block for this shared memory.
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index cdb8120f2..ea9554cbb 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -20,7 +20,6 @@
20#include "core/core_timing_util.h" 20#include "core/core_timing_util.h"
21#include "core/hle/kernel/errors.h" 21#include "core/hle/kernel/errors.h"
22#include "core/hle/kernel/handle_table.h" 22#include "core/hle/kernel/handle_table.h"
23#include "core/hle/kernel/memory.h"
24#include "core/hle/kernel/object.h" 23#include "core/hle/kernel/object.h"
25#include "core/hle/kernel/process.h" 24#include "core/hle/kernel/process.h"
26#include "core/hle/kernel/thread.h" 25#include "core/hle/kernel/thread.h"
@@ -81,8 +80,8 @@ void Thread::Stop() {
81 wait_objects.clear(); 80 wait_objects.clear();
82 81
83 // Mark the TLS slot in the thread's page as free. 82 // Mark the TLS slot in the thread's page as free.
84 u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE; 83 const u64 tls_page = (tls_address - Memory::TLS_AREA_VADDR) / Memory::PAGE_SIZE;
85 u64 tls_slot = 84 const u64 tls_slot =
86 ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE; 85 ((tls_address - Memory::TLS_AREA_VADDR) % Memory::PAGE_SIZE) / Memory::TLS_ENTRY_SIZE;
87 Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot); 86 Core::CurrentProcess()->tls_slots[tls_page].reset(tls_slot);
88} 87}
@@ -336,38 +335,10 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
336 auto& tls_slots = owner_process->tls_slots; 335 auto& tls_slots = owner_process->tls_slots;
337 336
338 auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots); 337 auto [available_page, available_slot, needs_allocation] = GetFreeThreadLocalSlot(tls_slots);
339
340 if (needs_allocation) { 338 if (needs_allocation) {
341 // There are no already-allocated pages with free slots, lets allocate a new one.
342 // TLS pages are allocated from the BASE region in the linear heap.
343 MemoryRegionInfo* memory_region = GetMemoryRegion(MemoryRegion::BASE);
344 auto& linheap_memory = memory_region->linear_heap_memory;
345
346 if (linheap_memory->size() + Memory::PAGE_SIZE > memory_region->size) {
347 LOG_ERROR(Kernel_SVC,
348 "Not enough space in region to allocate a new TLS page for thread");
349 return ERR_OUT_OF_MEMORY;
350 }
351
352 size_t offset = linheap_memory->size();
353
354 // Allocate some memory from the end of the linear heap for this region.
355 linheap_memory->insert(linheap_memory->end(), Memory::PAGE_SIZE, 0);
356 memory_region->used += Memory::PAGE_SIZE;
357 owner_process->linear_heap_used += Memory::PAGE_SIZE;
358
359 tls_slots.emplace_back(0); // The page is completely available at the start 339 tls_slots.emplace_back(0); // The page is completely available at the start
360 available_page = tls_slots.size() - 1; 340 available_page = tls_slots.size() - 1;
361 available_slot = 0; // Use the first slot in the new page 341 available_slot = 0; // Use the first slot in the new page
362
363 auto& vm_manager = owner_process->vm_manager;
364 vm_manager.RefreshMemoryBlockMappings(linheap_memory.get());
365
366 // Map the page to the current process' address space.
367 // TODO(Subv): Find the correct MemoryState for this region.
368 vm_manager.MapMemoryBlock(Memory::TLS_AREA_VADDR + available_page * Memory::PAGE_SIZE,
369 linheap_memory, offset, Memory::PAGE_SIZE,
370 MemoryState::ThreadLocal);
371 } 342 }
372 343
373 // Mark the slot as used 344 // Mark the slot as used