summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
authorGravatar Lioncash2019-11-26 16:29:34 -0500
committerGravatar Lioncash2019-11-26 21:55:39 -0500
commitb05bfc603689419dc515a656b9fc711d79994f13 (patch)
treebc0937d11bbe31458785a69478edbf11a720b0ae /src/core/memory.cpp
parentcore/memory: Migrate over ZeroBlock() and CopyBlock() to the Memory class (diff)
downloadyuzu-b05bfc603689419dc515a656b9fc711d79994f13.tar.gz
yuzu-b05bfc603689419dc515a656b9fc711d79994f13.tar.xz
yuzu-b05bfc603689419dc515a656b9fc711d79994f13.zip
core/memory: Migrate over Read{8, 16, 32, 64, Block} to the Memory class
With all of the trivial parts of the memory interface moved over, we can get right into moving over the bits that are used. Note that this does require the use of GetInstance from the global system instance to be used within hle_ipc.cpp and the gdbstub. This is fine for the time being, as they both already rely on the global system instance in other functions. These will be removed in a change directed at both of these respectively. For now, it's sufficient, as it still accomplishes the goal of de-globalizing the memory code.
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp228
1 files changed, 132 insertions, 96 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index c939e980d..699c48107 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -60,37 +60,6 @@ u8* GetPointerFromVMA(VAddr vaddr) {
60} 60}
61 61
62template <typename T> 62template <typename T>
63T Read(const VAddr vaddr) {
64 const u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
65 if (page_pointer != nullptr) {
66 // NOTE: Avoid adding any extra logic to this fast-path block
67 T value;
68 std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T));
69 return value;
70 }
71
72 const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
73 switch (type) {
74 case Common::PageType::Unmapped:
75 LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr);
76 return 0;
77 case Common::PageType::Memory:
78 ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
79 break;
80 case Common::PageType::RasterizerCachedMemory: {
81 const u8* const host_ptr{GetPointerFromVMA(vaddr)};
82 Core::System::GetInstance().GPU().FlushRegion(ToCacheAddr(host_ptr), sizeof(T));
83 T value;
84 std::memcpy(&value, host_ptr, sizeof(T));
85 return value;
86 }
87 default:
88 UNREACHABLE();
89 }
90 return {};
91}
92
93template <typename T>
94void Write(const VAddr vaddr, const T data) { 63void Write(const VAddr vaddr, const T data) {
95 u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS]; 64 u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
96 if (page_pointer != nullptr) { 65 if (page_pointer != nullptr) {
@@ -210,6 +179,22 @@ struct Memory::Impl {
210 return nullptr; 179 return nullptr;
211 } 180 }
212 181
182 u8 Read8(const VAddr addr) {
183 return Read<u8>(addr);
184 }
185
186 u16 Read16(const VAddr addr) {
187 return Read<u16_le>(addr);
188 }
189
190 u32 Read32(const VAddr addr) {
191 return Read<u32_le>(addr);
192 }
193
194 u64 Read64(const VAddr addr) {
195 return Read<u64_le>(addr);
196 }
197
213 std::string ReadCString(VAddr vaddr, std::size_t max_length) { 198 std::string ReadCString(VAddr vaddr, std::size_t max_length) {
214 std::string string; 199 std::string string;
215 string.reserve(max_length); 200 string.reserve(max_length);
@@ -225,6 +210,55 @@ struct Memory::Impl {
225 return string; 210 return string;
226 } 211 }
227 212
213 void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
214 const std::size_t size) {
215 const auto& page_table = process.VMManager().page_table;
216
217 std::size_t remaining_size = size;
218 std::size_t page_index = src_addr >> PAGE_BITS;
219 std::size_t page_offset = src_addr & PAGE_MASK;
220
221 while (remaining_size > 0) {
222 const std::size_t copy_amount =
223 std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
224 const auto current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
225
226 switch (page_table.attributes[page_index]) {
227 case Common::PageType::Unmapped: {
228 LOG_ERROR(HW_Memory,
229 "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
230 current_vaddr, src_addr, size);
231 std::memset(dest_buffer, 0, copy_amount);
232 break;
233 }
234 case Common::PageType::Memory: {
235 DEBUG_ASSERT(page_table.pointers[page_index]);
236
237 const u8* const src_ptr = page_table.pointers[page_index] + page_offset;
238 std::memcpy(dest_buffer, src_ptr, copy_amount);
239 break;
240 }
241 case Common::PageType::RasterizerCachedMemory: {
242 const u8* const host_ptr = GetPointerFromVMA(process, current_vaddr);
243 system.GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
244 std::memcpy(dest_buffer, host_ptr, copy_amount);
245 break;
246 }
247 default:
248 UNREACHABLE();
249 }
250
251 page_index++;
252 page_offset = 0;
253 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
254 remaining_size -= copy_amount;
255 }
256 }
257
258 void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
259 ReadBlock(*system.CurrentProcess(), src_addr, dest_buffer, size);
260 }
261
228 void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) { 262 void ZeroBlock(const Kernel::Process& process, const VAddr dest_addr, const std::size_t size) {
229 const auto& page_table = process.VMManager().page_table; 263 const auto& page_table = process.VMManager().page_table;
230 std::size_t remaining_size = size; 264 std::size_t remaining_size = size;
@@ -425,6 +459,48 @@ struct Memory::Impl {
425 } 459 }
426 } 460 }
427 461
462 /**
463 * Reads a particular data type out of memory at the given virtual address.
464 *
465 * @param vaddr The virtual address to read the data type from.
466 *
467 * @tparam T The data type to read out of memory. This type *must* be
468 * trivially copyable, otherwise the behavior of this function
469 * is undefined.
470 *
471 * @returns The instance of T read from the specified virtual address.
472 */
473 template <typename T>
474 T Read(const VAddr vaddr) {
475 const u8* const page_pointer = current_page_table->pointers[vaddr >> PAGE_BITS];
476 if (page_pointer != nullptr) {
477 // NOTE: Avoid adding any extra logic to this fast-path block
478 T value;
479 std::memcpy(&value, &page_pointer[vaddr & PAGE_MASK], sizeof(T));
480 return value;
481 }
482
483 const Common::PageType type = current_page_table->attributes[vaddr >> PAGE_BITS];
484 switch (type) {
485 case Common::PageType::Unmapped:
486 LOG_ERROR(HW_Memory, "Unmapped Read{} @ 0x{:08X}", sizeof(T) * 8, vaddr);
487 return 0;
488 case Common::PageType::Memory:
489 ASSERT_MSG(false, "Mapped memory page without a pointer @ {:016X}", vaddr);
490 break;
491 case Common::PageType::RasterizerCachedMemory: {
492 const u8* const host_ptr = GetPointerFromVMA(vaddr);
493 system.GPU().FlushRegion(ToCacheAddr(host_ptr), sizeof(T));
494 T value;
495 std::memcpy(&value, host_ptr, sizeof(T));
496 return value;
497 }
498 default:
499 UNREACHABLE();
500 }
501 return {};
502 }
503
428 Core::System& system; 504 Core::System& system;
429}; 505};
430 506
@@ -470,10 +546,35 @@ const u8* Memory::GetPointer(VAddr vaddr) const {
470 return impl->GetPointer(vaddr); 546 return impl->GetPointer(vaddr);
471} 547}
472 548
549u8 Memory::Read8(const VAddr addr) {
550 return impl->Read8(addr);
551}
552
553u16 Memory::Read16(const VAddr addr) {
554 return impl->Read16(addr);
555}
556
557u32 Memory::Read32(const VAddr addr) {
558 return impl->Read32(addr);
559}
560
561u64 Memory::Read64(const VAddr addr) {
562 return impl->Read64(addr);
563}
564
473std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) { 565std::string Memory::ReadCString(VAddr vaddr, std::size_t max_length) {
474 return impl->ReadCString(vaddr, max_length); 566 return impl->ReadCString(vaddr, max_length);
475} 567}
476 568
569void Memory::ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
570 const std::size_t size) {
571 impl->ReadBlock(process, src_addr, dest_buffer, size);
572}
573
574void Memory::ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
575 impl->ReadBlock(src_addr, dest_buffer, size);
576}
577
477void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) { 578void Memory::ZeroBlock(const Kernel::Process& process, VAddr dest_addr, std::size_t size) {
478 impl->ZeroBlock(process, dest_addr, size); 579 impl->ZeroBlock(process, dest_addr, size);
479} 580}
@@ -511,71 +612,6 @@ bool IsKernelVirtualAddress(const VAddr vaddr) {
511 return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END; 612 return KERNEL_REGION_VADDR <= vaddr && vaddr < KERNEL_REGION_END;
512} 613}
513 614
514u8 Read8(const VAddr addr) {
515 return Read<u8>(addr);
516}
517
518u16 Read16(const VAddr addr) {
519 return Read<u16_le>(addr);
520}
521
522u32 Read32(const VAddr addr) {
523 return Read<u32_le>(addr);
524}
525
526u64 Read64(const VAddr addr) {
527 return Read<u64_le>(addr);
528}
529
530void ReadBlock(const Kernel::Process& process, const VAddr src_addr, void* dest_buffer,
531 const std::size_t size) {
532 const auto& page_table = process.VMManager().page_table;
533
534 std::size_t remaining_size = size;
535 std::size_t page_index = src_addr >> PAGE_BITS;
536 std::size_t page_offset = src_addr & PAGE_MASK;
537
538 while (remaining_size > 0) {
539 const std::size_t copy_amount =
540 std::min(static_cast<std::size_t>(PAGE_SIZE) - page_offset, remaining_size);
541 const VAddr current_vaddr = static_cast<VAddr>((page_index << PAGE_BITS) + page_offset);
542
543 switch (page_table.attributes[page_index]) {
544 case Common::PageType::Unmapped: {
545 LOG_ERROR(HW_Memory,
546 "Unmapped ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
547 current_vaddr, src_addr, size);
548 std::memset(dest_buffer, 0, copy_amount);
549 break;
550 }
551 case Common::PageType::Memory: {
552 DEBUG_ASSERT(page_table.pointers[page_index]);
553
554 const u8* src_ptr = page_table.pointers[page_index] + page_offset;
555 std::memcpy(dest_buffer, src_ptr, copy_amount);
556 break;
557 }
558 case Common::PageType::RasterizerCachedMemory: {
559 const auto& host_ptr{GetPointerFromVMA(process, current_vaddr)};
560 Core::System::GetInstance().GPU().FlushRegion(ToCacheAddr(host_ptr), copy_amount);
561 std::memcpy(dest_buffer, host_ptr, copy_amount);
562 break;
563 }
564 default:
565 UNREACHABLE();
566 }
567
568 page_index++;
569 page_offset = 0;
570 dest_buffer = static_cast<u8*>(dest_buffer) + copy_amount;
571 remaining_size -= copy_amount;
572 }
573}
574
575void ReadBlock(const VAddr src_addr, void* dest_buffer, const std::size_t size) {
576 ReadBlock(*Core::System::GetInstance().CurrentProcess(), src_addr, dest_buffer, size);
577}
578
579void Write8(const VAddr addr, const u8 data) { 615void Write8(const VAddr addr, const u8 data) {
580 Write<u8>(addr, data); 616 Write<u8>(addr, data);
581} 617}