aboutsummaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
authorExverge <exverge@exverge.xyz>2026-09-09 21:35:49 +0200
committercrueter <crueter@eden-emu.dev>2026-09-09 21:35:49 +0200
commit5f142c7926d0c7fcbbd0ce30794d72f638a43b2a (patch)
treef77a2dd0c7acb9cdc5f28893c25bea0006932f03 /src/core/arm
parentc5f6f1ca5eaf16ff84aee7987c0c8d37a1d9d2b2 (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.cpp18
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp19
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();
}