diff options
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r-- | src/core/memory.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index e5ca78ef4..5b376b202 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -78,6 +78,51 @@ struct Memory::Impl { } } + void ProtectRegion(Common::PageTable& page_table, VAddr vaddr, u64 size, + Common::MemoryPermission perms) { + ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); + ASSERT_MSG((vaddr & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", vaddr); + + if (!Settings::IsFastmemEnabled()) { + return; + } + + const bool is_r = True(perms & Common::MemoryPermission::Read); + const bool is_w = True(perms & Common::MemoryPermission::Write); + const bool is_x = + True(perms & Common::MemoryPermission::Execute) && Settings::IsNceEnabled(); + + if (!current_page_table) { + system.DeviceMemory().buffer.Protect(vaddr, size, is_r, is_w, is_x); + return; + } + + u64 protect_bytes{}; + u64 protect_begin{}; + for (u64 addr = vaddr; addr < vaddr + size; addr += YUZU_PAGESIZE) { + const Common::PageType page_type{ + current_page_table->pointers[addr >> YUZU_PAGEBITS].Type()}; + switch (page_type) { + case Common::PageType::RasterizerCachedMemory: + if (protect_bytes > 0) { + system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, + is_x); + protect_bytes = 0; + } + break; + default: + if (protect_bytes == 0) { + protect_begin = addr; + } + protect_bytes += YUZU_PAGESIZE; + } + } + + if (protect_bytes > 0) { + system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, is_x); + } + } + [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { const Common::PhysicalAddress paddr{ current_page_table->backing_addr[vaddr >> YUZU_PAGEBITS]}; @@ -839,6 +884,11 @@ void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress b impl->UnmapRegion(page_table, base, size); } +void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress vaddr, u64 size, + Common::MemoryPermission perms) { + impl->ProtectRegion(page_table, GetInteger(vaddr), size, perms); +} + bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { const Kernel::KProcess& process = *system.ApplicationProcess(); const auto& page_table = process.GetPageTable().GetImpl(); |