diff options
| author | Exverge <exverge@exverge.xyz> | 2026-09-09 21:35:49 +0200 |
|---|---|---|
| committer | crueter <crueter@eden-emu.dev> | 2026-09-09 21:35:49 +0200 |
| commit | 5f142c7926d0c7fcbbd0ce30794d72f638a43b2a (patch) | |
| tree | f77a2dd0c7acb9cdc5f28893c25bea0006932f03 /src/core/arm | |
| parent | c5f6f1ca5eaf16ff84aee7987c0c8d37a1d9d2b2 (diff) | |
[common/core/dynarmic] Optimize page table allocations (#4219)
Reduces the page entries from 32 bytes to 8 and rewrites `VirtualBuffer` to be more efficient in memory usage and specifically for large zero regions.
The page table will now only reserve 1GiB instead of 4GiB and of this memory it should only use at most ~8MiB.
This PR has the side effect of using Eden on Windows on low memory systems much more plausible since it would previously require ~10GiB of committable memory at front (despite using ~5-6 at most, inadvertently stalling other processes) where as now it should only require around the amount that it'll actually use.
Co-authored-by: Lizzie <lizzie@eden-emu.dev>
Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4219
Reviewed-by: Maufeat <sahyno1996@gmail.com>
Reviewed-by: lizzie <lizzie@eden-emu.dev>
Reviewed-by: CamilleLaVey <camillelavey99@gmail.com>
Diffstat (limited to 'src/core/arm')
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_32.cpp | 18 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic_64.cpp | 19 |
2 files changed, 26 insertions, 11 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 97284efa4c..80e2b2dca9 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -172,12 +172,12 @@ 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; - static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData)); - config.page_table = reinterpret_cast<std::array<std::uint8_t*, NumPageTableEntries>*>(page_table->entries.data()); - config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; - config.page_table_log2_stride = PageLog2Stride; + // Dynarmic will not write to the page table, const_cast is safe here + config.page_table = reinterpret_cast<std::array<std::uint8_t*, NumPageTableEntries>*>( + const_cast<Common::PageTable::PageEntryData*>(page_table->entries.data())); + config.page_table_pointer_mask = Common::PageTable::ATTRIBUTE_MASK; + config.page_table_marked_bit = 0; config.absolute_offset_page_table = true; config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; config.only_detect_misalignment_via_page_table_on_page_boundary = true; @@ -188,6 +188,13 @@ void ArmDynarmic32::MakeJit(Common::PageTable* page_table) { config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt; config.recompile_on_exclusive_fastmem_failure = true; + + if (reinterpret_cast<u64>(m_system.DeviceMemory().buffer.BackingBasePointer() + + Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize()) < (1ULL << 39)) { + // Systems like FreeBSD allocate memory really low by default, and since we pack our page table entries, + // we have to manually sign extend when our actual pointer is negative. + config.page_table_sign_extension = Common::PageTable::SIGN_BIT; + } } // Multi-process state @@ -420,6 +427,7 @@ void ArmDynarmic32::SignalInterrupt(Kernel::KThread* thread) { } void ArmDynarmic32::ClearInstructionCache() { + m_cb->last_code_addr = u64(-1); m_jit->ClearCache(); } diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 0b7f6874a7..9662bf1712 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -211,13 +211,12 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s // Memory if (page_table) { - constexpr size_t PageLog2Stride = 5; - static_assert(1 << PageLog2Stride == sizeof(Common::PageTable::PageEntryData)); - - config.page_table = reinterpret_cast<void**>(page_table->entries.data()); + // Dynarmic will not write to the page table, const_cast is safe here + config.page_table = reinterpret_cast<void**>( + const_cast<Common::PageTable::PageEntryData*>(page_table->entries.data())); config.page_table_address_space_bits = std::uint32_t(address_space_bits); - config.page_table_pointer_mask_bits = Common::PageTable::ATTRIBUTE_BITS; - config.page_table_log2_stride = PageLog2Stride; + config.page_table_pointer_mask = Common::PageTable::ATTRIBUTE_MASK; + config.page_table_marked_bit = 0; config.silently_mirror_page_table = false; config.absolute_offset_page_table = true; config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128; @@ -231,6 +230,13 @@ void ArmDynarmic64::MakeJit(Common::PageTable* page_table, std::size_t address_s config.fastmem_exclusive_access = config.fastmem_pointer != std::nullopt; config.recompile_on_exclusive_fastmem_failure = true; + + if (reinterpret_cast<u64>(m_system.DeviceMemory().buffer.BackingBasePointer() + + Kernel::Board::Nintendo::Nx::KSystemControl::Init::GetIntendedMemorySize()) < (1ULL << 39)) { + // Systems like FreeBSD allocate memory really low by default, and since we pack our page table entries, + // we have to manually sign extend when our actual pointer is negative. + config.page_table_sign_extension = Common::PageTable::SIGN_BIT; + } } // Multi-process state @@ -447,6 +453,7 @@ void ArmDynarmic64::SignalInterrupt(Kernel::KThread* thread) { } void ArmDynarmic64::ClearInstructionCache() { + m_cb->last_code_addr = u64(-1); m_jit->ClearCache(); } |
