From 66aff82f37fa675ae2304c6c3b250bd659e1d3fc Mon Sep 17 00:00:00 2001 From: Exverge Date: Tue, 28 Jul 2026 16:07:34 -0400 Subject: [PATCH] [page_table] Optimize page table entry --- src/common/page_table.cpp | 24 +++++++++++------------ src/common/page_table.h | 11 +++++------ src/common/sparse_large_vector.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- src/core/memory.cpp | 9 ++++----- 6 files changed, 24 insertions(+), 26 deletions(-) diff --git a/src/common/page_table.cpp b/src/common/page_table.cpp index 740aa0660f..5814688bc9 100644 --- a/src/common/page_table.cpp +++ b/src/common/page_table.cpp @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project @@ -16,7 +16,7 @@ PageTable::~PageTable() noexcept = default; bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, Common::ProcessAddress address) const { out_context->next_offset = GetInteger(address); - out_context->next_page = address / page_size; + out_context->next_page = GetInteger(address) >> current_page_bits; return this->ContinueTraversal(out_entry, out_context); } @@ -24,28 +24,28 @@ bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_ bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const { // Setup invalid defaults. out_entry->phys_addr = 0; - out_entry->block_size = page_size; + out_entry->block_size = 1 << current_page_bits; + // Setup context + context->next_page += 1; + context->next_offset += 1 << current_page_bits; // Validate that we can read the actual entry. if (auto const page = context->next_page; page < entries.size()) { // Validate that the entry is mapped. if (auto const paddr = entries[page].addr; paddr != 0) { - // Populate the results. - out_entry->phys_addr = paddr + context->next_offset; - context->next_page += 1; - context->next_offset += page_size; + // Populate the results and return true + out_entry->phys_addr = (paddr << current_page_bits) + context->next_offset; return true; } } - context->next_page += 1; - context->next_offset += page_size; + // Otherwise return false return false; } -void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_size_in_bits) { - auto const num_page_table_entries = 1ULL << (address_space_width_in_bits - page_size_in_bits); +void PageTable::Resize(std::size_t address_space_width_in_bits, std::size_t page_bits) { + auto const num_page_table_entries = 1ULL << (address_space_width_in_bits - page_bits); entries.ResizeAndClear(num_page_table_entries); current_address_space_width_in_bits = address_space_width_in_bits; - page_size = 1ULL << page_size_in_bits; + current_page_bits = page_bits; } } // namespace Common diff --git a/src/common/page_table.h b/src/common/page_table.h index 4965aee8c1..dd8671c51f 100644 --- a/src/common/page_table.h +++ b/src/common/page_table.h @@ -127,7 +127,7 @@ struct PageTable { return false; } - *out_phys_addr = entries[virt_addr / page_size].addr + GetInteger(virt_addr); + *out_phys_addr = (entries[GetInteger(virt_addr) >> current_page_bits].addr >> current_page_bits) + GetInteger(virt_addr); return true; } @@ -135,16 +135,15 @@ struct PageTable { /// corresponding attribute element is of type `Memory`. struct PageEntryData { PageInfo ptr; - u64 block; - u64 addr; - u64 padding; + u32 block; + u32 addr; }; SparseLargeVector entries; - static_assert(sizeof(PageEntryData) == 32); + static_assert(sizeof(PageEntryData) == 16); u8* fastmem_arena{}; std::size_t current_address_space_width_in_bits{}; - std::size_t page_size{}; + std::size_t current_page_bits{}; }; } // namespace Common diff --git a/src/common/sparse_large_vector.cpp b/src/common/sparse_large_vector.cpp index d63ee28331..14b97edf2b 100644 --- a/src/common/sparse_large_vector.cpp +++ b/src/common/sparse_large_vector.cpp @@ -19,7 +19,7 @@ namespace Common { #ifdef _WIN32 -static std::vector> vector_regions; +static std::vector> vector_regions {}; // Workaround for handling non-commited memory accessed by Dynarmic; usually result of an error static LONG WINAPI FakePageFaultHandler(PEXCEPTION_POINTERS info) { diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index c9551c01d1..b5f376abb2 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -172,7 +172,7 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { if (page_table) { constexpr size_t PageBits = 12; constexpr size_t NumPageTableEntries = 1 << (32 - PageBits); - constexpr size_t PageLog2Stride = 5; + constexpr size_t PageLog2Stride = 4; static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData)); // Dynarmic will not write to the page table, const_cast is safe here diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 1a27e8f381..4dde1242b1 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -211,7 +211,7 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s // Memory if (page_table) { - constexpr size_t PageLog2Stride = 5; + constexpr size_t PageLog2Stride = 4; static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData)); // Dynarmic will not write to the page table, const_cast is safe here diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 1e6c6b6bac..3ba4b39168 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -125,14 +125,14 @@ struct Memory::Impl { [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { Common::PhysicalAddress const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; if (paddr) - return system.DeviceMemory().GetPointer(paddr + vaddr); + return system.DeviceMemory().GetPointer((paddr << YUZU_PAGEBITS) + vaddr); return {}; } [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { const Common::PhysicalAddress paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; if (paddr != 0) - return system.DeviceMemory().GetPointer(paddr + vaddr); + return system.DeviceMemory().GetPointer((paddr << YUZU_PAGEBITS) + vaddr); return {}; } @@ -548,12 +548,11 @@ struct Memory::Impl { auto orig_base = base; while (base != end) { auto host_ptr = uintptr_t(system.DeviceMemory().GetPointer(target)) - (base << YUZU_PAGEBITS); - auto backing = GetInteger(target) - (base << YUZU_PAGEBITS); auto& entry = page_table.entries.GetAndFault(base); entry.ptr.Store(host_ptr, type); - entry.addr = backing; - entry.block = orig_base << YUZU_PAGEBITS; + entry.addr = static_cast((GetInteger(target) >> YUZU_PAGEBITS) - base); + entry.block = static_cast(orig_base); ASSERT_MSG(page_table.entries[base].ptr.Pointer(), "memory mapping base yield a nullptr within the table");