Browse Source

[page_table] Optimize page table entry

pull/4219/head
Exverge 2 weeks ago
parent
commit
66aff82f37
No known key found for this signature in database GPG Key ID: DAD399BCC5FB77E4
  1. 24
      src/common/page_table.cpp
  2. 11
      src/common/page_table.h
  3. 2
      src/common/sparse_large_vector.cpp
  4. 2
      src/core/arm/dynarmic/arm_dynarmic_32.cpp
  5. 2
      src/core/arm/dynarmic/arm_dynarmic_64.cpp
  6. 9
      src/core/memory.cpp

24
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-License-Identifier: GPL-3.0-or-later
// SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2019 yuzu Emulator Project
@ -16,7 +16,7 @@ PageTable::~PageTable() noexcept = default;
bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context, bool PageTable::BeginTraversal(TraversalEntry* out_entry, TraversalContext* out_context,
Common::ProcessAddress address) const { Common::ProcessAddress address) const {
out_context->next_offset = GetInteger(address); 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); 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 { bool PageTable::ContinueTraversal(TraversalEntry* out_entry, TraversalContext* context) const {
// Setup invalid defaults. // Setup invalid defaults.
out_entry->phys_addr = 0; 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. // Validate that we can read the actual entry.
if (auto const page = context->next_page; page < entries.size()) { if (auto const page = context->next_page; page < entries.size()) {
// Validate that the entry is mapped. // Validate that the entry is mapped.
if (auto const paddr = entries[page].addr; paddr != 0) { 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; return true;
} }
} }
context->next_page += 1;
context->next_offset += page_size;
// Otherwise return false
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); entries.ResizeAndClear(num_page_table_entries);
current_address_space_width_in_bits = address_space_width_in_bits; 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 } // namespace Common

11
src/common/page_table.h

@ -127,7 +127,7 @@ struct PageTable {
return false; 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; return true;
} }
@ -135,16 +135,15 @@ struct PageTable {
/// corresponding attribute element is of type `Memory`. /// corresponding attribute element is of type `Memory`.
struct PageEntryData { struct PageEntryData {
PageInfo ptr; PageInfo ptr;
u64 block;
u64 addr;
u64 padding;
u32 block;
u32 addr;
}; };
SparseLargeVector<PageEntryData> entries; SparseLargeVector<PageEntryData> entries;
static_assert(sizeof(PageEntryData) == 32);
static_assert(sizeof(PageEntryData) == 16);
u8* fastmem_arena{}; u8* fastmem_arena{};
std::size_t current_address_space_width_in_bits{}; std::size_t current_address_space_width_in_bits{};
std::size_t page_size{};
std::size_t current_page_bits{};
}; };
} // namespace Common } // namespace Common

2
src/common/sparse_large_vector.cpp

@ -19,7 +19,7 @@
namespace Common { namespace Common {
#ifdef _WIN32 #ifdef _WIN32
static std::vector<std::pair<u64, u64>> vector_regions;
static std::vector<std::pair<u64, u64>> vector_regions {};
// Workaround for handling non-commited memory accessed by Dynarmic; usually result of an error // Workaround for handling non-commited memory accessed by Dynarmic; usually result of an error
static LONG WINAPI FakePageFaultHandler(PEXCEPTION_POINTERS info) { static LONG WINAPI FakePageFaultHandler(PEXCEPTION_POINTERS info) {

2
src/core/arm/dynarmic/arm_dynarmic_32.cpp

@ -172,7 +172,7 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) {
if (page_table) { if (page_table) {
constexpr size_t PageBits = 12; constexpr size_t PageBits = 12;
constexpr size_t NumPageTableEntries = 1 << (32 - PageBits); 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)); static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData));
// Dynarmic will not write to the page table, const_cast is safe here // Dynarmic will not write to the page table, const_cast is safe here

2
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 // Memory
if (page_table) { if (page_table) {
constexpr size_t PageLog2Stride = 5;
constexpr size_t PageLog2Stride = 4;
static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData)); static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData));
// Dynarmic will not write to the page table, const_cast is safe here // Dynarmic will not write to the page table, const_cast is safe here

9
src/core/memory.cpp

@ -125,14 +125,14 @@ struct Memory::Impl {
[[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const { [[nodiscard]] u8* GetPointerFromRasterizerCachedMemory(u64 vaddr) const {
Common::PhysicalAddress const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; Common::PhysicalAddress const paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr;
if (paddr) if (paddr)
return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
return system.DeviceMemory().GetPointer<u8>((paddr << YUZU_PAGEBITS) + vaddr);
return {}; return {};
} }
[[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const { [[nodiscard]] u8* GetPointerFromDebugMemory(u64 vaddr) const {
const Common::PhysicalAddress paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr; const Common::PhysicalAddress paddr = current_page_table->entries[vaddr >> YUZU_PAGEBITS].addr;
if (paddr != 0) if (paddr != 0)
return system.DeviceMemory().GetPointer<u8>(paddr + vaddr);
return system.DeviceMemory().GetPointer<u8>((paddr << YUZU_PAGEBITS) + vaddr);
return {}; return {};
} }
@ -548,12 +548,11 @@ struct Memory::Impl {
auto orig_base = base; auto orig_base = base;
while (base != end) { while (base != end) {
auto host_ptr = uintptr_t(system.DeviceMemory().GetPointer<u8>(target)) - (base << YUZU_PAGEBITS); auto host_ptr = uintptr_t(system.DeviceMemory().GetPointer<u8>(target)) - (base << YUZU_PAGEBITS);
auto backing = GetInteger(target) - (base << YUZU_PAGEBITS);
auto& entry = page_table.entries.GetAndFault(base); auto& entry = page_table.entries.GetAndFault(base);
entry.ptr.Store(host_ptr, type); entry.ptr.Store(host_ptr, type);
entry.addr = backing;
entry.block = orig_base << YUZU_PAGEBITS;
entry.addr = static_cast<u32>((GetInteger(target) >> YUZU_PAGEBITS) - base);
entry.block = static_cast<u32>(orig_base);
ASSERT_MSG(page_table.entries[base].ptr.Pointer(), ASSERT_MSG(page_table.entries[base].ptr.Pointer(),
"memory mapping base yield a nullptr within the table"); "memory mapping base yield a nullptr within the table");

Loading…
Cancel
Save