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-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

11
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<PageEntryData> 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

2
src/common/sparse_large_vector.cpp

@ -19,7 +19,7 @@
namespace Common {
#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
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) {
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

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
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

9
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<u8>(paddr + vaddr);
return system.DeviceMemory().GetPointer<u8>((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<u8>(paddr + vaddr);
return system.DeviceMemory().GetPointer<u8>((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<u8>(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<u32>((GetInteger(target) >> YUZU_PAGEBITS) - base);
entry.block = static_cast<u32>(orig_base);
ASSERT_MSG(page_table.entries[base].ptr.Pointer(),
"memory mapping base yield a nullptr within the table");

Loading…
Cancel
Save