summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar Lioncash2018-09-24 10:29:56 -0400
committerGravatar Lioncash2018-09-24 22:15:53 -0400
commit7fd598636e819d4e86874b20081945936a05c5f1 (patch)
tree046da702e80db7f8f5d75521b7864a1b7eb822a3
parentprocess/vm_manager: Amend API to allow reading parameters from NPDM metadata (diff)
downloadyuzu-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.cpp5
-rw-r--r--src/core/hle/kernel/vm_manager.cpp18
-rw-r--r--src/core/hle/kernel/vm_manager.h3
-rw-r--r--src/core/memory.cpp18
-rw-r--r--src/core/memory.h32
-rw-r--r--src/tests/core/arm/arm_test_common.cpp7
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
131std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() const { 131std::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
67void VMManager::Reset(FileSys::ProgramAddressSpaceType type) { 67void 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
79VMManager::VMAHandle VMManager::FindVMA(VAddr target) const { 82VMManager::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
457void VMManager::ClearPageTable() { 460void 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
463u64 VMManager::GetTotalMemoryUsage() const { 467u64 VMManager::GetTotalMemoryUsage() const {
@@ -480,6 +484,10 @@ u64 VMManager::GetAddressSpaceSize() const {
480 return MAX_ADDRESS; 484 return MAX_ADDRESS;
481} 485}
482 486
487u64 VMManager::GetAddressSpaceWidth() const {
488 return address_space_width;
489}
490
483VAddr VMManager::GetCodeRegionBaseAddress() const { 491VAddr 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
43PageTable::PageTable() = default;
44
45PageTable::PageTable(std::size_t address_space_width_in_bits) {
46 Resize(address_space_width_in_bits);
47}
48
49PageTable::~PageTable() = default;
50
51void 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
44static void MapPages(PageTable& page_table, VAddr base, u64 size, u8* memory, PageType type) { 58static 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 */
25constexpr std::size_t PAGE_BITS = 12; 25constexpr std::size_t PAGE_BITS = 12;
26constexpr u64 PAGE_SIZE = 1 << PAGE_BITS; 26constexpr u64 PAGE_SIZE = 1ULL << PAGE_BITS;
27constexpr u64 PAGE_MASK = PAGE_SIZE - 1; 27constexpr u64 PAGE_MASK = PAGE_SIZE - 1;
28constexpr std::size_t ADDRESS_SPACE_BITS = 36;
29constexpr std::size_t PAGE_TABLE_NUM_ENTRIES = 1ULL << (ADDRESS_SPACE_BITS - PAGE_BITS);
30 28
31enum class PageType : u8 { 29enum 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 */
64struct PageTable { 62struct 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);