summaryrefslogtreecommitdiff
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
authorGravatar Liam2022-06-06 12:56:01 -0400
committerGravatar Liam2022-06-16 13:18:07 -0400
commit208ed712f42cfd277405a22663197dc1c5e84cfe (patch)
tree56c1a3cbddf392d700e817cd4093564e3f096013 /src/core/memory.cpp
parentMerge pull request #8457 from liamwhite/kprocess-suspend (diff)
downloadyuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.tar.gz
yuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.tar.xz
yuzu-208ed712f42cfd277405a22663197dc1c5e84cfe.zip
core/debugger: memory breakpoint support
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r--src/core/memory.cpp79
1 files changed, 78 insertions, 1 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index 7534de01e..584808d50 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -67,6 +67,16 @@ struct Memory::Impl {
67 return system.DeviceMemory().GetPointer(paddr) + vaddr; 67 return system.DeviceMemory().GetPointer(paddr) + vaddr;
68 } 68 }
69 69
70 [[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const {
71 const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]};
72
73 if (paddr == 0) {
74 return {};
75 }
76
77 return system.DeviceMemory().GetPointer(paddr) + vaddr;
78 }
79
70 u8 Read8(const VAddr addr) { 80 u8 Read8(const VAddr addr) {
71 return Read<u8>(addr); 81 return Read<u8>(addr);
72 } 82 }
@@ -187,6 +197,12 @@ struct Memory::Impl {
187 on_memory(copy_amount, mem_ptr); 197 on_memory(copy_amount, mem_ptr);
188 break; 198 break;
189 } 199 }
200 case Common::PageType::DebugMemory: {
201 DEBUG_ASSERT(pointer);
202 u8* const mem_ptr{GetPointerFromDebugMemory(current_vaddr)};
203 on_memory(copy_amount, mem_ptr);
204 break;
205 }
190 case Common::PageType::RasterizerCachedMemory: { 206 case Common::PageType::RasterizerCachedMemory: {
191 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)}; 207 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
192 on_rasterizer(current_vaddr, copy_amount, host_ptr); 208 on_rasterizer(current_vaddr, copy_amount, host_ptr);
@@ -316,6 +332,58 @@ struct Memory::Impl {
316 }); 332 });
317 } 333 }
318 334
335 void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
336 if (vaddr == 0) {
337 return;
338 }
339
340 // Iterate over a contiguous CPU address space, marking/unmarking the region.
341 // The region is at a granularity of CPU pages.
342
343 const u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1;
344 for (u64 i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
345 const Common::PageType page_type{
346 current_page_table->pointers[vaddr >> PAGE_BITS].Type()};
347 if (debug) {
348 // Switch page type to debug if now debug
349 switch (page_type) {
350 case Common::PageType::Unmapped:
351 ASSERT_MSG(false, "Attempted to mark unmapped pages as debug");
352 break;
353 case Common::PageType::RasterizerCachedMemory:
354 case Common::PageType::DebugMemory:
355 // Page is already marked.
356 break;
357 case Common::PageType::Memory:
358 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
359 nullptr, Common::PageType::DebugMemory);
360 break;
361 default:
362 UNREACHABLE();
363 }
364 } else {
365 // Switch page type to non-debug if now non-debug
366 switch (page_type) {
367 case Common::PageType::Unmapped:
368 ASSERT_MSG(false, "Attempted to mark unmapped pages as non-debug");
369 break;
370 case Common::PageType::RasterizerCachedMemory:
371 case Common::PageType::Memory:
372 // Don't mess with already non-debug or rasterizer memory.
373 break;
374 case Common::PageType::DebugMemory: {
375 u8* const pointer{GetPointerFromDebugMemory(vaddr & ~PAGE_MASK)};
376 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
377 pointer - (vaddr & ~PAGE_MASK), Common::PageType::Memory);
378 break;
379 }
380 default:
381 UNREACHABLE();
382 }
383 }
384 }
385 }
386
319 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) { 387 void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
320 if (vaddr == 0) { 388 if (vaddr == 0) {
321 return; 389 return;
@@ -342,6 +410,7 @@ struct Memory::Impl {
342 // It is not necessary for a process to have this region mapped into its address 410 // It is not necessary for a process to have this region mapped into its address
343 // space, for example, a system module need not have a VRAM mapping. 411 // space, for example, a system module need not have a VRAM mapping.
344 break; 412 break;
413 case Common::PageType::DebugMemory:
345 case Common::PageType::Memory: 414 case Common::PageType::Memory:
346 current_page_table->pointers[vaddr >> PAGE_BITS].Store( 415 current_page_table->pointers[vaddr >> PAGE_BITS].Store(
347 nullptr, Common::PageType::RasterizerCachedMemory); 416 nullptr, Common::PageType::RasterizerCachedMemory);
@@ -360,6 +429,7 @@ struct Memory::Impl {
360 // It is not necessary for a process to have this region mapped into its address 429 // It is not necessary for a process to have this region mapped into its address
361 // space, for example, a system module need not have a VRAM mapping. 430 // space, for example, a system module need not have a VRAM mapping.
362 break; 431 break;
432 case Common::PageType::DebugMemory:
363 case Common::PageType::Memory: 433 case Common::PageType::Memory:
364 // There can be more than one GPU region mapped per CPU region, so it's common 434 // There can be more than one GPU region mapped per CPU region, so it's common
365 // that this area is already unmarked as cached. 435 // that this area is already unmarked as cached.
@@ -460,6 +530,8 @@ struct Memory::Impl {
460 case Common::PageType::Memory: 530 case Common::PageType::Memory:
461 ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr); 531 ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
462 return nullptr; 532 return nullptr;
533 case Common::PageType::DebugMemory:
534 return GetPointerFromDebugMemory(vaddr);
463 case Common::PageType::RasterizerCachedMemory: { 535 case Common::PageType::RasterizerCachedMemory: {
464 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)}; 536 u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
465 on_rasterizer(); 537 on_rasterizer();
@@ -591,7 +663,8 @@ bool Memory::IsValidVirtualAddress(const VAddr vaddr) const {
591 return false; 663 return false;
592 } 664 }
593 const auto [pointer, type] = page_table.pointers[page].PointerType(); 665 const auto [pointer, type] = page_table.pointers[page].PointerType();
594 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory; 666 return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory ||
667 type == Common::PageType::DebugMemory;
595} 668}
596 669
597bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { 670bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const {
@@ -707,4 +780,8 @@ void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
707 impl->RasterizerMarkRegionCached(vaddr, size, cached); 780 impl->RasterizerMarkRegionCached(vaddr, size, cached);
708} 781}
709 782
783void Memory::MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
784 impl->MarkRegionDebug(vaddr, size, debug);
785}
786
710} // namespace Core::Memory 787} // namespace Core::Memory