memory: minimize dependency on process

This commit is contained in:
Liam 2023-07-14 22:19:59 -04:00
parent 3e4029b238
commit d144168442
2 changed files with 63 additions and 65 deletions

View File

@ -183,13 +183,13 @@ struct Memory::Impl {
return string; return string;
} }
void WalkBlock(const Kernel::KProcess& process, const Common::ProcessAddress addr, bool WalkBlock(const Common::ProcessAddress addr, const std::size_t size, auto on_unmapped,
const std::size_t size, auto on_unmapped, auto on_memory, auto on_rasterizer, auto on_memory, auto on_rasterizer, auto increment) {
auto increment) { const auto& page_table = system.ApplicationProcess()->GetPageTable().PageTableImpl();
const auto& page_table = process.GetPageTable().PageTableImpl();
std::size_t remaining_size = size; std::size_t remaining_size = size;
std::size_t page_index = addr >> YUZU_PAGEBITS; std::size_t page_index = addr >> YUZU_PAGEBITS;
std::size_t page_offset = addr & YUZU_PAGEMASK; std::size_t page_offset = addr & YUZU_PAGEMASK;
bool user_accessible = true;
while (remaining_size) { while (remaining_size) {
const std::size_t copy_amount = const std::size_t copy_amount =
@ -200,6 +200,7 @@ struct Memory::Impl {
const auto [pointer, type] = page_table.pointers[page_index].PointerType(); const auto [pointer, type] = page_table.pointers[page_index].PointerType();
switch (type) { switch (type) {
case Common::PageType::Unmapped: { case Common::PageType::Unmapped: {
user_accessible = false;
on_unmapped(copy_amount, current_vaddr); on_unmapped(copy_amount, current_vaddr);
break; break;
} }
@ -227,13 +228,15 @@ struct Memory::Impl {
increment(copy_amount); increment(copy_amount);
remaining_size -= copy_amount; remaining_size -= copy_amount;
} }
return user_accessible;
} }
template <bool UNSAFE> template <bool UNSAFE>
void ReadBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress src_addr, bool ReadBlockImpl(const Common::ProcessAddress src_addr, void* dest_buffer,
void* dest_buffer, const std::size_t size) { const std::size_t size) {
WalkBlock( return WalkBlock(
process, src_addr, size, src_addr, size,
[src_addr, size, &dest_buffer](const std::size_t copy_amount, [src_addr, size, &dest_buffer](const std::size_t copy_amount,
const Common::ProcessAddress current_vaddr) { const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
@ -256,14 +259,14 @@ struct Memory::Impl {
}); });
} }
void ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, bool ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) { const std::size_t size) {
ReadBlockImpl<false>(*system.ApplicationProcess(), src_addr, dest_buffer, size); return ReadBlockImpl<false>(src_addr, dest_buffer, size);
} }
void ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, bool ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) { const std::size_t size) {
ReadBlockImpl<true>(*system.ApplicationProcess(), src_addr, dest_buffer, size); return ReadBlockImpl<true>(src_addr, dest_buffer, size);
} }
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const { const u8* GetSpan(const VAddr src_addr, const std::size_t size) const {
@ -283,10 +286,10 @@ struct Memory::Impl {
} }
template <bool UNSAFE> template <bool UNSAFE>
void WriteBlockImpl(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, bool WriteBlockImpl(const Common::ProcessAddress dest_addr, const void* src_buffer,
const void* src_buffer, const std::size_t size) { const std::size_t size) {
WalkBlock( return WalkBlock(
process, dest_addr, size, dest_addr, size,
[dest_addr, size](const std::size_t copy_amount, [dest_addr, size](const std::size_t copy_amount,
const Common::ProcessAddress current_vaddr) { const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
@ -308,20 +311,19 @@ struct Memory::Impl {
}); });
} }
void WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, bool WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) { const std::size_t size) {
WriteBlockImpl<false>(*system.ApplicationProcess(), dest_addr, src_buffer, size); return WriteBlockImpl<false>(dest_addr, src_buffer, size);
} }
void WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, bool WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) { const std::size_t size) {
WriteBlockImpl<true>(*system.ApplicationProcess(), dest_addr, src_buffer, size); return WriteBlockImpl<true>(dest_addr, src_buffer, size);
} }
void ZeroBlock(const Kernel::KProcess& process, const Common::ProcessAddress dest_addr, bool ZeroBlock(const Common::ProcessAddress dest_addr, const std::size_t size) {
const std::size_t size) { return WalkBlock(
WalkBlock( dest_addr, size,
process, dest_addr, size,
[dest_addr, size](const std::size_t copy_amount, [dest_addr, size](const std::size_t copy_amount,
const Common::ProcessAddress current_vaddr) { const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
@ -339,23 +341,23 @@ struct Memory::Impl {
[](const std::size_t copy_amount) {}); [](const std::size_t copy_amount) {});
} }
void CopyBlock(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
Common::ProcessAddress src_addr, const std::size_t size) { const std::size_t size) {
WalkBlock( return WalkBlock(
process, dest_addr, size, dest_addr, size,
[&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) { [&](const std::size_t copy_amount, const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, LOG_ERROR(HW_Memory,
"Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})", "Unmapped CopyBlock @ 0x{:016X} (start address = 0x{:016X}, size = {})",
GetInteger(current_vaddr), GetInteger(src_addr), size); GetInteger(current_vaddr), GetInteger(src_addr), size);
ZeroBlock(process, dest_addr, copy_amount); ZeroBlock(dest_addr, copy_amount);
}, },
[&](const std::size_t copy_amount, const u8* const src_ptr) { [&](const std::size_t copy_amount, const u8* const src_ptr) {
WriteBlockImpl<false>(process, dest_addr, src_ptr, copy_amount); WriteBlockImpl<false>(dest_addr, src_ptr, copy_amount);
}, },
[&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount, [&](const Common::ProcessAddress current_vaddr, const std::size_t copy_amount,
u8* const host_ptr) { u8* const host_ptr) {
HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount); HandleRasterizerDownload(GetInteger(current_vaddr), copy_amount);
WriteBlockImpl<false>(process, dest_addr, host_ptr, copy_amount); WriteBlockImpl<false>(dest_addr, host_ptr, copy_amount);
}, },
[&](const std::size_t copy_amount) { [&](const std::size_t copy_amount) {
dest_addr += copy_amount; dest_addr += copy_amount;
@ -364,13 +366,13 @@ struct Memory::Impl {
} }
template <typename Callback> template <typename Callback>
Result PerformCacheOperation(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, Result PerformCacheOperation(Common::ProcessAddress dest_addr, std::size_t size,
std::size_t size, Callback&& cb) { Callback&& cb) {
class InvalidMemoryException : public std::exception {}; class InvalidMemoryException : public std::exception {};
try { try {
WalkBlock( WalkBlock(
process, dest_addr, size, dest_addr, size,
[&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) { [&](const std::size_t block_size, const Common::ProcessAddress current_vaddr) {
LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}", LOG_ERROR(HW_Memory, "Unmapped cache maintenance @ {:#018X}",
GetInteger(current_vaddr)); GetInteger(current_vaddr));
@ -387,37 +389,34 @@ struct Memory::Impl {
return ResultSuccess; return ResultSuccess;
} }
Result InvalidateDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, Result InvalidateDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) { const std::size_t block_size) {
// dc ivac: Invalidate to point of coherency // dc ivac: Invalidate to point of coherency
// GPU flush -> CPU invalidate // GPU flush -> CPU invalidate
HandleRasterizerDownload(GetInteger(current_vaddr), block_size); HandleRasterizerDownload(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
Result StoreDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, Result StoreDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) { const std::size_t block_size) {
// dc cvac: Store to point of coherency // dc cvac: Store to point of coherency
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
Result FlushDataCache(const Kernel::KProcess& process, Common::ProcessAddress dest_addr, Result FlushDataCache(Common::ProcessAddress dest_addr, std::size_t size) {
std::size_t size) {
auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr, auto on_rasterizer = [&](const Common::ProcessAddress current_vaddr,
const std::size_t block_size) { const std::size_t block_size) {
// dc civac: Store to point of coherency, and invalidate from cache // dc civac: Store to point of coherency, and invalidate from cache
// CPU flush -> GPU invalidate // CPU flush -> GPU invalidate
system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size); system.GPU().InvalidateRegion(GetInteger(current_vaddr), block_size);
}; };
return PerformCacheOperation(process, dest_addr, size, on_rasterizer); return PerformCacheOperation(dest_addr, size, on_rasterizer);
} }
void MarkRegionDebug(u64 vaddr, u64 size, bool debug) { void MarkRegionDebug(u64 vaddr, u64 size, bool debug) {
@ -899,14 +898,14 @@ std::string Memory::ReadCString(Common::ProcessAddress vaddr, std::size_t max_le
return impl->ReadCString(vaddr, max_length); return impl->ReadCString(vaddr, max_length);
} }
void Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer, bool Memory::ReadBlock(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) { const std::size_t size) {
impl->ReadBlock(src_addr, dest_buffer, size); return impl->ReadBlock(src_addr, dest_buffer, size);
} }
void Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer, bool Memory::ReadBlockUnsafe(const Common::ProcessAddress src_addr, void* dest_buffer,
const std::size_t size) { const std::size_t size) {
impl->ReadBlockUnsafe(src_addr, dest_buffer, size); return impl->ReadBlockUnsafe(src_addr, dest_buffer, size);
} }
const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const { const u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) const {
@ -917,23 +916,23 @@ u8* Memory::GetSpan(const VAddr src_addr, const std::size_t size) {
return impl->GetSpan(src_addr, size); return impl->GetSpan(src_addr, size);
} }
void Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer, bool Memory::WriteBlock(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) { const std::size_t size) {
impl->WriteBlock(dest_addr, src_buffer, size); return impl->WriteBlock(dest_addr, src_buffer, size);
} }
void Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer, bool Memory::WriteBlockUnsafe(const Common::ProcessAddress dest_addr, const void* src_buffer,
const std::size_t size) { const std::size_t size) {
impl->WriteBlockUnsafe(dest_addr, src_buffer, size); return impl->WriteBlockUnsafe(dest_addr, src_buffer, size);
} }
void Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, bool Memory::CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
const std::size_t size) { const std::size_t size) {
impl->CopyBlock(*system.ApplicationProcess(), dest_addr, src_addr, size); return impl->CopyBlock(dest_addr, src_addr, size);
} }
void Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) { bool Memory::ZeroBlock(Common::ProcessAddress dest_addr, const std::size_t size) {
impl->ZeroBlock(*system.ApplicationProcess(), dest_addr, size); return impl->ZeroBlock(dest_addr, size);
} }
void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) { void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers) {
@ -941,15 +940,15 @@ void Memory::SetGPUDirtyManagers(std::span<Core::GPUDirtyMemoryManager> managers
} }
Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { Result Memory::InvalidateDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
return impl->InvalidateDataCache(*system.ApplicationProcess(), dest_addr, size); return impl->InvalidateDataCache(dest_addr, size);
} }
Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { Result Memory::StoreDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
return impl->StoreDataCache(*system.ApplicationProcess(), dest_addr, size); return impl->StoreDataCache(dest_addr, size);
} }
Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) { Result Memory::FlushDataCache(Common::ProcessAddress dest_addr, const std::size_t size) {
return impl->FlushDataCache(*system.ApplicationProcess(), dest_addr, size); return impl->FlushDataCache(dest_addr, size);
} }
void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) { void Memory::RasterizerMarkRegionCached(Common::ProcessAddress vaddr, u64 size, bool cached) {

View File

@ -24,7 +24,6 @@ class GPUDirtyMemoryManager;
} // namespace Core } // namespace Core
namespace Kernel { namespace Kernel {
class PhysicalMemory;
class KProcess; class KProcess;
} // namespace Kernel } // namespace Kernel
@ -330,7 +329,7 @@ public:
* @post The range [dest_buffer, size) contains the read bytes from the * @post The range [dest_buffer, size) contains the read bytes from the
* current process' address space. * current process' address space.
*/ */
void ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); bool ReadBlock(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
/** /**
* Reads a contiguous block of bytes from the current process' address space. * Reads a contiguous block of bytes from the current process' address space.
@ -349,7 +348,7 @@ public:
* @post The range [dest_buffer, size) contains the read bytes from the * @post The range [dest_buffer, size) contains the read bytes from the
* current process' address space. * current process' address space.
*/ */
void ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size); bool ReadBlockUnsafe(Common::ProcessAddress src_addr, void* dest_buffer, std::size_t size);
const u8* GetSpan(const VAddr src_addr, const std::size_t size) const; const u8* GetSpan(const VAddr src_addr, const std::size_t size) const;
u8* GetSpan(const VAddr src_addr, const std::size_t size); u8* GetSpan(const VAddr src_addr, const std::size_t size);
@ -373,7 +372,7 @@ public:
* and will mark that region as invalidated to caches that the active * and will mark that region as invalidated to caches that the active
* graphics backend may be maintaining over the course of execution. * graphics backend may be maintaining over the course of execution.
*/ */
void WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size); bool WriteBlock(Common::ProcessAddress dest_addr, const void* src_buffer, std::size_t size);
/** /**
* Writes a range of bytes into the current process' address space at the specified * Writes a range of bytes into the current process' address space at the specified
@ -391,7 +390,7 @@ public:
* will be ignored and an error will be logged. * will be ignored and an error will be logged.
* *
*/ */
void WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer, bool WriteBlockUnsafe(Common::ProcessAddress dest_addr, const void* src_buffer,
std::size_t size); std::size_t size);
/** /**
@ -405,7 +404,7 @@ public:
* @post The range [dest_addr, size) within the process' address space contains the * @post The range [dest_addr, size) within the process' address space contains the
* same data within the range [src_addr, size). * same data within the range [src_addr, size).
*/ */
void CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr, bool CopyBlock(Common::ProcessAddress dest_addr, Common::ProcessAddress src_addr,
std::size_t size); std::size_t size);
/** /**
@ -418,7 +417,7 @@ public:
* @post The range [dest_addr, size) within the process' address space contains the * @post The range [dest_addr, size) within the process' address space contains the
* value 0. * value 0.
*/ */
void ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size); bool ZeroBlock(Common::ProcessAddress dest_addr, std::size_t size);
/** /**
* Invalidates a range of bytes within the current process' address space at the specified * Invalidates a range of bytes within the current process' address space at the specified