diff options
| author | 2018-09-24 10:29:56 -0400 | |
|---|---|---|
| committer | 2018-09-24 22:15:53 -0400 | |
| commit | 7fd598636e819d4e86874b20081945936a05c5f1 (patch) | |
| tree | 046da702e80db7f8f5d75521b7864a1b7eb822a3 | |
| parent | process/vm_manager: Amend API to allow reading parameters from NPDM metadata (diff) | |
| download | yuzu-7fd598636e819d4e86874b20081945936a05c5f1.tar.gz yuzu-7fd598636e819d4e86874b20081945936a05c5f1.tar.xz yuzu-7fd598636e819d4e86874b20081945936a05c5f1.zip | |
memory: Dehardcode the use of a 36-bit address space
Given games can also request a 32-bit or 39-bit address space, we
shouldn't be hardcoding the address space range as 36-bit.
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 5 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.cpp | 18 | ||||
| -rw-r--r-- | src/core/hle/kernel/vm_manager.h | 3 | ||||
| -rw-r--r-- | src/core/memory.cpp | 18 | ||||
| -rw-r--r-- | src/core/memory.h | 32 | ||||
| -rw-r--r-- | src/tests/core/arm/arm_test_common.cpp | 7 |
6 files changed, 61 insertions, 22 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index 7be5a38de..928bbc096 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp | |||
| @@ -129,7 +129,8 @@ public: | |||
| 129 | }; | 129 | }; |
| 130 | 130 | ||
| 131 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | 131 | std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { |
| 132 | auto** const page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data(); | 132 | auto& current_process = Core::CurrentProcess(); |
| 133 | auto** const page_table = current_process->vm_manager.page_table.pointers.data(); | ||
| 133 | 134 | ||
| 134 | Dynarmic::A64::UserConfig config; | 135 | Dynarmic::A64::UserConfig config; |
| 135 | 136 | ||
| @@ -138,7 +139,7 @@ std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { | |||
| 138 | 139 | ||
| 139 | // Memory | 140 | // Memory |
| 140 | config.page_table = reinterpret_cast<void**>(page_table); | 141 | config.page_table = reinterpret_cast<void**>(page_table); |
| 141 | config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS; | 142 | config.page_table_address_space_bits = current_process->vm_manager.GetAddressSpaceWidth(); |
| 142 | config.silently_mirror_page_table = false; | 143 | config.silently_mirror_page_table = false; |
| 143 | 144 | ||
| 144 | // Multi-process state | 145 | // Multi-process state |
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp index 337f17b7b..20d06f000 100644 --- a/src/core/hle/kernel/vm_manager.cpp +++ b/src/core/hle/kernel/vm_manager.cpp | |||
| @@ -66,18 +66,21 @@ VMManager::~VMManager() { | |||
| 66 | 66 | ||
| 67 | void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { | 67 | void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { |
| 68 | Clear(); | 68 | Clear(); |
| 69 | |||
| 69 | InitializeMemoryRegionRanges(type); | 70 | InitializeMemoryRegionRanges(type); |
| 70 | 71 | ||
| 72 | page_table.Resize(address_space_width); | ||
| 73 | |||
| 71 | // Initialize the map with a single free region covering the entire managed space. | 74 | // Initialize the map with a single free region covering the entire managed space. |
| 72 | VirtualMemoryArea initial_vma; | 75 | VirtualMemoryArea initial_vma; |
| 73 | initial_vma.size = MAX_ADDRESS; | 76 | initial_vma.size = address_space_end; |
| 74 | vma_map.emplace(initial_vma.base, initial_vma); | 77 | vma_map.emplace(initial_vma.base, initial_vma); |
| 75 | 78 | ||
| 76 | UpdatePageTableForVMA(initial_vma); | 79 | UpdatePageTableForVMA(initial_vma); |
| 77 | } | 80 | } |
| 78 | 81 | ||
| 79 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { | 82 | VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { |
| 80 | if (target >= MAX_ADDRESS) { | 83 | if (target >= address_space_end) { |
| 81 | return vma_map.end(); | 84 | return vma_map.end(); |
| 82 | } else { | 85 | } else { |
| 83 | return std::prev(vma_map.upper_bound(target)); | 86 | return std::prev(vma_map.upper_bound(target)); |
| @@ -291,7 +294,7 @@ ResultVal<VMManager::VMAIter> VMManager::CarveVMARange(VAddr target, u64 size) { | |||
| 291 | 294 | ||
| 292 | const VAddr target_end = target + size; | 295 | const VAddr target_end = target + size; |
| 293 | ASSERT(target_end >= target); | 296 | ASSERT(target_end >= target); |
| 294 | ASSERT(target_end <= MAX_ADDRESS); | 297 | ASSERT(target_end <= address_space_end); |
| 295 | ASSERT(size > 0); | 298 | ASSERT(size > 0); |
| 296 | 299 | ||
| 297 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); | 300 | VMAIter begin_vma = StripIterConstness(FindVMA(target)); |
| @@ -455,9 +458,10 @@ void VMManager::ClearVMAMap() { | |||
| 455 | } | 458 | } |
| 456 | 459 | ||
| 457 | void VMManager::ClearPageTable() { | 460 | void VMManager::ClearPageTable() { |
| 458 | page_table.pointers.fill(nullptr); | 461 | std::fill(page_table.pointers.begin(), page_table.pointers.end(), nullptr); |
| 459 | page_table.special_regions.clear(); | 462 | page_table.special_regions.clear(); |
| 460 | page_table.attributes.fill(Memory::PageType::Unmapped); | 463 | std::fill(page_table.attributes.begin(), page_table.attributes.end(), |
| 464 | Memory::PageType::Unmapped); | ||
| 461 | } | 465 | } |
| 462 | 466 | ||
| 463 | u64 VMManager::GetTotalMemoryUsage() const { | 467 | u64 VMManager::GetTotalMemoryUsage() const { |
| @@ -480,6 +484,10 @@ u64 VMManager::GetAddressSpaceSize() const { | |||
| 480 | return MAX_ADDRESS; | 484 | return MAX_ADDRESS; |
| 481 | } | 485 | } |
| 482 | 486 | ||
| 487 | u64 VMManager::GetAddressSpaceWidth() const { | ||
| 488 | return address_space_width; | ||
| 489 | } | ||
| 490 | |||
| 483 | VAddr VMManager::GetCodeRegionBaseAddress() const { | 491 | VAddr VMManager::GetCodeRegionBaseAddress() const { |
| 484 | return code_region_base; | 492 | return code_region_base; |
| 485 | } | 493 | } |
diff --git a/src/core/hle/kernel/vm_manager.h b/src/core/hle/kernel/vm_manager.h index 0ce240126..581bf3d00 100644 --- a/src/core/hle/kernel/vm_manager.h +++ b/src/core/hle/kernel/vm_manager.h | |||
| @@ -205,6 +205,9 @@ public: | |||
| 205 | /// Gets the total address space address size, used by svcGetInfo | 205 | /// Gets the total address space address size, used by svcGetInfo |
| 206 | u64 GetAddressSpaceSize() const; | 206 | u64 GetAddressSpaceSize() const; |
| 207 | 207 | ||
| 208 | /// Gets the address space width in bits. | ||
| 209 | u64 GetAddressSpaceWidth() const; | ||
| 210 | |||
| 208 | /// Gets the base address of the code region. | 211 | /// Gets the base address of the code region. |
| 209 | VAddr GetCodeRegionBaseAddress() const; | 212 | VAddr GetCodeRegionBaseAddress() const; |
| 210 | 213 | ||
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 316b46820..674ef0829 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -3,7 +3,6 @@ | |||
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <array> | ||
| 7 | #include <cstring> | 6 | #include <cstring> |
| 8 | #include <utility> | 7 | #include <utility> |
| 9 | 8 | ||
| @@ -41,6 +40,21 @@ PageTable* GetCurrentPageTable() { | |||
| 41 | return current_page_table; | 40 | return current_page_table; |
| 42 | } | 41 | } |
| 43 | 42 | ||
| 43 | PageTable::PageTable() = default; | ||
| 44 | |||
| 45 | PageTable::PageTable(std::size_t address_space_width_in_bits) { | ||
| 46 | Resize(address_space_width_in_bits); | ||
| 47 | } | ||
| 48 | |||
| 49 | PageTable::~PageTable() = default; | ||
| 50 | |||
| 51 | void PageTable::Resize(std::size_t address_space_width_in_bits) { | ||
| 52 | const std::size_t num_page_table_entries = 1ULL << (address_space_width_in_bits - PAGE_BITS); | ||
| 53 | |||
| 54 | pointers.resize(num_page_table_entries); | ||
| 55 | attributes.resize(num_page_table_entries); | ||
| 56 | } | ||
| 57 | |||
| 44 | static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { | 58 | static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { |
| 45 | LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, | 59 | LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, |
| 46 | (base + size) * PAGE_SIZE); | 60 | (base + size) * PAGE_SIZE); |
| @@ -50,7 +64,7 @@ static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, Pa | |||
| 50 | 64 | ||
| 51 | VAddr end = base + size; | 65 | VAddr end = base + size; |
| 52 | while (base != end) { | 66 | while (base != end) { |
| 53 | ASSERT_MSG(base < PAGE_TABLE_NUM_ENTRIES, "out of range mapping at {:016X}", base); | 67 | ASSERT_MSG(base < page_table.pointers.size(), "out of range mapping at {:016X}", base); |
| 54 | 68 | ||
| 55 | page_table.attributes[base] = type; | 69 | page_table.attributes[base] = type; |
| 56 | page_table.pointers[base] = memory; | 70 | page_table.pointers[base] = memory; |
diff --git a/src/core/memory.h b/src/core/memory.h index 2a27c0251..739e5be94 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -4,10 +4,10 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 8 | #include <cstddef> | 7 | #include <cstddef> |
| 9 | #include <string> | 8 | #include <string> |
| 10 | #include <tuple> | 9 | #include <tuple> |
| 10 | #include <vector> | ||
| 11 | #include <boost/icl/interval_map.hpp> | 11 | #include <boost/icl/interval_map.hpp> |
| 12 | #include "common/common_types.h" | 12 | #include "common/common_types.h" |
| 13 | #include "core/memory_hook.h" | 13 | #include "core/memory_hook.h" |
| @@ -23,10 +23,8 @@ namespace Memory { | |||
| 23 | * be mapped. | 23 | * be mapped. |
| 24 | */ | 24 | */ |
| 25 | constexpr std::size_t PAGE_BITS = 12; | 25 | constexpr std::size_t PAGE_BITS = 12; |
| 26 | constexpr u64 PAGE_SIZE = 1 << PAGE_BITS; | 26 | constexpr u64 PAGE_SIZE = 1ULL << PAGE_BITS; |
| 27 | constexpr u64 PAGE_MASK = PAGE_SIZE - 1; | 27 | constexpr u64 PAGE_MASK = PAGE_SIZE - 1; |
| 28 | constexpr std::size_t ADDRESS_SPACE_BITS = 36; | ||
| 29 | constexpr std::size_t PAGE_TABLE_NUM_ENTRIES = 1ULL << (ADDRESS_SPACE_BITS - PAGE_BITS); | ||
| 30 | 28 | ||
| 31 | enum class PageType : u8 { | 29 | enum class PageType : u8 { |
| 32 | /// Page is unmapped and should cause an access error. | 30 | /// Page is unmapped and should cause an access error. |
| @@ -62,23 +60,35 @@ struct SpecialRegion { | |||
| 62 | * mimics the way a real CPU page table works. | 60 | * mimics the way a real CPU page table works. |
| 63 | */ | 61 | */ |
| 64 | struct PageTable { | 62 | struct PageTable { |
| 63 | explicit PageTable(); | ||
| 64 | explicit PageTable(std::size_t address_space_width_in_bits); | ||
| 65 | ~PageTable(); | ||
| 66 | |||
| 67 | /** | ||
| 68 | * Resizes the page table to be able to accomodate enough pages within | ||
| 69 | * a given address space. | ||
| 70 | * | ||
| 71 | * @param address_space_width_in_bits The address size width in bits. | ||
| 72 | */ | ||
| 73 | void Resize(std::size_t address_space_width_in_bits); | ||
| 74 | |||
| 65 | /** | 75 | /** |
| 66 | * Array of memory pointers backing each page. An entry can only be non-null if the | 76 | * Vector of memory pointers backing each page. An entry can only be non-null if the |
| 67 | * corresponding entry in the `attributes` array is of type `Memory`. | 77 | * corresponding entry in the `attributes` vector is of type `Memory`. |
| 68 | */ | 78 | */ |
| 69 | std::array<u8*, PAGE_TABLE_NUM_ENTRIES> pointers; | 79 | std::vector<u8*> pointers; |
| 70 | 80 | ||
| 71 | /** | 81 | /** |
| 72 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` array is of | 82 | * Contains MMIO handlers that back memory regions whose entries in the `attribute` vector is |
| 73 | * type `Special`. | 83 | * of type `Special`. |
| 74 | */ | 84 | */ |
| 75 | boost::icl::interval_map<VAddr, std::set<SpecialRegion>> special_regions; | 85 | boost::icl::interval_map<VAddr, std::set<SpecialRegion>> special_regions; |
| 76 | 86 | ||
| 77 | /** | 87 | /** |
| 78 | * Array of fine grained page attributes. If it is set to any value other than `Memory`, then | 88 | * Vector of fine grained page attributes. If it is set to any value other than `Memory`, then |
| 79 | * the corresponding entry in `pointers` MUST be set to null. | 89 | * the corresponding entry in `pointers` MUST be set to null. |
| 80 | */ | 90 | */ |
| 81 | std::array<PageType, PAGE_TABLE_NUM_ENTRIES> attributes; | 91 | std::vector<PageType> attributes; |
| 82 | }; | 92 | }; |
| 83 | 93 | ||
| 84 | /// Virtual user-space memory regions | 94 | /// Virtual user-space memory regions |
diff --git a/src/tests/core/arm/arm_test_common.cpp b/src/tests/core/arm/arm_test_common.cpp index 7c69fc26e..c17a122cd 100644 --- a/src/tests/core/arm/arm_test_common.cpp +++ b/src/tests/core/arm/arm_test_common.cpp | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <algorithm> | ||
| 6 | |||
| 5 | #include "core/core.h" | 7 | #include "core/core.h" |
| 6 | #include "core/hle/kernel/process.h" | 8 | #include "core/hle/kernel/process.h" |
| 7 | #include "core/memory.h" | 9 | #include "core/memory.h" |
| @@ -16,9 +18,10 @@ TestEnvironment::TestEnvironment(bool mutable_memory_) | |||
| 16 | Core::CurrentProcess() = Kernel::Process::Create(kernel, ""); | 18 | Core::CurrentProcess() = Kernel::Process::Create(kernel, ""); |
| 17 | page_table = &Core::CurrentProcess()->vm_manager.page_table; | 19 | page_table = &Core::CurrentProcess()->vm_manager.page_table; |
| 18 | 20 | ||
| 19 | page_table->pointers.fill(nullptr); | 21 | std::fill(page_table->pointers.begin(), page_table->pointers.end(), nullptr); |
| 20 | page_table->special_regions.clear(); | 22 | page_table->special_regions.clear(); |
| 21 | page_table->attributes.fill(Memory::PageType::Unmapped); | 23 | std::fill(page_table->attributes.begin(), page_table->attributes.end(), |
| 24 | Memory::PageType::Unmapped); | ||
| 22 | 25 | ||
| 23 | Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); | 26 | Memory::MapIoRegion(*page_table, 0x00000000, 0x80000000, test_memory); |
| 24 | Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); | 27 | Memory::MapIoRegion(*page_table, 0x80000000, 0x80000000, test_memory); |