From 34a8d0cc8e04b4b9d8e5a75e552f0adb31b5d718 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 29 Dec 2023 07:53:52 +0100 Subject: SMMU: Implement physical memory mirroring --- src/core/device_memory_manager.h | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) (limited to 'src/core/device_memory_manager.h') diff --git a/src/core/device_memory_manager.h b/src/core/device_memory_manager.h index 1a63cbd09..7c7726348 100644 --- a/src/core/device_memory_manager.h +++ b/src/core/device_memory_manager.h @@ -10,8 +10,10 @@ #include #include "common/common_types.h" +#include "common/scratch_buffer.h" #include "common/virtual_buffer.h" + namespace Core { class DeviceMemory; @@ -49,9 +51,25 @@ public: template const T* GetPointer(DAddr address) const; - DAddr GetAddressFromPAddr(PAddr address) const { + template + void ApplyOpOnPAddr(PAddr address, Common::ScratchBuffer& buffer, Func&& operation) { DAddr subbits = static_cast(address & page_mask); - return (static_cast(compressed_device_addr[(address >> page_bits)]) << page_bits) + subbits; + const u32 base = compressed_device_addr[(address >> page_bits)]; + if ((base >> MULTI_FLAG_BITS) == 0) [[likely]] { + const DAddr d_address = static_cast(base << page_bits) + subbits; + operation(d_address); + return; + } + InnerGatherDeviceAddresses(buffer, address); + for (u32 value : buffer) { + operation(static_cast(value << page_bits) + subbits); + } + } + + template + void ApplyOpOnPointer(const u8* p, Common::ScratchBuffer& buffer, Func&& operation) { + PAddr address = GetRawPhysicalAddr(p); + ApplyOpOnPAddr(address, buffer, operation); } PAddr GetPhysicalRawAddressFromDAddr(DAddr address) const { @@ -98,6 +116,9 @@ private: static constexpr size_t page_size = 1ULL << page_bits; static constexpr size_t page_mask = page_size - 1ULL; static constexpr u32 physical_address_base = 1U << page_bits; + static constexpr u32 MULTI_FLAG_BITS = 31; + static constexpr u32 MULTI_FLAG = 1U << MULTI_FLAG_BITS; + static constexpr u32 MULTI_MASK = ~MULTI_FLAG; template T* GetPointerFromRaw(PAddr addr) { @@ -117,6 +138,8 @@ private: void WalkBlock(const DAddr addr, const std::size_t size, auto on_unmapped, auto on_memory, auto increment); + void InnerGatherDeviceAddresses(Common::ScratchBuffer& buffer, PAddr address); + std::unique_ptr> impl; const uintptr_t physical_base; -- cgit v1.2.3