diff options
Diffstat (limited to 'src/core/memory.cpp')
| -rw-r--r-- | src/core/memory.cpp | 201 |
1 files changed, 93 insertions, 108 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6061d37ae..9d87045a0 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -14,13 +14,14 @@ | |||
| 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/device_memory.h" | ||
| 18 | #include "core/hle/kernel/memory/page_table.h" | ||
| 17 | #include "core/hle/kernel/physical_memory.h" | 19 | #include "core/hle/kernel/physical_memory.h" |
| 18 | #include "core/hle/kernel/process.h" | 20 | #include "core/hle/kernel/process.h" |
| 19 | #include "core/hle/kernel/vm_manager.h" | ||
| 20 | #include "core/memory.h" | 21 | #include "core/memory.h" |
| 21 | #include "video_core/gpu.h" | 22 | #include "video_core/gpu.h" |
| 22 | 23 | ||
| 23 | namespace Memory { | 24 | namespace Core::Memory { |
| 24 | 25 | ||
| 25 | // Implementation class used to keep the specifics of the memory subsystem hidden | 26 | // Implementation class used to keep the specifics of the memory subsystem hidden |
| 26 | // from outside classes. This also allows modification to the internals of the memory | 27 | // from outside classes. This also allows modification to the internals of the memory |
| @@ -29,9 +30,9 @@ struct Memory::Impl { | |||
| 29 | explicit Impl(Core::System& system_) : system{system_} {} | 30 | explicit Impl(Core::System& system_) : system{system_} {} |
| 30 | 31 | ||
| 31 | void SetCurrentPageTable(Kernel::Process& process) { | 32 | void SetCurrentPageTable(Kernel::Process& process) { |
| 32 | current_page_table = &process.VMManager().page_table; | 33 | current_page_table = &process.PageTable().PageTableImpl(); |
| 33 | 34 | ||
| 34 | const std::size_t address_space_width = process.VMManager().GetAddressSpaceWidth(); | 35 | const std::size_t address_space_width = process.PageTable().GetAddressSpaceWidth(); |
| 35 | 36 | ||
| 36 | system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width); | 37 | system.ArmInterface(0).PageTableChanged(*current_page_table, address_space_width); |
| 37 | system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width); | 38 | system.ArmInterface(1).PageTableChanged(*current_page_table, address_space_width); |
| @@ -39,12 +40,7 @@ struct Memory::Impl { | |||
| 39 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); | 40 | system.ArmInterface(3).PageTableChanged(*current_page_table, address_space_width); |
| 40 | } | 41 | } |
| 41 | 42 | ||
| 42 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, | 43 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { |
| 43 | Kernel::PhysicalMemory& memory, VAddr offset) { | ||
| 44 | MapMemoryRegion(page_table, base, size, memory.data() + offset); | ||
| 45 | } | ||
| 46 | |||
| 47 | void MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { | ||
| 48 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 44 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); |
| 49 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | 45 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); |
| 50 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); | 46 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, target, Common::PageType::Memory); |
| @@ -52,46 +48,27 @@ struct Memory::Impl { | |||
| 52 | 48 | ||
| 53 | void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size, | 49 | void MapIoRegion(Common::PageTable& page_table, VAddr base, u64 size, |
| 54 | Common::MemoryHookPointer mmio_handler) { | 50 | Common::MemoryHookPointer mmio_handler) { |
| 55 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 51 | UNIMPLEMENTED(); |
| 56 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | ||
| 57 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, | ||
| 58 | Common::PageType::Special); | ||
| 59 | |||
| 60 | const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); | ||
| 61 | const Common::SpecialRegion region{Common::SpecialRegion::Type::IODevice, | ||
| 62 | std::move(mmio_handler)}; | ||
| 63 | page_table.special_regions.add( | ||
| 64 | std::make_pair(interval, std::set<Common::SpecialRegion>{region})); | ||
| 65 | } | 52 | } |
| 66 | 53 | ||
| 67 | void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { | 54 | void UnmapRegion(Common::PageTable& page_table, VAddr base, u64 size) { |
| 68 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); | 55 | ASSERT_MSG((size & PAGE_MASK) == 0, "non-page aligned size: {:016X}", size); |
| 69 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); | 56 | ASSERT_MSG((base & PAGE_MASK) == 0, "non-page aligned base: {:016X}", base); |
| 70 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, nullptr, | 57 | MapPages(page_table, base / PAGE_SIZE, size / PAGE_SIZE, 0, Common::PageType::Unmapped); |
| 71 | Common::PageType::Unmapped); | ||
| 72 | |||
| 73 | const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); | ||
| 74 | page_table.special_regions.erase(interval); | ||
| 75 | } | 58 | } |
| 76 | 59 | ||
| 77 | void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size, | 60 | void AddDebugHook(Common::PageTable& page_table, VAddr base, u64 size, |
| 78 | Common::MemoryHookPointer hook) { | 61 | Common::MemoryHookPointer hook) { |
| 79 | const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); | 62 | UNIMPLEMENTED(); |
| 80 | const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)}; | ||
| 81 | page_table.special_regions.add( | ||
| 82 | std::make_pair(interval, std::set<Common::SpecialRegion>{region})); | ||
| 83 | } | 63 | } |
| 84 | 64 | ||
| 85 | void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, | 65 | void RemoveDebugHook(Common::PageTable& page_table, VAddr base, u64 size, |
| 86 | Common::MemoryHookPointer hook) { | 66 | Common::MemoryHookPointer hook) { |
| 87 | const auto interval = boost::icl::discrete_interval<VAddr>::closed(base, base + size - 1); | 67 | UNIMPLEMENTED(); |
| 88 | const Common::SpecialRegion region{Common::SpecialRegion::Type::DebugHook, std::move(hook)}; | ||
| 89 | page_table.special_regions.subtract( | ||
| 90 | std::make_pair(interval, std::set<Common::SpecialRegion>{region})); | ||
| 91 | } | 68 | } |
| 92 | 69 | ||
| 93 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { | 70 | bool IsValidVirtualAddress(const Kernel::Process& process, const VAddr vaddr) const { |
| 94 | const auto& page_table = process.VMManager().page_table; | 71 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 95 | 72 | ||
| 96 | const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; | 73 | const u8* const page_pointer = page_table.pointers[vaddr >> PAGE_BITS]; |
| 97 | if (page_pointer != nullptr) { | 74 | if (page_pointer != nullptr) { |
| @@ -113,55 +90,28 @@ struct Memory::Impl { | |||
| 113 | return IsValidVirtualAddress(*system.CurrentProcess(), vaddr); | 90 | return IsValidVirtualAddress(*system.CurrentProcess(), vaddr); |
| 114 | } | 91 | } |
| 115 | 92 | ||
| 116 | /** | 93 | u8* GetPointerFromRasterizerCachedMemory(VAddr vaddr) const { |
| 117 | * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) | 94 | const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]}; |
| 118 | * using a VMA from the current process | ||
| 119 | */ | ||
| 120 | u8* GetPointerFromVMA(const Kernel::Process& process, VAddr vaddr) { | ||
| 121 | const auto& vm_manager = process.VMManager(); | ||
| 122 | 95 | ||
| 123 | const auto it = vm_manager.FindVMA(vaddr); | 96 | if (!paddr) { |
| 124 | DEBUG_ASSERT(vm_manager.IsValidHandle(it)); | 97 | return {}; |
| 125 | |||
| 126 | u8* direct_pointer = nullptr; | ||
| 127 | const auto& vma = it->second; | ||
| 128 | switch (vma.type) { | ||
| 129 | case Kernel::VMAType::AllocatedMemoryBlock: | ||
| 130 | direct_pointer = vma.backing_block->data() + vma.offset; | ||
| 131 | break; | ||
| 132 | case Kernel::VMAType::BackingMemory: | ||
| 133 | direct_pointer = vma.backing_memory; | ||
| 134 | break; | ||
| 135 | case Kernel::VMAType::Free: | ||
| 136 | return nullptr; | ||
| 137 | default: | ||
| 138 | UNREACHABLE(); | ||
| 139 | } | 98 | } |
| 140 | 99 | ||
| 141 | return direct_pointer + (vaddr - vma.base); | 100 | return system.DeviceMemory().GetPointer(paddr) + vaddr; |
| 142 | } | 101 | } |
| 143 | 102 | ||
| 144 | /** | 103 | u8* GetPointer(const VAddr vaddr) const { |
| 145 | * Gets a pointer to the exact memory at the virtual address (i.e. not page aligned) | 104 | u8* const page_pointer{current_page_table->pointers[vaddr >> PAGE_BITS]}; |
| 146 | * using a VMA from the current process. | 105 | if (page_pointer) { |
| 147 | */ | ||
| 148 | u8* GetPointerFromVMA(VAddr vaddr) { | ||
| 149 | return GetPointerFromVMA(*system.CurrentProcess(), vaddr); | ||
| 150 | } | ||
| 151 | |||
| 152 | u8* GetPointer(const VAddr vaddr) { | ||
| 153 | u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; | ||
| 154 | if (page_pointer != nullptr) { | ||
| 155 | return page_pointer + vaddr; | 106 | return page_pointer + vaddr; |
| 156 | } | 107 | } |
| 157 | 108 | ||
| 158 | if (current_page_table->attributes[vaddr >> PAGE_BITS] == | 109 | if (current_page_table->attributes[vaddr >> PAGE_BITS] == |
| 159 | Common::PageType::RasterizerCachedMemory) { | 110 | Common::PageType::RasterizerCachedMemory) { |
| 160 | return GetPointerFromVMA(vaddr); | 111 | return GetPointerFromRasterizerCachedMemory(vaddr); |
| 161 | } | 112 | } |
| 162 | 113 | ||
| 163 | LOG_ERROR(HW_Memory, "Unknown GetPointer @ 0x{:016X}", vaddr); | 114 | return {}; |
| 164 | return nullptr; | ||
| 165 | } | 115 | } |
| 166 | 116 | ||
| 167 | u8 Read8(const VAddr addr) { | 117 | u8 Read8(const VAddr addr) { |
| @@ -169,15 +119,33 @@ struct Memory::Impl { | |||
| 169 | } | 119 | } |
| 170 | 120 | ||
| 171 | u16 Read16(const VAddr addr) { | 121 | u16 Read16(const VAddr addr) { |
| 172 | return Read<u16_le>(addr); | 122 | if ((addr & 1) == 0) { |
| 123 | return Read<u16_le>(addr); | ||
| 124 | } else { | ||
| 125 | const u8 a{Read<u8>(addr)}; | ||
| 126 | const u8 b{Read<u8>(addr + sizeof(u8))}; | ||
| 127 | return (static_cast<u16>(b) << 8) | a; | ||
| 128 | } | ||
| 173 | } | 129 | } |
| 174 | 130 | ||
| 175 | u32 Read32(const VAddr addr) { | 131 | u32 Read32(const VAddr addr) { |
| 176 | return Read<u32_le>(addr); | 132 | if ((addr & 3) == 0) { |
| 133 | return Read<u32_le>(addr); | ||
| 134 | } else { | ||
| 135 | const u16 a{Read16(addr)}; | ||
| 136 | const u16 b{Read16(addr + sizeof(u16))}; | ||
| 137 | return (static_cast<u32>(b) << 16) | a; | ||
| 138 | } | ||
| 177 | } | 139 | } |
| 178 | 140 | ||
| 179 | u64 Read64(const VAddr addr) { | 141 | u64 Read64(const VAddr addr) { |
| 180 | return Read<u64_le>(addr); | 142 | if ((addr & 7) == 0) { |
| 143 | return Read<u64_le>(addr); | ||
| 144 | } else { | ||
| 145 | const u32 a{Read32(addr)}; | ||
| 146 | const u32 b{Read32(addr + sizeof(u32))}; | ||
| 147 | return (static_cast<u64>(b) << 32) | a; | ||
| 148 | } | ||
| 181 | } | 149 | } |
| 182 | 150 | ||
| 183 | void Write8(const VAddr addr, const u8 data) { | 151 | void Write8(const VAddr addr, const u8 data) { |
| @@ -185,15 +153,30 @@ struct Memory::Impl { | |||
| 185 | } | 153 | } |
| 186 | 154 | ||
| 187 | void Write16(const VAddr addr, const u16 data) { | 155 | void Write16(const VAddr addr, const u16 data) { |
| 188 | Write<u16_le>(addr, data); | 156 | if ((addr & 1) == 0) { |
| 157 | Write<u16_le>(addr, data); | ||
| 158 | } else { | ||
| 159 | Write<u8>(addr, static_cast<u8>(data)); | ||
| 160 | Write<u8>(addr + sizeof(u8), static_cast<u8>(data >> 8)); | ||
| 161 | } | ||
| 189 | } | 162 | } |
| 190 | 163 | ||
| 191 | void Write32(const VAddr addr, const u32 data) { | 164 | void Write32(const VAddr addr, const u32 data) { |
| 192 | Write<u32_le>(addr, data); | 165 | if ((addr & 3) == 0) { |
| 166 | Write<u32_le>(addr, data); | ||
| 167 | } else { | ||
| 168 | Write16(addr, static_cast<u16>(data)); | ||
| 169 | Write16(addr + sizeof(u16), static_cast<u16>(data >> 16)); | ||
| 170 | } | ||
| 193 | } | 171 | } |
| 194 | 172 | ||
| 195 | void Write64(const VAddr addr, const u64 data) { | 173 | void Write64(const VAddr addr, const u64 data) { |
| 196 | Write<u64_le>(addr, data); | 174 | if ((addr & 7) == 0) { |
| 175 | Write<u64_le>(addr, data); | ||
| 176 | } else { | ||
| 177 | Write32(addr, static_cast<u32>(data)); | ||
| 178 | Write32(addr + sizeof(u32), static_cast<u32>(data >> 32)); | ||
| 179 | } | ||
| 197 | } | 180 | } |
| 198 | 181 | ||
| 199 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { | 182 | std::string ReadCString(VAddr vaddr, std::size_t max_length) { |
| @@ -213,7 +196,7 @@ struct Memory::Impl { | |||
| 213 | 196 | ||
| 214 | void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | 197 | void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, |
| 215 | const std::size_t size) { | 198 | const std::size_t size) { |
| 216 | const auto& page_table = process.VMManager().page_table; | 199 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 217 | 200 | ||
| 218 | std::size_t remaining_size = size; | 201 | std::size_t remaining_size = size; |
| 219 | std::size_t page_index = src_addr >> PAGE_BITS; | 202 | std::size_t page_index = src_addr >> PAGE_BITS; |
| @@ -241,7 +224,7 @@ struct Memory::Impl { | |||
| 241 | break; | 224 | break; |
| 242 | } | 225 | } |
| 243 | case Common::PageType::RasterizerCachedMemory: { | 226 | case Common::PageType::RasterizerCachedMemory: { |
| 244 | const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 227 | const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 245 | system.GPU().FlushRegion(current_vaddr, copy_amount); | 228 | system.GPU().FlushRegion(current_vaddr, copy_amount); |
| 246 | std::memcpy(dest_buffer, host_ptr, copy_amount); | 229 | std::memcpy(dest_buffer, host_ptr, copy_amount); |
| 247 | break; | 230 | break; |
| @@ -259,7 +242,7 @@ struct Memory::Impl { | |||
| 259 | 242 | ||
| 260 | void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, | 243 | void ReadBlockUnsafe(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer, |
| 261 | const std::size_t size) { | 244 | const std::size_t size) { |
| 262 | const auto& page_table = process.VMManager().page_table; | 245 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 263 | 246 | ||
| 264 | std::size_t remaining_size = size; | 247 | std::size_t remaining_size = size; |
| 265 | std::size_t page_index = src_addr >> PAGE_BITS; | 248 | std::size_t page_index = src_addr >> PAGE_BITS; |
| @@ -287,7 +270,7 @@ struct Memory::Impl { | |||
| 287 | break; | 270 | break; |
| 288 | } | 271 | } |
| 289 | case Common::PageType::RasterizerCachedMemory: { | 272 | case Common::PageType::RasterizerCachedMemory: { |
| 290 | const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 273 | const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 291 | std::memcpy(dest_buffer, host_ptr, copy_amount); | 274 | std::memcpy(dest_buffer, host_ptr, copy_amount); |
| 292 | break; | 275 | break; |
| 293 | } | 276 | } |
| @@ -312,7 +295,7 @@ struct Memory::Impl { | |||
| 312 | 295 | ||
| 313 | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, | 296 | void WriteBlock(const Kernel::Process& process, const VAddr dest_addr, const void* src_buffer, |
| 314 | const std::size_t size) { | 297 | const std::size_t size) { |
| 315 | const auto& page_table = process.VMManager().page_table; | 298 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 316 | std::size_t remaining_size = size; | 299 | std::size_t remaining_size = size; |
| 317 | std::size_t page_index = dest_addr >> PAGE_BITS; | 300 | std::size_t page_index = dest_addr >> PAGE_BITS; |
| 318 | std::size_t page_offset = dest_addr & PAGE_MASK; | 301 | std::size_t page_offset = dest_addr & PAGE_MASK; |
| @@ -338,7 +321,7 @@ struct Memory::Impl { | |||
| 338 | break; | 321 | break; |
| 339 | } | 322 | } |
| 340 | case Common::PageType::RasterizerCachedMemory: { | 323 | case Common::PageType::RasterizerCachedMemory: { |
| 341 | u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 324 | u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 342 | system.GPU().InvalidateRegion(current_vaddr, copy_amount); | 325 | system.GPU().InvalidateRegion(current_vaddr, copy_amount); |
| 343 | std::memcpy(host_ptr, src_buffer, copy_amount); | 326 | std::memcpy(host_ptr, src_buffer, copy_amount); |
| 344 | break; | 327 | break; |
| @@ -356,7 +339,7 @@ struct Memory::Impl { | |||
| 356 | 339 | ||
| 357 | void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr, | 340 | void WriteBlockUnsafe(const Kernel::Process& process, const VAddr dest_addr, |
| 358 | const void* src_buffer, const std::size_t size) { | 341 | const void* src_buffer, const std::size_t size) { |
| 359 | const auto& page_table = process.VMManager().page_table; | 342 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 360 | std::size_t remaining_size = size; | 343 | std::size_t remaining_size = size; |
| 361 | std::size_t page_index = dest_addr >> PAGE_BITS; | 344 | std::size_t page_index = dest_addr >> PAGE_BITS; |
| 362 | std::size_t page_offset = dest_addr & PAGE_MASK; | 345 | std::size_t page_offset = dest_addr & PAGE_MASK; |
| @@ -382,7 +365,7 @@ struct Memory::Impl { | |||
| 382 | break; | 365 | break; |
| 383 | } | 366 | } |
| 384 | case Common::PageType::RasterizerCachedMemory: { | 367 | case Common::PageType::RasterizerCachedMemory: { |
| 385 | u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 368 | u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 386 | std::memcpy(host_ptr, src_buffer, copy_amount); | 369 | std::memcpy(host_ptr, src_buffer, copy_amount); |
| 387 | break; | 370 | break; |
| 388 | } | 371 | } |
| @@ -406,7 +389,7 @@ struct Memory::Impl { | |||
| 406 | } | 389 | } |
| 407 | 390 | ||
| 408 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { | 391 | void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { |
| 409 | const auto& page_table = process.VMManager().page_table; | 392 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 410 | std::size_t remaining_size = size; | 393 | std::size_t remaining_size = size; |
| 411 | std::size_t page_index = dest_addr >> PAGE_BITS; | 394 | std::size_t page_index = dest_addr >> PAGE_BITS; |
| 412 | std::size_t page_offset = dest_addr & PAGE_MASK; | 395 | std::size_t page_offset = dest_addr & PAGE_MASK; |
| @@ -432,7 +415,7 @@ struct Memory::Impl { | |||
| 432 | break; | 415 | break; |
| 433 | } | 416 | } |
| 434 | case Common::PageType::RasterizerCachedMemory: { | 417 | case Common::PageType::RasterizerCachedMemory: { |
| 435 | u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 418 | u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 436 | system.GPU().InvalidateRegion(current_vaddr, copy_amount); | 419 | system.GPU().InvalidateRegion(current_vaddr, copy_amount); |
| 437 | std::memset(host_ptr, 0, copy_amount); | 420 | std::memset(host_ptr, 0, copy_amount); |
| 438 | break; | 421 | break; |
| @@ -453,7 +436,7 @@ struct Memory::Impl { | |||
| 453 | 436 | ||
| 454 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, | 437 | void CopyBlock(const Kernel::Process& process, VAddr dest_addr, VAddr src_addr, |
| 455 | const std::size_t size) { | 438 | const std::size_t size) { |
| 456 | const auto& page_table = process.VMManager().page_table; | 439 | const auto& page_table = process.PageTable().PageTableImpl(); |
| 457 | std::size_t remaining_size = size; | 440 | std::size_t remaining_size = size; |
| 458 | std::size_t page_index = src_addr >> PAGE_BITS; | 441 | std::size_t page_index = src_addr >> PAGE_BITS; |
| 459 | std::size_t page_offset = src_addr & PAGE_MASK; | 442 | std::size_t page_offset = src_addr & PAGE_MASK; |
| @@ -479,7 +462,7 @@ struct Memory::Impl { | |||
| 479 | break; | 462 | break; |
| 480 | } | 463 | } |
| 481 | case Common::PageType::RasterizerCachedMemory: { | 464 | case Common::PageType::RasterizerCachedMemory: { |
| 482 | const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr); | 465 | const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; |
| 483 | system.GPU().FlushRegion(current_vaddr, copy_amount); | 466 | system.GPU().FlushRegion(current_vaddr, copy_amount); |
| 484 | WriteBlock(process, dest_addr, host_ptr, copy_amount); | 467 | WriteBlock(process, dest_addr, host_ptr, copy_amount); |
| 485 | break; | 468 | break; |
| @@ -512,7 +495,7 @@ struct Memory::Impl { | |||
| 512 | 495 | ||
| 513 | u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1; | 496 | u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1; |
| 514 | for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { | 497 | for (unsigned i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) { |
| 515 | Common::PageType& page_type = current_page_table->attributes[vaddr >> PAGE_BITS]; | 498 | Common::PageType& page_type{current_page_table->attributes[vaddr >> PAGE_BITS]}; |
| 516 | 499 | ||
| 517 | if (cached) { | 500 | if (cached) { |
| 518 | // Switch page type to cached if now cached | 501 | // Switch page type to cached if now cached |
| @@ -544,7 +527,7 @@ struct Memory::Impl { | |||
| 544 | // that this area is already unmarked as cached. | 527 | // that this area is already unmarked as cached. |
| 545 | break; | 528 | break; |
| 546 | case Common::PageType::RasterizerCachedMemory: { | 529 | case Common::PageType::RasterizerCachedMemory: { |
| 547 | u8* pointer = GetPointerFromVMA(vaddr & ~PAGE_MASK); | 530 | u8* pointer{GetPointerFromRasterizerCachedMemory(vaddr & ~PAGE_MASK)}; |
| 548 | if (pointer == nullptr) { | 531 | if (pointer == nullptr) { |
| 549 | // It's possible that this function has been called while updating the | 532 | // It's possible that this function has been called while updating the |
| 550 | // pagetable after unmapping a VMA. In that case the underlying VMA will no | 533 | // pagetable after unmapping a VMA. In that case the underlying VMA will no |
| @@ -573,9 +556,9 @@ struct Memory::Impl { | |||
| 573 | * @param memory The memory to map. | 556 | * @param memory The memory to map. |
| 574 | * @param type The page type to map the memory as. | 557 | * @param type The page type to map the memory as. |
| 575 | */ | 558 | */ |
| 576 | void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* memory, | 559 | void MapPages(Common::PageTable& page_table, VAddr base, u64 size, PAddr target, |
| 577 | Common::PageType type) { | 560 | Common::PageType type) { |
| 578 | LOG_DEBUG(HW_Memory, "Mapping {} onto {:016X}-{:016X}", fmt::ptr(memory), base * PAGE_SIZE, | 561 | LOG_DEBUG(HW_Memory, "Mapping {:016X} onto {:016X}-{:016X}", target, base * PAGE_SIZE, |
| 579 | (base + size) * PAGE_SIZE); | 562 | (base + size) * PAGE_SIZE); |
| 580 | 563 | ||
| 581 | // During boot, current_page_table might not be set yet, in which case we need not flush | 564 | // During boot, current_page_table might not be set yet, in which case we need not flush |
| @@ -593,19 +576,26 @@ struct Memory::Impl { | |||
| 593 | ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", | 576 | ASSERT_MSG(end <= page_table.pointers.size(), "out of range mapping at {:016X}", |
| 594 | base + page_table.pointers.size()); | 577 | base + page_table.pointers.size()); |
| 595 | 578 | ||
| 596 | std::fill(page_table.attributes.begin() + base, page_table.attributes.begin() + end, type); | 579 | if (!target) { |
| 580 | while (base != end) { | ||
| 581 | page_table.pointers[base] = nullptr; | ||
| 582 | page_table.attributes[base] = type; | ||
| 583 | page_table.backing_addr[base] = 0; | ||
| 597 | 584 | ||
| 598 | if (memory == nullptr) { | 585 | base += 1; |
| 599 | std::fill(page_table.pointers.begin() + base, page_table.pointers.begin() + end, | 586 | } |
| 600 | memory); | ||
| 601 | } else { | 587 | } else { |
| 602 | while (base != end) { | 588 | while (base != end) { |
| 603 | page_table.pointers[base] = memory - (base << PAGE_BITS); | 589 | page_table.pointers[base] = |
| 590 | system.DeviceMemory().GetPointer(target) - (base << PAGE_BITS); | ||
| 591 | page_table.attributes[base] = type; | ||
| 592 | page_table.backing_addr[base] = target - (base << PAGE_BITS); | ||
| 593 | |||
| 604 | ASSERT_MSG(page_table.pointers[base], | 594 | ASSERT_MSG(page_table.pointers[base], |
| 605 | "memory mapping base yield a nullptr within the table"); | 595 | "memory mapping base yield a nullptr within the table"); |
| 606 | 596 | ||
| 607 | base += 1; | 597 | base += 1; |
| 608 | memory += PAGE_SIZE; | 598 | target += PAGE_SIZE; |
| 609 | } | 599 | } |
| 610 | } | 600 | } |
| 611 | } | 601 | } |
| @@ -640,7 +630,7 @@ struct Memory::Impl { | |||
| 640 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | 630 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); |
| 641 | break; | 631 | break; |
| 642 | case Common::PageType::RasterizerCachedMemory: { | 632 | case Common::PageType::RasterizerCachedMemory: { |
| 643 | const u8* const host_ptr = GetPointerFromVMA(vaddr); | 633 | const u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; |
| 644 | system.GPU().FlushRegion(vaddr, sizeof(T)); | 634 | system.GPU().FlushRegion(vaddr, sizeof(T)); |
| 645 | T value; | 635 | T value; |
| 646 | std::memcpy(&value, host_ptr, sizeof(T)); | 636 | std::memcpy(&value, host_ptr, sizeof(T)); |
| @@ -682,7 +672,7 @@ struct Memory::Impl { | |||
| 682 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); | 672 | ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr); |
| 683 | break; | 673 | break; |
| 684 | case Common::PageType::RasterizerCachedMemory: { | 674 | case Common::PageType::RasterizerCachedMemory: { |
| 685 | u8* const host_ptr{GetPointerFromVMA(vaddr)}; | 675 | u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; |
| 686 | system.GPU().InvalidateRegion(vaddr, sizeof(T)); | 676 | system.GPU().InvalidateRegion(vaddr, sizeof(T)); |
| 687 | std::memcpy(host_ptr, &data, sizeof(T)); | 677 | std::memcpy(host_ptr, &data, sizeof(T)); |
| 688 | break; | 678 | break; |
| @@ -703,12 +693,7 @@ void Memory::SetCurrentPageTable(Kernel::Process& process) { | |||
| 703 | impl->SetCurrentPageTable(process); | 693 | impl->SetCurrentPageTable(process); |
| 704 | } | 694 | } |
| 705 | 695 | ||
| 706 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, | 696 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, PAddr target) { |
| 707 | Kernel::PhysicalMemory& memory, VAddr offset) { | ||
| 708 | impl->MapMemoryRegion(page_table, base, size, memory, offset); | ||
| 709 | } | ||
| 710 | |||
| 711 | void Memory::MapMemoryRegion(Common::PageTable& page_table, VAddr base, u64 size, u8* target) { | ||
| 712 | impl->MapMemoryRegion(page_table, base, size, target); | 697 | impl->MapMemoryRegion(page_table, base, size, target); |
| 713 | } | 698 | } |
| 714 | 699 | ||
| @@ -845,4 +830,4 @@ bool IsKernelVirtualAddress(const VAddr vaddr) { | |||
| 845 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; | 830 | return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; |
| 846 | } | 831 | } |
| 847 | 832 | ||
| 848 | } // namespace Memory | 833 | } // namespace Core::Memory |