summaryrefslogtreecommitdiffstats
path: root/src/core/memory.cpp
diff options
context:
space:
mode:
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 {
return system.DeviceMemory().GetPointer(paddr) + vaddr;
}
+ [[nodiscard]] u8* GetPointerFromDebugMemory(VAddr vaddr) const {
+ const PAddr paddr{current_page_table->backing_addr[vaddr >> PAGE_BITS]};
+
+ if (paddr == 0) {
+ return {};
+ }
+
+ return system.DeviceMemory().GetPointer(paddr) + vaddr;
+ }
+
u8 Read8(const VAddr addr) {
return Read<u8>(addr);
}
@@ -187,6 +197,12 @@ struct Memory::Impl {
on_memory(copy_amount, mem_ptr);
break;
}
+ case Common::PageType::DebugMemory: {
+ DEBUG_ASSERT(pointer);
+ u8* const mem_ptr{GetPointerFromDebugMemory(current_vaddr)};
+ on_memory(copy_amount, mem_ptr);
+ break;
+ }
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr{GetPointerFromRasterizerCachedMemory(current_vaddr)};
on_rasterizer(current_vaddr, copy_amount, host_ptr);
@@ -316,6 +332,58 @@ struct Memory::Impl {
});
}
+ void MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
+ if (vaddr == 0) {
+ return;
+ }
+
+ // Iterate over a contiguous CPU address space, marking/unmarking the region.
+ // The region is at a granularity of CPU pages.
+
+ const u64 num_pages = ((vaddr + size - 1) >> PAGE_BITS) - (vaddr >> PAGE_BITS) + 1;
+ for (u64 i = 0; i < num_pages; ++i, vaddr += PAGE_SIZE) {
+ const Common::PageType page_type{
+ current_page_table->pointers[vaddr >> PAGE_BITS].Type()};
+ if (debug) {
+ // Switch page type to debug if now debug
+ switch (page_type) {
+ case Common::PageType::Unmapped:
+ ASSERT_MSG(false, "Attempted to mark unmapped pages as debug");
+ break;
+ case Common::PageType::RasterizerCachedMemory:
+ case Common::PageType::DebugMemory:
+ // Page is already marked.
+ break;
+ case Common::PageType::Memory:
+ current_page_table->pointers[vaddr >> PAGE_BITS].Store(
+ nullptr, Common::PageType::DebugMemory);
+ break;
+ default:
+ UNREACHABLE();
+ }
+ } else {
+ // Switch page type to non-debug if now non-debug
+ switch (page_type) {
+ case Common::PageType::Unmapped:
+ ASSERT_MSG(false, "Attempted to mark unmapped pages as non-debug");
+ break;
+ case Common::PageType::RasterizerCachedMemory:
+ case Common::PageType::Memory:
+ // Don't mess with already non-debug or rasterizer memory.
+ break;
+ case Common::PageType::DebugMemory: {
+ u8* const pointer{GetPointerFromDebugMemory(vaddr & ~PAGE_MASK)};
+ current_page_table->pointers[vaddr >> PAGE_BITS].Store(
+ pointer - (vaddr & ~PAGE_MASK), Common::PageType::Memory);
+ break;
+ }
+ default:
+ UNREACHABLE();
+ }
+ }
+ }
+ }
+
void RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
if (vaddr == 0) {
return;
@@ -342,6 +410,7 @@ struct Memory::Impl {
// It is not necessary for a process to have this region mapped into its address
// space, for example, a system module need not have a VRAM mapping.
break;
+ case Common::PageType::DebugMemory:
case Common::PageType::Memory:
current_page_table->pointers[vaddr >> PAGE_BITS].Store(
nullptr, Common::PageType::RasterizerCachedMemory);
@@ -360,6 +429,7 @@ struct Memory::Impl {
// It is not necessary for a process to have this region mapped into its address
// space, for example, a system module need not have a VRAM mapping.
break;
+ case Common::PageType::DebugMemory:
case Common::PageType::Memory:
// There can be more than one GPU region mapped per CPU region, so it's common
// that this area is already unmarked as cached.
@@ -460,6 +530,8 @@ struct Memory::Impl {
case Common::PageType::Memory:
ASSERT_MSG(false, "Mapped memory page without a pointer @ 0x{:016X}", vaddr);
return nullptr;
+ case Common::PageType::DebugMemory:
+ return GetPointerFromDebugMemory(vaddr);
case Common::PageType::RasterizerCachedMemory: {
u8* const host_ptr{GetPointerFromRasterizerCachedMemory(vaddr)};
on_rasterizer();
@@ -591,7 +663,8 @@ bool Memory::IsValidVirtualAddress(const VAddr vaddr) const {
return false;
}
const auto [pointer, type] = page_table.pointers[page].PointerType();
- return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory;
+ return pointer != nullptr || type == Common::PageType::RasterizerCachedMemory ||
+ type == Common::PageType::DebugMemory;
}
bool Memory::IsValidVirtualAddressRange(VAddr base, u64 size) const {
@@ -707,4 +780,8 @@ void Memory::RasterizerMarkRegionCached(VAddr vaddr, u64 size, bool cached) {
impl->RasterizerMarkRegionCached(vaddr, size, cached);
}
+void Memory::MarkRegionDebug(VAddr vaddr, u64 size, bool debug) {
+ impl->MarkRegionDebug(vaddr, size, debug);
+}
+
} // namespace Core::Memory