diff options
| -rw-r--r-- | src/core/CMakeLists.txt | 2 | ||||
| -rw-r--r-- | src/core/core.cpp | 6 | ||||
| -rw-r--r-- | src/core/core.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.cpp | 90 | ||||
| -rw-r--r-- | src/core/hle/kernel/memory.h | 34 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 78 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 17 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.cpp | 63 | ||||
| -rw-r--r-- | src/core/hle/kernel/shared_memory.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 33 | ||||
| -rw-r--r-- | src/core/memory.cpp | 106 | ||||
| -rw-r--r-- | src/core/memory.h | 88 | ||||
| -rw-r--r-- | src/tests/CMakeLists.txt | 1 | ||||
| -rw-r--r-- | src/tests/core/memory/memory.cpp | 56 |
16 files changed, 29 insertions, 559 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d29f6a84f..19c629afe 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -63,8 +63,6 @@ add_library(core STATIC | |||
| 63 | hle/kernel/hle_ipc.h | 63 | hle/kernel/hle_ipc.h |
| 64 | hle/kernel/kernel.cpp | 64 | hle/kernel/kernel.cpp |
| 65 | hle/kernel/kernel.h | 65 | hle/kernel/kernel.h |
| 66 | hle/kernel/memory.cpp | ||
| 67 | hle/kernel/memory.h | ||
| 68 | hle/kernel/mutex.cpp | 66 | hle/kernel/mutex.cpp |
| 69 | hle/kernel/mutex.h | 67 | hle/kernel/mutex.h |
| 70 | hle/kernel/object.cpp | 68 | hle/kernel/object.cpp |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 54fc4170f..9824769cf 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -110,7 +110,7 @@ System::ResultStatus System::Load(EmuWindow& emu_window, const std::string& file | |||
| 110 | } | 110 | } |
| 111 | } | 111 | } |
| 112 | 112 | ||
| 113 | ResultStatus init_result{Init(emu_window, system_mode.first.get())}; | 113 | ResultStatus init_result{Init(emu_window)}; |
| 114 | if (init_result != ResultStatus::Success) { | 114 | if (init_result != ResultStatus::Success) { |
| 115 | LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", | 115 | LOG_CRITICAL(Core, "Failed to initialize system (Error {})!", |
| 116 | static_cast<int>(init_result)); | 116 | static_cast<int>(init_result)); |
| @@ -161,7 +161,7 @@ Cpu& System::CpuCore(size_t core_index) { | |||
| 161 | return *cpu_cores[core_index]; | 161 | return *cpu_cores[core_index]; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { | 164 | System::ResultStatus System::Init(EmuWindow& emu_window) { |
| 165 | LOG_DEBUG(HW_Memory, "initialized OK"); | 165 | LOG_DEBUG(HW_Memory, "initialized OK"); |
| 166 | 166 | ||
| 167 | CoreTiming::Init(); | 167 | CoreTiming::Init(); |
| @@ -178,7 +178,7 @@ System::ResultStatus System::Init(EmuWindow& emu_window, u32 system_mode) { | |||
| 178 | telemetry_session = std::make_unique<Core::TelemetrySession>(); | 178 | telemetry_session = std::make_unique<Core::TelemetrySession>(); |
| 179 | service_manager = std::make_shared<Service::SM::ServiceManager>(); | 179 | service_manager = std::make_shared<Service::SM::ServiceManager>(); |
| 180 | 180 | ||
| 181 | Kernel::Init(system_mode); | 181 | Kernel::Init(); |
| 182 | Service::Init(service_manager); | 182 | Service::Init(service_manager); |
| 183 | GDBStub::Init(); | 183 | GDBStub::Init(); |
| 184 | 184 | ||
diff --git a/src/core/core.h b/src/core/core.h index f8b6644bb..ed475ac4e 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -189,10 +189,9 @@ private: | |||
| 189 | * Initialize the emulated system. | 189 | * Initialize the emulated system. |
| 190 | * @param emu_window Reference to the host-system window used for video output and keyboard | 190 | * @param emu_window Reference to the host-system window used for video output and keyboard |
| 191 | * input. | 191 | * input. |
| 192 | * @param system_mode The system mode. | ||
| 193 | * @return ResultStatus code, indicating if the operation succeeded. | 192 | * @return ResultStatus code, indicating if the operation succeeded. |
| 194 | */ | 193 | */ |
| 195 | ResultStatus Init(EmuWindow& emu_window, u32 system_mode); | 194 | ResultStatus Init(EmuWindow& emu_window); |
| 196 | 195 | ||
| 197 | /// AppLoader used to load the current executing application | 196 | /// AppLoader used to load the current executing application |
| 198 | std::unique_ptr<Loader::AppLoader> app_loader; | 197 | std::unique_ptr<Loader::AppLoader> app_loader; |
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 { | |||
| 15 | unsigned int Object::next_object_id; | 14 | unsigned int Object::next_object_id; |
| 16 | 15 | ||
| 17 | /// Initialize the kernel | 16 | /// Initialize the kernel |
| 18 | void Init(u32 system_mode) { | 17 | void 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 @@ | |||
| 9 | namespace Kernel { | 9 | namespace Kernel { |
| 10 | 10 | ||
| 11 | /// Initialize the kernel with the specified system mode. | 11 | /// Initialize the kernel with the specified system mode. |
| 12 | void Init(u32 system_mode); | 12 | void Init(); |
| 13 | 13 | ||
| 14 | /// Shutdown the kernel | 14 | /// Shutdown the kernel |
| 15 | void Shutdown(); | 15 | void 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 | |||
| 20 | namespace Kernel { | ||
| 21 | |||
| 22 | MemoryRegionInfo memory_regions[3]; | ||
| 23 | |||
| 24 | /// Size of the APPLICATION, SYSTEM and BASE memory regions (respectively) for each system | ||
| 25 | /// memory configuration type. | ||
| 26 | static 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 | |||
| 40 | void 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 | |||
| 64 | void 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 | |||
| 73 | MemoryRegionInfo* 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 | |||
| 86 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping) {} | ||
| 87 | |||
| 88 | void 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 | |||
| 12 | namespace Kernel { | ||
| 13 | |||
| 14 | class VMManager; | ||
| 15 | enum class MemoryRegion : u16; | ||
| 16 | struct AddressMapping; | ||
| 17 | |||
| 18 | struct 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 | |||
| 26 | void MemoryInit(u32 mem_type); | ||
| 27 | void MemoryShutdown(); | ||
| 28 | MemoryRegionInfo* GetMemoryRegion(MemoryRegion region); | ||
| 29 | |||
| 30 | void HandleSpecialMapping(VMManager& address_space, const AddressMapping& mapping); | ||
| 31 | void MapSharedPages(VMManager& address_space); | ||
| 32 | |||
| 33 | extern 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 | ||
| 143 | void Process::LoadModule(SharedPtr<CodeSet> module_, VAddr base_addr) { | 134 | void 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 | ||
| 163 | VAddr 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 | |||
| 169 | VAddr Process::GetLinearHeapBase() const { | ||
| 170 | return GetLinearHeapAreaAddress() + memory_region->base; | ||
| 171 | } | ||
| 172 | |||
| 173 | VAddr Process::GetLinearHeapLimit() const { | ||
| 174 | return GetLinearHeapBase() + memory_region->size; | ||
| 175 | } | ||
| 176 | |||
| 177 | ResultVal<VAddr> Process::HeapAllocate(VAddr target, u64 size, VMAPermission perms) { | 150 | ResultVal<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 | |||
| 234 | ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission perms) { | ||
| 235 | UNIMPLEMENTED(); | ||
| 236 | return {}; | ||
| 237 | } | ||
| 238 | |||
| 239 | ResultCode 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 { | |||
| 53 | enum class ProcessStatus { Created, Running, Exited }; | 53 | enum class ProcessStatus { Created, Running, Exited }; |
| 54 | 54 | ||
| 55 | class ResourceLimit; | 55 | class ResourceLimit; |
| 56 | struct MemoryRegionInfo; | ||
| 57 | 56 | ||
| 58 | struct CodeSet final : public Object { | 57 | struct 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 |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index e753e3436..0d41b2527 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -14,7 +14,6 @@ | |||
| 14 | #include "common/swap.h" | 14 | #include "common/swap.h" |
| 15 | #include "core/arm/arm_interface.h" | 15 | #include "core/arm/arm_interface.h" |
| 16 | #include "core/core.h" | 16 | #include "core/core.h" |
| 17 | #include "core/hle/kernel/memory.h" | ||
| 18 | #include "core/hle/kernel/process.h" | 17 | #include "core/hle/kernel/process.h" |
| 19 | #include "core/hle/lock.h" | 18 | #include "core/hle/lock.h" |
| 20 | #include "core/memory.h" | 19 | #include "core/memory.h" |
| @@ -24,8 +23,6 @@ | |||
| 24 | 23 | ||
| 25 | namespace Memory { | 24 | namespace Memory { |
| 26 | 25 | ||
| 27 | static std::array<u8, Memory::VRAM_SIZE> vram; | ||
| 28 | |||
| 29 | static PageTable* current_page_table = nullptr; | 26 | static PageTable* current_page_table = nullptr; |
| 30 | 27 | ||
| 31 | void SetCurrentPageTable(PageTable* page_table) { | 28 | void SetCurrentPageTable(PageTable* page_table) { |
| @@ -242,10 +239,6 @@ bool IsKernelVirtualAddress(const VAddr vaddr) { | |||
| 242 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; | 239 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; |
| 243 | } | 240 | } |
| 244 | 241 | ||
| 245 | bool IsValidPhysicalAddress(const PAddr paddr) { | ||
| 246 | return GetPhysicalPointer(paddr) != nullptr; | ||
| 247 | } | ||
| 248 | |||
| 249 | u8* GetPointer(const VAddr vaddr) { | 242 | u8* GetPointer(const VAddr vaddr) { |
| 250 | u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | 243 | u8* page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; |
| 251 | if (page_pointer) { | 244 | if (page_pointer) { |
| @@ -274,61 +267,6 @@ std::string ReadCString(VAddr vaddr, std::size_t max_length) { | |||
| 274 | return string; | 267 | return string; |
| 275 | } | 268 | } |
| 276 | 269 | ||
| 277 | u8* GetPhysicalPointer(PAddr address) { | ||
| 278 | struct MemoryArea { | ||
| 279 | PAddr paddr_base; | ||
| 280 | u32 size; | ||
| 281 | }; | ||
| 282 | |||
| 283 | static constexpr MemoryArea memory_areas[] = { | ||
| 284 | {VRAM_PADDR, VRAM_SIZE}, | ||
| 285 | {IO_AREA_PADDR, IO_AREA_SIZE}, | ||
| 286 | {DSP_RAM_PADDR, DSP_RAM_SIZE}, | ||
| 287 | {FCRAM_PADDR, FCRAM_N3DS_SIZE}, | ||
| 288 | }; | ||
| 289 | |||
| 290 | const auto area = | ||
| 291 | std::find_if(std::begin(memory_areas), std::end(memory_areas), [&](const auto& area) { | ||
| 292 | return address >= area.paddr_base && address < area.paddr_base + area.size; | ||
| 293 | }); | ||
| 294 | |||
| 295 | if (area == std::end(memory_areas)) { | ||
| 296 | LOG_ERROR(HW_Memory, "Unknown GetPhysicalPointer @ 0x{:016X}", address); | ||
| 297 | return nullptr; | ||
| 298 | } | ||
| 299 | |||
| 300 | if (area->paddr_base == IO_AREA_PADDR) { | ||
| 301 | LOG_ERROR(HW_Memory, "MMIO mappings are not supported yet. phys_addr={:016X}", address); | ||
| 302 | return nullptr; | ||
| 303 | } | ||
| 304 | |||
| 305 | u64 offset_into_region = address - area->paddr_base; | ||
| 306 | |||
| 307 | u8* target_pointer = nullptr; | ||
| 308 | switch (area->paddr_base) { | ||
| 309 | case VRAM_PADDR: | ||
| 310 | target_pointer = vram.data() + offset_into_region; | ||
| 311 | break; | ||
| 312 | case DSP_RAM_PADDR: | ||
| 313 | break; | ||
| 314 | case FCRAM_PADDR: | ||
| 315 | for (const auto& region : Kernel::memory_regions) { | ||
| 316 | if (offset_into_region >= region.base && | ||
| 317 | offset_into_region < region.base + region.size) { | ||
| 318 | target_pointer = | ||
| 319 | region.linear_heap_memory->data() + offset_into_region - region.base; | ||
| 320 | break; | ||
| 321 | } | ||
| 322 | } | ||
| 323 | ASSERT_MSG(target_pointer != nullptr, "Invalid FCRAM address"); | ||
| 324 | break; | ||
| 325 | default: | ||
| 326 | UNREACHABLE(); | ||
| 327 | } | ||
| 328 | |||
| 329 | return target_pointer; | ||
| 330 | } | ||
| 331 | |||
| 332 | void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) { | 270 | void RasterizerMarkRegionCached(Tegra::GPUVAddr gpu_addr, u64 size, bool cached) { |
| 333 | if (gpu_addr == 0) { | 271 | if (gpu_addr == 0) { |
| 334 | return; | 272 | return; |
| @@ -666,48 +604,4 @@ void CopyBlock(VAddr dest_addr, VAddr src_addr, size_t size) { | |||
| 666 | CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size); | 604 | CopyBlock(*Core::CurrentProcess(), dest_addr, src_addr, size); |
| 667 | } | 605 | } |
| 668 | 606 | ||
| 669 | boost::optional<PAddr> TryVirtualToPhysicalAddress(const VAddr addr) { | ||
| 670 | if (addr == 0) { | ||
| 671 | return 0; | ||
| 672 | } else if (addr >= VRAM_VADDR && addr < VRAM_VADDR_END) { | ||
| 673 | return addr - VRAM_VADDR + VRAM_PADDR; | ||
| 674 | } else if (addr >= LINEAR_HEAP_VADDR && addr < LINEAR_HEAP_VADDR_END) { | ||
| 675 | return addr - LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||
| 676 | } else if (addr >= NEW_LINEAR_HEAP_VADDR && addr < NEW_LINEAR_HEAP_VADDR_END) { | ||
| 677 | return addr - NEW_LINEAR_HEAP_VADDR + FCRAM_PADDR; | ||
| 678 | } else if (addr >= DSP_RAM_VADDR && addr < DSP_RAM_VADDR_END) { | ||
| 679 | return addr - DSP_RAM_VADDR + DSP_RAM_PADDR; | ||
| 680 | } else if (addr >= IO_AREA_VADDR && addr < IO_AREA_VADDR_END) { | ||
| 681 | return addr - IO_AREA_VADDR + IO_AREA_PADDR; | ||
| 682 | } | ||
| 683 | |||
| 684 | return boost::none; | ||
| 685 | } | ||
| 686 | |||
| 687 | PAddr VirtualToPhysicalAddress(const VAddr addr) { | ||
| 688 | auto paddr = TryVirtualToPhysicalAddress(addr); | ||
| 689 | if (!paddr) { | ||
| 690 | LOG_ERROR(HW_Memory, "Unknown virtual address @ 0x{:016X}", addr); | ||
| 691 | // To help with debugging, set bit on address so that it's obviously invalid. | ||
| 692 | return addr | 0x80000000; | ||
| 693 | } | ||
| 694 | return *paddr; | ||
| 695 | } | ||
| 696 | |||
| 697 | boost::optional<VAddr> PhysicalToVirtualAddress(const PAddr addr) { | ||
| 698 | if (addr == 0) { | ||
| 699 | return 0; | ||
| 700 | } else if (addr >= VRAM_PADDR && addr < VRAM_PADDR_END) { | ||
| 701 | return addr - VRAM_PADDR + VRAM_VADDR; | ||
| 702 | } else if (addr >= FCRAM_PADDR && addr < FCRAM_PADDR_END) { | ||
| 703 | return addr - FCRAM_PADDR + Core::CurrentProcess()->GetLinearHeapAreaAddress(); | ||
| 704 | } else if (addr >= DSP_RAM_PADDR && addr < DSP_RAM_PADDR_END) { | ||
| 705 | return addr - DSP_RAM_PADDR + DSP_RAM_VADDR; | ||
| 706 | } else if (addr >= IO_AREA_PADDR && addr < IO_AREA_PADDR_END) { | ||
| 707 | return addr - IO_AREA_PADDR + IO_AREA_VADDR; | ||
| 708 | } | ||
| 709 | |||
| 710 | return boost::none; | ||
| 711 | } | ||
| 712 | |||
| 713 | } // namespace Memory | 607 | } // namespace Memory |
diff --git a/src/core/memory.h b/src/core/memory.h index 8d5d017a4..b5d885b8a 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -6,12 +6,9 @@ | |||
| 6 | 6 | ||
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstddef> | 8 | #include <cstddef> |
| 9 | #include <map> | ||
| 10 | #include <string> | 9 | #include <string> |
| 11 | #include <tuple> | 10 | #include <tuple> |
| 12 | #include <vector> | ||
| 13 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| 14 | #include <boost/optional.hpp> | ||
| 15 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 16 | #include "core/memory_hook.h" | 13 | #include "core/memory_hook.h" |
| 17 | #include "video_core/memory_manager.h" | 14 | #include "video_core/memory_manager.h" |
| @@ -85,40 +82,6 @@ struct PageTable { | |||
| 85 | std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; | 82 | std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; |
| 86 | }; | 83 | }; |
| 87 | 84 | ||
| 88 | /// Physical memory regions as seen from the ARM11 | ||
| 89 | enum : PAddr { | ||
| 90 | /// IO register area | ||
| 91 | IO_AREA_PADDR = 0x10100000, | ||
| 92 | IO_AREA_SIZE = 0x01000000, ///< IO area size (16MB) | ||
| 93 | IO_AREA_PADDR_END = IO_AREA_PADDR + IO_AREA_SIZE, | ||
| 94 | |||
| 95 | /// MPCore internal memory region | ||
| 96 | MPCORE_RAM_PADDR = 0x17E00000, | ||
| 97 | MPCORE_RAM_SIZE = 0x00002000, ///< MPCore internal memory size (8KB) | ||
| 98 | MPCORE_RAM_PADDR_END = MPCORE_RAM_PADDR + MPCORE_RAM_SIZE, | ||
| 99 | |||
| 100 | /// Video memory | ||
| 101 | VRAM_PADDR = 0x18000000, | ||
| 102 | VRAM_SIZE = 0x00600000, ///< VRAM size (6MB) | ||
| 103 | VRAM_PADDR_END = VRAM_PADDR + VRAM_SIZE, | ||
| 104 | |||
| 105 | /// DSP memory | ||
| 106 | DSP_RAM_PADDR = 0x1FF00000, | ||
| 107 | DSP_RAM_SIZE = 0x00080000, ///< DSP memory size (512KB) | ||
| 108 | DSP_RAM_PADDR_END = DSP_RAM_PADDR + DSP_RAM_SIZE, | ||
| 109 | |||
| 110 | /// AXI WRAM | ||
| 111 | AXI_WRAM_PADDR = 0x1FF80000, | ||
| 112 | AXI_WRAM_SIZE = 0x00080000, ///< AXI WRAM size (512KB) | ||
| 113 | AXI_WRAM_PADDR_END = AXI_WRAM_PADDR + AXI_WRAM_SIZE, | ||
| 114 | |||
| 115 | /// Main FCRAM | ||
| 116 | FCRAM_PADDR = 0x20000000, | ||
| 117 | FCRAM_SIZE = 0x08000000, ///< FCRAM size on the Old 3DS (128MB) | ||
| 118 | FCRAM_N3DS_SIZE = 0x10000000, ///< FCRAM size on the New 3DS (256MB) | ||
| 119 | FCRAM_PADDR_END = FCRAM_PADDR + FCRAM_SIZE, | ||
| 120 | }; | ||
| 121 | |||
| 122 | /// Virtual user-space memory regions | 85 | /// Virtual user-space memory regions |
| 123 | enum : VAddr { | 86 | enum : VAddr { |
| 124 | /// Where the application text, data and bss reside. | 87 | /// Where the application text, data and bss reside. |
| @@ -126,24 +89,6 @@ enum : VAddr { | |||
| 126 | PROCESS_IMAGE_MAX_SIZE = 0x08000000, | 89 | PROCESS_IMAGE_MAX_SIZE = 0x08000000, |
| 127 | PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, | 90 | PROCESS_IMAGE_VADDR_END = PROCESS_IMAGE_VADDR + PROCESS_IMAGE_MAX_SIZE, |
| 128 | 91 | ||
| 129 | /// Maps 1:1 to an offset in FCRAM. Used for HW allocations that need to be linear in physical | ||
| 130 | /// memory. | ||
| 131 | LINEAR_HEAP_VADDR = 0x14000000, | ||
| 132 | LINEAR_HEAP_SIZE = 0x08000000, | ||
| 133 | LINEAR_HEAP_VADDR_END = LINEAR_HEAP_VADDR + LINEAR_HEAP_SIZE, | ||
| 134 | |||
| 135 | /// Maps 1:1 to the IO register area. | ||
| 136 | IO_AREA_VADDR = 0x1EC00000, | ||
| 137 | IO_AREA_VADDR_END = IO_AREA_VADDR + IO_AREA_SIZE, | ||
| 138 | |||
| 139 | /// Maps 1:1 to VRAM. | ||
| 140 | VRAM_VADDR = 0x1F000000, | ||
| 141 | VRAM_VADDR_END = VRAM_VADDR + VRAM_SIZE, | ||
| 142 | |||
| 143 | /// Maps 1:1 to DSP memory. | ||
| 144 | DSP_RAM_VADDR = 0x1FF00000, | ||
| 145 | DSP_RAM_VADDR_END = DSP_RAM_VADDR + DSP_RAM_SIZE, | ||
| 146 | |||
| 147 | /// Read-only page containing kernel and system configuration values. | 92 | /// Read-only page containing kernel and system configuration values. |
| 148 | CONFIG_MEMORY_VADDR = 0x1FF80000, | 93 | CONFIG_MEMORY_VADDR = 0x1FF80000, |
| 149 | CONFIG_MEMORY_SIZE = 0x00001000, | 94 | CONFIG_MEMORY_SIZE = 0x00001000, |
| @@ -154,13 +99,8 @@ enum : VAddr { | |||
| 154 | SHARED_PAGE_SIZE = 0x00001000, | 99 | SHARED_PAGE_SIZE = 0x00001000, |
| 155 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, | 100 | SHARED_PAGE_VADDR_END = SHARED_PAGE_VADDR + SHARED_PAGE_SIZE, |
| 156 | 101 | ||
| 157 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | ||
| 158 | NEW_LINEAR_HEAP_VADDR = 0x30000000, | ||
| 159 | NEW_LINEAR_HEAP_SIZE = 0x10000000, | ||
| 160 | NEW_LINEAR_HEAP_VADDR_END = NEW_LINEAR_HEAP_VADDR + NEW_LINEAR_HEAP_SIZE, | ||
| 161 | |||
| 162 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 102 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 163 | TLS_AREA_VADDR = NEW_LINEAR_HEAP_VADDR_END, | 103 | TLS_AREA_VADDR = 0x40000000, |
| 164 | TLS_ENTRY_SIZE = 0x200, | 104 | TLS_ENTRY_SIZE = 0x200, |
| 165 | TLS_AREA_SIZE = 0x10000000, | 105 | TLS_AREA_SIZE = 0x10000000, |
| 166 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, | 106 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, |
| @@ -205,8 +145,6 @@ bool IsValidVirtualAddress(const VAddr addr); | |||
| 205 | /// Determines if the given VAddr is a kernel address | 145 | /// Determines if the given VAddr is a kernel address |
| 206 | bool IsKernelVirtualAddress(const VAddr addr); | 146 | bool IsKernelVirtualAddress(const VAddr addr); |
| 207 | 147 | ||
| 208 | bool IsValidPhysicalAddress(const PAddr addr); | ||
| 209 | |||
| 210 | u8 Read8(VAddr addr); | 148 | u8 Read8(VAddr addr); |
| 211 | u16 Read16(VAddr addr); | 149 | u16 Read16(VAddr addr); |
| 212 | u32 Read32(VAddr addr); | 150 | u32 Read32(VAddr addr); |
| @@ -230,30 +168,6 @@ u8* GetPointer(VAddr virtual_address); | |||
| 230 | 168 | ||
| 231 | std::string ReadCString(VAddr virtual_address, std::size_t max_length); | 169 | std::string ReadCString(VAddr virtual_address, std::size_t max_length); |
| 232 | 170 | ||
| 233 | /** | ||
| 234 | * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical | ||
| 235 | * address. This should be used by services to translate addresses for use by the hardware. | ||
| 236 | */ | ||
| 237 | boost::optional<PAddr> TryVirtualToPhysicalAddress(VAddr addr); | ||
| 238 | |||
| 239 | /** | ||
| 240 | * Converts a virtual address inside a region with 1:1 mapping to physical memory to a physical | ||
| 241 | * address. This should be used by services to translate addresses for use by the hardware. | ||
| 242 | * | ||
| 243 | * @deprecated Use TryVirtualToPhysicalAddress(), which reports failure. | ||
| 244 | */ | ||
| 245 | PAddr VirtualToPhysicalAddress(VAddr addr); | ||
| 246 | |||
| 247 | /** | ||
| 248 | * Undoes a mapping performed by VirtualToPhysicalAddress(). | ||
| 249 | */ | ||
| 250 | boost::optional<VAddr> PhysicalToVirtualAddress(PAddr addr); | ||
| 251 | |||
| 252 | /** | ||
| 253 | * Gets a pointer to the memory region beginning at the specified physical address. | ||
| 254 | */ | ||
| 255 | u8* GetPhysicalPointer(PAddr address); | ||
| 256 | |||
| 257 | enum class FlushMode { | 171 | enum class FlushMode { |
| 258 | /// Write back modified surfaces to RAM | 172 | /// Write back modified surfaces to RAM |
| 259 | Flush, | 173 | Flush, |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 6a0a62ecc..4d74bb395 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -3,7 +3,6 @@ add_executable(tests | |||
| 3 | core/arm/arm_test_common.cpp | 3 | core/arm/arm_test_common.cpp |
| 4 | core/arm/arm_test_common.h | 4 | core/arm/arm_test_common.h |
| 5 | core/core_timing.cpp | 5 | core/core_timing.cpp |
| 6 | core/memory/memory.cpp | ||
| 7 | glad.cpp | 6 | glad.cpp |
| 8 | tests.cpp | 7 | tests.cpp |
| 9 | ) | 8 | ) |
diff --git a/src/tests/core/memory/memory.cpp b/src/tests/core/memory/memory.cpp deleted file mode 100644 index 165496a54..000000000 --- a/src/tests/core/memory/memory.cpp +++ /dev/null | |||
| @@ -1,56 +0,0 @@ | |||
| 1 | // Copyright 2017 Citra Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <catch.hpp> | ||
| 6 | #include "core/hle/kernel/memory.h" | ||
| 7 | #include "core/hle/kernel/process.h" | ||
| 8 | #include "core/memory.h" | ||
| 9 | |||
| 10 | TEST_CASE("Memory::IsValidVirtualAddress", "[core][memory][!hide]") { | ||
| 11 | SECTION("these regions should not be mapped on an empty process") { | ||
| 12 | auto process = Kernel::Process::Create(""); | ||
| 13 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::PROCESS_IMAGE_VADDR) == false); | ||
| 14 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::HEAP_VADDR) == false); | ||
| 15 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::LINEAR_HEAP_VADDR) == false); | ||
| 16 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == false); | ||
| 17 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||
| 18 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == false); | ||
| 19 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::TLS_AREA_VADDR) == false); | ||
| 20 | } | ||
| 21 | |||
| 22 | SECTION("CONFIG_MEMORY_VADDR and SHARED_PAGE_VADDR should be valid after mapping them") { | ||
| 23 | auto process = Kernel::Process::Create(""); | ||
| 24 | Kernel::MapSharedPages(process->vm_manager); | ||
| 25 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == true); | ||
| 26 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::SHARED_PAGE_VADDR) == true); | ||
| 27 | } | ||
| 28 | |||
| 29 | SECTION("special regions should be valid after mapping them") { | ||
| 30 | auto process = Kernel::Process::Create(""); | ||
| 31 | SECTION("VRAM") { | ||
| 32 | Kernel::HandleSpecialMapping(process->vm_manager, | ||
| 33 | {Memory::VRAM_VADDR, Memory::VRAM_SIZE, false, false}); | ||
| 34 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::VRAM_VADDR) == true); | ||
| 35 | } | ||
| 36 | |||
| 37 | SECTION("IO (Not yet implemented)") { | ||
| 38 | Kernel::HandleSpecialMapping( | ||
| 39 | process->vm_manager, {Memory::IO_AREA_VADDR, Memory::IO_AREA_SIZE, false, false}); | ||
| 40 | CHECK_FALSE(Memory::IsValidVirtualAddress(*process, Memory::IO_AREA_VADDR) == true); | ||
| 41 | } | ||
| 42 | |||
| 43 | SECTION("DSP") { | ||
| 44 | Kernel::HandleSpecialMapping( | ||
| 45 | process->vm_manager, {Memory::DSP_RAM_VADDR, Memory::DSP_RAM_SIZE, false, false}); | ||
| 46 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::DSP_RAM_VADDR) == true); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | SECTION("Unmapping a VAddr should make it invalid") { | ||
| 51 | auto process = Kernel::Process::Create(""); | ||
| 52 | Kernel::MapSharedPages(process->vm_manager); | ||
| 53 | process->vm_manager.UnmapRange(Memory::CONFIG_MEMORY_VADDR, Memory::CONFIG_MEMORY_SIZE); | ||
| 54 | CHECK(Memory::IsValidVirtualAddress(*process, Memory::CONFIG_MEMORY_VADDR) == false); | ||
| 55 | } | ||
| 56 | } | ||