diff options
author | Fernando Sahmkow <fsahmkow27@gmail.com> | 2023-12-25 07:32:16 +0100 |
---|---|---|
committer | Liam <byteslice@airmail.cc> | 2024-01-19 03:12:30 +0100 |
commit | 0a2536a0df1f4aea406f2132d3edda0430acc9d1 (patch) | |
tree | c0ad53890581c9c7e180c5ccb3b66e3c63e3ba64 /src/core/device_memory_manager.inc | |
parent | SMMU: Implement backing CPU page protect/unprotect (diff) | |
download | yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.gz yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.bz2 yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.lz yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.xz yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.tar.zst yuzu-0a2536a0df1f4aea406f2132d3edda0430acc9d1.zip |
Diffstat (limited to 'src/core/device_memory_manager.inc')
-rw-r--r-- | src/core/device_memory_manager.inc | 72 |
1 files changed, 64 insertions, 8 deletions
diff --git a/src/core/device_memory_manager.inc b/src/core/device_memory_manager.inc index 77410f72f..8c5f82d31 100644 --- a/src/core/device_memory_manager.inc +++ b/src/core/device_memory_manager.inc @@ -105,7 +105,8 @@ template <typename Traits> DeviceMemoryManager<Traits>::DeviceMemoryManager(const DeviceMemory& device_memory_) : physical_base{reinterpret_cast<const uintptr_t>(device_memory_.buffer.BackingBasePointer())}, interface{nullptr}, compressed_physical_ptr(device_as_size >> Memory::YUZU_PAGEBITS), - compressed_device_addr(1ULL << (physical_max_bits - Memory::YUZU_PAGEBITS)) { + compressed_device_addr(1ULL << (physical_max_bits - Memory::YUZU_PAGEBITS)), + cpu_backing_address(device_as_size >> Memory::YUZU_PAGEBITS) { impl = std::make_unique<DeviceMemoryManagerAllocator<Traits>>(); cached_pages = std::make_unique<CachedPages>(); } @@ -144,10 +145,10 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size Core::Memory::Memory* process_memory = registered_processes[process_id]; size_t start_page_d = address >> Memory::YUZU_PAGEBITS; size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; - std::atomic_thread_fence(std::memory_order_acquire); + std::scoped_lock lk(mapping_guard); for (size_t i = 0; i < num_pages; i++) { const VAddr new_vaddress = virtual_address + i * Memory::YUZU_PAGESIZE; - auto* ptr = process_memory->GetPointer(Common::ProcessAddress(new_vaddress)); + auto* ptr = process_memory->GetPointerSilent(Common::ProcessAddress(new_vaddress)); if (ptr == nullptr) [[unlikely]] { compressed_physical_ptr[start_page_d + i] = 0; continue; @@ -157,14 +158,14 @@ void DeviceMemoryManager<Traits>::Map(DAddr address, VAddr virtual_address, size compressed_device_addr[phys_addr - 1U] = static_cast<u32>(start_page_d + i); InsertCPUBacking(start_page_d + i, new_vaddress, process_id); } - std::atomic_thread_fence(std::memory_order_release); } template <typename Traits> void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { size_t start_page_d = address >> Memory::YUZU_PAGEBITS; size_t num_pages = Common::AlignUp(size, Memory::YUZU_PAGESIZE) >> Memory::YUZU_PAGEBITS; - std::atomic_thread_fence(std::memory_order_acquire); + interface->InvalidateRegion(address, size); + std::scoped_lock lk(mapping_guard); for (size_t i = 0; i < num_pages; i++) { auto phys_addr = compressed_physical_ptr[start_page_d + i]; compressed_physical_ptr[start_page_d + i] = 0; @@ -173,7 +174,6 @@ void DeviceMemoryManager<Traits>::Unmap(DAddr address, size_t size) { compressed_device_addr[phys_addr - 1] = 0; } } - std::atomic_thread_fence(std::memory_order_release); } template <typename Traits> @@ -256,6 +256,45 @@ void DeviceMemoryManager<Traits>::WalkBlock(DAddr addr, std::size_t size, auto o template <typename Traits> void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, size_t size) { + interface->FlushRegion(address, size); + WalkBlock( + address, size, + [&](size_t copy_amount, DAddr current_vaddr) { + LOG_ERROR( + HW_Memory, + "Unmapped Device ReadBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", + current_vaddr, address, size); + std::memset(dest_pointer, 0, copy_amount); + }, + [&](size_t copy_amount, const u8* const src_ptr) { + std::memcpy(dest_pointer, src_ptr, copy_amount); + }, + [&](const std::size_t copy_amount) { + dest_pointer = static_cast<u8*>(dest_pointer) + copy_amount; + }); +} + +template <typename Traits> +void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, const void* src_pointer, size_t size) { + WalkBlock( + address, size, + [&](size_t copy_amount, DAddr current_vaddr) { + LOG_ERROR( + HW_Memory, + "Unmapped Device WriteBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", + current_vaddr, address, size); + }, + [&](size_t copy_amount, u8* const dst_ptr) { + std::memcpy(dst_ptr, src_pointer, copy_amount); + }, + [&](const std::size_t copy_amount) { + src_pointer = static_cast<const u8*>(src_pointer) + copy_amount; + }); + interface->InvalidateRegion(address, size); +} + +template <typename Traits> +void DeviceMemoryManager<Traits>::ReadBlockUnsafe(DAddr address, void* dest_pointer, size_t size) { WalkBlock( address, size, [&](size_t copy_amount, DAddr current_vaddr) { @@ -274,7 +313,8 @@ void DeviceMemoryManager<Traits>::ReadBlock(DAddr address, void* dest_pointer, s } template <typename Traits> -void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, void* src_pointer, size_t size) { +void DeviceMemoryManager<Traits>::WriteBlockUnsafe(DAddr address, const void* src_pointer, + size_t size) { WalkBlock( address, size, [&](size_t copy_amount, DAddr current_vaddr) { @@ -287,7 +327,7 @@ void DeviceMemoryManager<Traits>::WriteBlock(DAddr address, void* src_pointer, s std::memcpy(dst_ptr, src_pointer, copy_amount); }, [&](const std::size_t copy_amount) { - src_pointer = static_cast<u8*>(src_pointer) + copy_amount; + src_pointer = static_cast<const u8*>(src_pointer) + copy_amount; }); } @@ -313,6 +353,18 @@ void DeviceMemoryManager<Traits>::UnregisterProcess(size_t id) { template <typename Traits> void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size, s32 delta) { + bool locked = false; + auto lock = [&] { + if (!locked) { + counter_guard.lock(); + locked = true; + } + }; + SCOPE_EXIT({ + if (locked) { + counter_guard.unlock(); + } + }); u64 uncache_begin = 0; u64 cache_begin = 0; u64 uncache_bytes = 0; @@ -347,6 +399,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size } uncache_bytes += Memory::YUZU_PAGESIZE; } else if (uncache_bytes > 0) { + lock(); MarkRegionCaching(memory_interface, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, false); uncache_bytes = 0; @@ -357,6 +410,7 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size } cache_bytes += Memory::YUZU_PAGESIZE; } else if (cache_bytes > 0) { + lock(); MarkRegionCaching(memory_interface, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, true); cache_bytes = 0; @@ -364,10 +418,12 @@ void DeviceMemoryManager<Traits>::UpdatePagesCachedCount(DAddr addr, size_t size vpage++; } if (uncache_bytes > 0) { + lock(); MarkRegionCaching(memory_interface, uncache_begin << Memory::YUZU_PAGEBITS, uncache_bytes, false); } if (cache_bytes > 0) { + lock(); MarkRegionCaching(memory_interface, cache_begin << Memory::YUZU_PAGEBITS, cache_bytes, true); } |