diff options
| author | 2022-06-06 12:56:01 -0400 | |
|---|---|---|
| committer | 2022-06-16 13:18:07 -0400 | |
| commit | 208ed712f42cfd277405a22663197dc1c5e84cfe (patch) | |
| tree | 56c1a3cbddf392d700e817cd4093564e3f096013 /src/core/memory.cpp | |
| parent | Merge pull request #8457 from liamwhite/kprocess-suspend (diff) | |
| download | yuzu-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.cpp | 79 |
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 | ||
| 597 | bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const { | 670 | bool 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 | ||
| 783 | void Memory::MarkRegionDebug(VAddr vaddr, u64 size, bool debug) { | ||
| 784 | impl->MarkRegionDebug(vaddr, size, debug); | ||
| 785 | } | ||
| 786 | |||
| 710 | } // namespace Core::Memory | 787 | } // namespace Core::Memory |