diff options
Diffstat (limited to 'src/core/memory.cpp')
-rw-r--r-- | src/core/memory.cpp | 114 |
1 files changed, 77 insertions, 37 deletions
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 169bf4c8c..8176a41be 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -10,6 +10,7 @@ #include "common/assert.h" #include "common/atomic_ops.h" #include "common/common_types.h" +#include "common/heap_tracker.h" #include "common/logging/log.h" #include "common/page_table.h" #include "common/scope_exit.h" @@ -45,11 +46,25 @@ struct Memory::Impl { void SetCurrentPageTable(Kernel::KProcess& process) { current_page_table = &process.GetPageTable().GetImpl(); - current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); + + if (std::addressof(process) == system.ApplicationProcess() && + Settings::IsFastmemEnabled()) { + current_page_table->fastmem_arena = system.DeviceMemory().buffer.VirtualBasePointer(); + } else { + current_page_table->fastmem_arena = nullptr; + } + +#ifdef __linux__ + heap_tracker.emplace(system.DeviceMemory().buffer); + buffer = std::addressof(*heap_tracker); +#else + buffer = std::addressof(system.DeviceMemory().buffer); +#endif } void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, - Common::PhysicalAddress target, Common::MemoryPermission perms) { + Common::PhysicalAddress target, Common::MemoryPermission perms, + bool separate_heap) { ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); ASSERT_MSG(target >= DramMemoryMap::Base, "Out of bounds target: {:016X}", @@ -57,20 +72,21 @@ struct Memory::Impl { MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, target, Common::PageType::Memory); - if (Settings::IsFastmemEnabled()) { - system.DeviceMemory().buffer.Map(GetInteger(base), - GetInteger(target) - DramMemoryMap::Base, size, perms); + if (current_page_table->fastmem_arena) { + buffer->Map(GetInteger(base), GetInteger(target) - DramMemoryMap::Base, size, perms, + separate_heap); } } - void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { + void UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, + bool separate_heap) { ASSERT_MSG((size & YUZU_PAGEMASK) == 0, "non-page aligned size: {:016X}", size); ASSERT_MSG((base & YUZU_PAGEMASK) == 0, "non-page aligned base: {:016X}", GetInteger(base)); MapPages(page_table, base / YUZU_PAGESIZE, size / YUZU_PAGESIZE, 0, Common::PageType::Unmapped); - if (Settings::IsFastmemEnabled()) { - system.DeviceMemory().buffer.Unmap(GetInteger(base), size); + if (current_page_table->fastmem_arena) { + buffer->Unmap(GetInteger(base), size, separate_heap); } } @@ -79,17 +95,7 @@ struct Memory::Impl { 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); + if (!current_page_table->fastmem_arena) { return; } @@ -101,8 +107,7 @@ struct Memory::Impl { 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); + buffer->Protect(protect_begin, protect_bytes, perms); protect_bytes = 0; } break; @@ -115,7 +120,7 @@ struct Memory::Impl { } if (protect_bytes > 0) { - system.DeviceMemory().buffer.Protect(protect_begin, protect_bytes, is_r, is_w, is_x); + buffer->Protect(protect_begin, protect_bytes, perms); } } @@ -239,7 +244,7 @@ struct Memory::Impl { bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer, auto increment) { - const auto& page_table = system.ApplicationProcess()->GetPageTable().GetImpl(); + const auto& page_table = *current_page_table; std::size_t remaining_size = size; std::size_t page_index = addr >> YUZU_PAGEBITS; std::size_t page_offset = addr & YUZU_PAGEMASK; @@ -484,8 +489,10 @@ struct Memory::Impl { return; } - if (Settings::IsFastmemEnabled()) { - system.DeviceMemory().buffer.Protect(vaddr, size, !debug, !debug); + if (current_page_table->fastmem_arena) { + const auto perm{debug ? Common::MemoryPermission{} + : Common::MemoryPermission::ReadWrite}; + buffer->Protect(vaddr, size, perm); } // Iterate over a contiguous CPU address space, marking/unmarking the region. @@ -541,10 +548,15 @@ struct Memory::Impl { return; } - if (Settings::IsFastmemEnabled()) { - const bool is_read_enable = - !Settings::values.use_reactive_flushing.GetValue() || !cached; - system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); + if (current_page_table->fastmem_arena) { + Common::MemoryPermission perm{}; + if (!Settings::values.use_reactive_flushing.GetValue() || !cached) { + perm |= Common::MemoryPermission::Read; + } + if (!cached) { + perm |= Common::MemoryPermission::Write; + } + buffer->Protect(vaddr, size, perm); } // Iterate over a contiguous CPU address space, which corresponds to the specified GPU @@ -855,6 +867,13 @@ struct Memory::Impl { std::array<GPUDirtyState, Core::Hardware::NUM_CPU_CORES> rasterizer_write_areas{}; std::span<Core::GPUDirtyMemoryManager> gpu_dirty_managers; std::mutex sys_core_guard; + + std::optional<Common::HeapTracker> heap_tracker; +#ifdef __linux__ + Common::HeapTracker* buffer{}; +#else + Common::HostMemory* buffer{}; +#endif }; Memory::Memory(Core::System& system_) : system{system_} { @@ -872,12 +891,14 @@ void Memory::SetCurrentPageTable(Kernel::KProcess& process) { } void Memory::MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, - Common::PhysicalAddress target, Common::MemoryPermission perms) { - impl->MapMemoryRegion(page_table, base, size, target, perms); + Common::PhysicalAddress target, Common::MemoryPermission perms, + bool separate_heap) { + impl->MapMemoryRegion(page_table, base, size, target, perms, separate_heap); } -void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size) { - impl->UnmapRegion(page_table, base, size); +void Memory::UnmapRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, + bool separate_heap) { + impl->UnmapRegion(page_table, base, size, separate_heap); } void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress vaddr, u64 size, @@ -886,8 +907,7 @@ void Memory::ProtectRegion(Common::PageTable& page_table, Common::ProcessAddress } bool Memory::IsValidVirtualAddress(const Common::ProcessAddress vaddr) const { - const Kernel::KProcess& process = *system.ApplicationProcess(); - const auto& page_table = process.GetPageTable().GetImpl(); + const auto& page_table = *impl->current_page_table; const size_t page = vaddr >> YUZU_PAGEBITS; if (page >= page_table.pointers.size()) { return false; @@ -1048,7 +1068,9 @@ void Memory::FlushRegion(Common::ProcessAddress dest_addr, size_t size) { } bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { - bool mapped = true; + [[maybe_unused]] bool mapped = true; + [[maybe_unused]] bool rasterizer = false; + u8* const ptr = impl->GetPointerImpl( GetInteger(vaddr), [&] { @@ -1056,8 +1078,26 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { GetInteger(vaddr)); mapped = false; }, - [&] { impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); }); + [&] { + impl->system.GPU().InvalidateRegion(GetInteger(vaddr), size); + rasterizer = true; + }); + +#ifdef __linux__ + if (!rasterizer && mapped) { + impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr)); + } +#endif + return mapped && ptr != nullptr; } +bool Memory::InvalidateSeparateHeap(void* fault_address) { +#ifdef __linux__ + return impl->buffer->DeferredMapSeparateHeap(static_cast<u8*>(fault_address)); +#else + return false; +#endif +} + } // namespace Core::Memory |