From 01c01e30eeb527762dec331e767041055890afd7 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 26 Sep 2025 08:09:28 +0000 Subject: [PATCH 1/8] [core/memory] Remove defered heap allocation on Linux. Authored-by: weakboson Signed-off-by: lizzie --- src/common/heap_tracker.cpp | 82 ++++++++--------------- src/core/CMakeLists.txt | 1 - src/core/arm/dynarmic/arm_dynarmic.cpp | 49 -------------- src/core/arm/dynarmic/arm_dynarmic.h | 20 ------ src/core/arm/dynarmic/arm_dynarmic_32.cpp | 5 -- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 5 -- src/core/memory.cpp | 15 ----- src/core/memory.h | 2 - 8 files changed, 29 insertions(+), 150 deletions(-) delete mode 100644 src/core/arm/dynarmic/arm_dynarmic.cpp diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index a99d386d8a..48d1cdcddb 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -1,13 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include +#include + #include "common/heap_tracker.h" #include "common/logging/log.h" -#include "common/assert.h" namespace Common { @@ -36,6 +36,8 @@ HeapTracker::~HeapTracker() = default; void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap) { + bool rebuild_required = false; + // When mapping other memory, map pages immediately. if (!is_separate_heap) { m_buffer.Map(virtual_offset, host_offset, length, perm, false); @@ -57,11 +59,29 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, // Insert into mappings. m_map_count++; - m_mappings.insert(*map); + const auto it = m_mappings.insert(*map); + + // Update tick before possible rebuild. + it->tick = m_tick++; + + // Check if we need to rebuild. + if (m_resident_map_count >= m_max_resident_map_count) { + rebuild_required = true; + } + + // Map the area. + m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); + + // This map is now resident. + it->is_resident = true; + m_resident_map_count++; + m_resident_mappings.insert(*it); } - // Finally, map. - this->DeferredMapSeparateHeap(virtual_offset); + if (rebuild_required) { + // A rebuild was required, so perform it now. + this->RebuildSeparateHeapAddressSpace(); + } } void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) { @@ -147,7 +167,8 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p } // Clamp to end. - next = (std::min)(next, end); + next = std::min(next, end); + // Reprotect, if we need to. if (should_protect) { m_buffer.Protect(cur, next - cur, perm); @@ -158,51 +179,6 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p } } -bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) { - if (m_buffer.IsInVirtualRange(fault_address)) { - return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer()); - } - - return false; -} - -bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) { - bool rebuild_required = false; - - { - std::scoped_lock lk{m_lock}; - - // Check to ensure this was a non-resident separate heap mapping. - const auto it = this->GetNearestHeapMapLocked(virtual_offset); - if (it == m_mappings.end() || it->is_resident) { - return false; - } - - // Update tick before possible rebuild. - it->tick = m_tick++; - - // Check if we need to rebuild. - if (m_resident_map_count > m_max_resident_map_count) { - rebuild_required = true; - } - - // Map the area. - m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); - - // This map is now resident. - it->is_resident = true; - m_resident_map_count++; - m_resident_mappings.insert(*it); - } - - if (rebuild_required) { - // A rebuild was required, so perform it now. - this->RebuildSeparateHeapAddressSpace(); - } - - return true; -} - void HeapTracker::RebuildSeparateHeapAddressSpace() { std::scoped_lock lk{m_rebuild_lock, m_lock}; @@ -213,8 +189,8 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() { // Despite being worse in theory, this has proven to be better in practice than more // regularly dumping a smaller amount, because it significantly reduces average case // lock contention. - std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2; - std::size_t const evict_count = m_resident_map_count - desired_count; + const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; + const size_t evict_count = m_resident_map_count - desired_count; auto it = m_resident_mappings.begin(); for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 11c217fce6..eea49ca844 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1229,7 +1229,6 @@ endif() if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) target_sources(core PRIVATE - arm/dynarmic/arm_dynarmic.cpp arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp arm/dynarmic/arm_dynarmic_64.h diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp deleted file mode 100644 index e6e9fc45be..0000000000 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef __linux__ - -#include "common/signal_chain.h" - -#include "core/arm/dynarmic/arm_dynarmic.h" -#include "core/hle/kernel/k_process.h" -#include "core/memory.h" - -namespace Core { - -namespace { - -thread_local Core::Memory::Memory* g_current_memory{}; -std::once_flag g_registered{}; -struct sigaction g_old_segv {}; - -void HandleSigSegv(int sig, siginfo_t* info, void* ctx) { - if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) { - return; - } - - return g_old_segv.sa_sigaction(sig, info, ctx); -} - -} // namespace - -ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) { - g_current_memory = std::addressof(process->GetMemory()); -} - -ScopedJitExecution::~ScopedJitExecution() { - g_current_memory = nullptr; -} - -void ScopedJitExecution::RegisterHandler() { - std::call_once(g_registered, [] { - struct sigaction sa {}; - sa.sa_sigaction = &HandleSigSegv; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv)); - }); -} - -} // namespace Core - -#endif diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 53dd188151..eef7c31160 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -26,24 +26,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { return static_cast(hr); } -#ifdef __linux__ - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process); - ~ScopedJitExecution(); - static void RegisterHandler(); -}; - -#else - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process) {} - ~ScopedJitExecution() {} - static void RegisterHandler() {} -}; - -#endif - } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index d2035d0fe0..4e83e5243b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -343,15 +343,11 @@ bool ArmDynarmic32::IsInThumbMode() const { } HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -393,7 +389,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc m_cp15(std::make_shared(*this)), m_core_index{core_index} { auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl(); m_jit = MakeJit(&page_table_impl); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic32::~ArmDynarmic32() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 438b7b691c..2745aeb862 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -374,15 +374,11 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa } HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -422,7 +418,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc auto& page_table = process->GetPageTable().GetBasePageTable(); auto& page_table_impl = page_table.GetImpl(); m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth()); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic64::~ArmDynarmic64() = default; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2583aae867..4f1854a2e5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1230,22 +1230,7 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { if (rasterizer) { impl->InvalidateGPUMemory(ptr, size); } - -#ifdef __linux__ - if (!rasterizer && mapped) { - impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr)); - } -#endif - return mapped && ptr != nullptr; } -bool Memory::InvalidateSeparateHeap(void* fault_address) { -#ifdef __linux__ - return impl->buffer->DeferredMapSeparateHeap(static_cast(fault_address)); -#else - return false; -#endif -} - } // namespace Core::Memory diff --git a/src/core/memory.h b/src/core/memory.h index dcca26892b..c99bb37377 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -492,8 +492,6 @@ public: bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); - bool InvalidateSeparateHeap(void* fault_address); - private: Core::System& system; From ddb09e5486d8242531fd31d88f1320f60c5b120c Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 26 Sep 2025 08:11:15 +0000 Subject: [PATCH 2/8] fix Signed-off-by: lizzie --- src/core/arm/dynarmic/arm_dynarmic.h | 3 +++ src/core/memory.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index eef7c31160..0633a9eb5a 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/core/memory.h b/src/core/memory.h index c99bb37377..c23b41a111 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later From cc50571275cd09196ae60ade262d802a96fdd96b Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 27 Sep 2025 20:41:52 +0200 Subject: [PATCH 3/8] [dynarmic] fix tests builds (#2601) This fixes tests for dynarmic, print_info and test_generator. Signed-off-by: lizzie Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2601 Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: lizzie Co-committed-by: lizzie --- src/dynarmic/tests/A32/fuzz_arm.cpp | 5 ++-- src/dynarmic/tests/A32/fuzz_thumb.cpp | 1 + .../tests/A32/test_arm_instructions.cpp | 4 +++ src/dynarmic/tests/A32/test_coprocessor.cpp | 4 +++ src/dynarmic/tests/A32/test_svc.cpp | 4 +++ .../tests/A32/test_thumb_instructions.cpp | 1 + src/dynarmic/tests/A32/testenv.h | 1 - src/dynarmic/tests/A64/a64.cpp | 4 +++ src/dynarmic/tests/A64/fp_min_max.cpp | 1 + src/dynarmic/tests/A64/fuzz_with_unicorn.cpp | 1 + .../tests/A64/misaligned_page_table.cpp | 4 +++ src/dynarmic/tests/A64/real_world.cpp | 1 + src/dynarmic/tests/A64/test_invalidation.cpp | 4 +++ src/dynarmic/tests/A64/testenv.h | 1 - src/dynarmic/tests/decoder_tests.cpp | 26 ++++++----------- src/dynarmic/tests/native/preserve_xmm.cpp | 1 + src/dynarmic/tests/print_info.cpp | 29 +++++++++---------- 17 files changed, 56 insertions(+), 36 deletions(-) diff --git a/src/dynarmic/tests/A32/fuzz_arm.cpp b/src/dynarmic/tests/A32/fuzz_arm.cpp index 087ce54813..bef473a491 100644 --- a/src/dynarmic/tests/A32/fuzz_arm.cpp +++ b/src/dynarmic/tests/A32/fuzz_arm.cpp @@ -24,6 +24,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a32_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" @@ -46,7 +47,7 @@ using namespace Dynarmic; template bool AnyLocationDescriptorForTerminalHas(IR::Terminal terminal, Fn fn) { - return Common::VisitVariant(terminal, [&](auto t) -> bool { + return boost::apply_visitor([&](auto t) -> bool { using T = std::decay_t; if constexpr (std::is_same_v) { return false; @@ -72,7 +73,7 @@ bool AnyLocationDescriptorForTerminalHas(IR::Terminal terminal, Fn fn) { ASSERT_MSG(false, "Invalid terminal type"); return false; } - }); + }, terminal); } bool ShouldTestInst(u32 instruction, u32 pc, bool is_thumb, bool is_last_inst, A32::ITState it_state = {}) { diff --git a/src/dynarmic/tests/A32/fuzz_thumb.cpp b/src/dynarmic/tests/A32/fuzz_thumb.cpp index ad01e5718b..7f64cb0ccb 100644 --- a/src/dynarmic/tests/A32/fuzz_thumb.cpp +++ b/src/dynarmic/tests/A32/fuzz_thumb.cpp @@ -22,6 +22,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a32_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/FPSCR.h" #include "dynarmic/frontend/A32/PSR.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" diff --git a/src/dynarmic/tests/A32/test_arm_instructions.cpp b/src/dynarmic/tests/A32/test_arm_instructions.cpp index 0411877823..2e7e7dc5d8 100644 --- a/src/dynarmic/tests/A32/test_arm_instructions.cpp +++ b/src/dynarmic/tests/A32/test_arm_instructions.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2016 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" diff --git a/src/dynarmic/tests/A32/test_coprocessor.cpp b/src/dynarmic/tests/A32/test_coprocessor.cpp index 98da0e5d34..3888d2c68b 100644 --- a/src/dynarmic/tests/A32/test_coprocessor.cpp +++ b/src/dynarmic/tests/A32/test_coprocessor.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,6 +11,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/frontend/A32/a32_location_descriptor.h" #include "dynarmic/interface/A32/a32.h" #include "dynarmic/interface/A32/coprocessor.h" diff --git a/src/dynarmic/tests/A32/test_svc.cpp b/src/dynarmic/tests/A32/test_svc.cpp index 8b55d6537c..0be2432c7b 100644 --- a/src/dynarmic/tests/A32/test_svc.cpp +++ b/src/dynarmic/tests/A32/test_svc.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2022 MerryMage * SPDX-License-Identifier: 0BSD @@ -8,6 +11,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A32/test_thumb_instructions.cpp b/src/dynarmic/tests/A32/test_thumb_instructions.cpp index 3501d5419f..d509acdd8d 100644 --- a/src/dynarmic/tests/A32/test_thumb_instructions.cpp +++ b/src/dynarmic/tests/A32/test_thumb_instructions.cpp @@ -10,6 +10,7 @@ #include "dynarmic/common/common_types.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A32/a32.h" static Dynarmic::A32::UserConfig GetUserConfig(ThumbTestEnv* testenv) { diff --git a/src/dynarmic/tests/A32/testenv.h b/src/dynarmic/tests/A32/testenv.h index a6df2017ce..72eaafce14 100644 --- a/src/dynarmic/tests/A32/testenv.h +++ b/src/dynarmic/tests/A32/testenv.h @@ -17,7 +17,6 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" #include "dynarmic/interface/A32/a32.h" -#include "../native/testenv.h" template class A32TestEnv : public Dynarmic::A32::UserCallbacks { diff --git a/src/dynarmic/tests/A64/a64.cpp b/src/dynarmic/tests/A64/a64.cpp index 40eff1f071..bc51eca164 100644 --- a/src/dynarmic/tests/A64/a64.cpp +++ b/src/dynarmic/tests/A64/a64.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -7,6 +10,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/tests/A64/fp_min_max.cpp b/src/dynarmic/tests/A64/fp_min_max.cpp index d8b45db807..1669b63071 100644 --- a/src/dynarmic/tests/A64/fp_min_max.cpp +++ b/src/dynarmic/tests/A64/fp_min_max.cpp @@ -12,6 +12,7 @@ #include "dynarmic/common/common_types.h" #include "./testenv.h" +#include "../native/testenv.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp index 1c3531ebc5..2fb5a7b35e 100644 --- a/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp +++ b/src/dynarmic/tests/A64/fuzz_with_unicorn.cpp @@ -19,6 +19,7 @@ #include "../rand_int.h" #include "../unicorn_emu/a64_unicorn.h" #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpcr.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/common/llvm_disassemble.h" diff --git a/src/dynarmic/tests/A64/misaligned_page_table.cpp b/src/dynarmic/tests/A64/misaligned_page_table.cpp index 8235e14a67..fc0bc77428 100644 --- a/src/dynarmic/tests/A64/misaligned_page_table.cpp +++ b/src/dynarmic/tests/A64/misaligned_page_table.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" TEST_CASE("misaligned load/store do not use page_table when detect_misaligned_access_via_page_table is set", "[a64]") { diff --git a/src/dynarmic/tests/A64/real_world.cpp b/src/dynarmic/tests/A64/real_world.cpp index 07532d95af..a083f16d61 100644 --- a/src/dynarmic/tests/A64/real_world.cpp +++ b/src/dynarmic/tests/A64/real_world.cpp @@ -5,6 +5,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/test_invalidation.cpp b/src/dynarmic/tests/A64/test_invalidation.cpp index 168043c1cb..0c92f5f606 100644 --- a/src/dynarmic/tests/A64/test_invalidation.cpp +++ b/src/dynarmic/tests/A64/test_invalidation.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + /* This file is part of the dynarmic project. * Copyright (c) 2018 MerryMage * SPDX-License-Identifier: 0BSD @@ -6,6 +9,7 @@ #include #include "./testenv.h" +#include "../native/testenv.h" #include "dynarmic/interface/A64/a64.h" using namespace Dynarmic; diff --git a/src/dynarmic/tests/A64/testenv.h b/src/dynarmic/tests/A64/testenv.h index 31e338b138..fcdadb23e6 100644 --- a/src/dynarmic/tests/A64/testenv.h +++ b/src/dynarmic/tests/A64/testenv.h @@ -12,7 +12,6 @@ #include "dynarmic/common/assert.h" #include "dynarmic/common/common_types.h" #include "dynarmic/interface/A64/a64.h" -#include "../native/testenv.h" using Vector = Dynarmic::A64::Vector; diff --git a/src/dynarmic/tests/decoder_tests.cpp b/src/dynarmic/tests/decoder_tests.cpp index e545309960..cdd2c70cd9 100644 --- a/src/dynarmic/tests/decoder_tests.cpp +++ b/src/dynarmic/tests/decoder_tests.cpp @@ -36,22 +36,12 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { const auto is_decode_error = [&get_ir](const A32::ASIMDMatcher& matcher, u32 instruction) { const auto block = get_ir(matcher, instruction); - - for (const auto& ir_inst : block) { - if (ir_inst.GetOpcode() == IR::Opcode::A32ExceptionRaised) { - if (static_cast(ir_inst.GetArg(1).GetU64()) == A32::Exception::DecodeError) { - return true; - } - } - } - return false; + return std::find_if(block.cbegin(), block.cend(), [](auto const& e) { + return e.GetOpcode() == IR::Opcode::A32ExceptionRaised && A32::Exception(e.GetArg(1).GetU64()) == A32::Exception::DecodeError; + }) != block.cend(); }; for (auto iter = table.cbegin(); iter != table.cend(); ++iter) { - if (std::strncmp(iter->GetName(), "UNALLOCATED", 11) == 0) { - continue; - } - const u32 expect = iter->GetExpected(); const u32 mask = iter->GetMask(); u32 x = 0; @@ -59,15 +49,17 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { const u32 instruction = expect | x; const bool iserr = is_decode_error(*iter, instruction); - const auto alternative = std::find_if(table.cbegin(), iter, [instruction](const auto& m) { return m.Matches(instruction); }); + const auto alternative = std::find_if(table.cbegin(), iter, [instruction](const auto& m) { + return m.Matches(instruction); + }); const bool altiserr = is_decode_error(*alternative, instruction); INFO("Instruction: " << std::hex << std::setfill('0') << std::setw(8) << instruction); INFO("Expect: " << std::hex << std::setfill('0') << std::setw(8) << expect); INFO("Fill: " << std::hex << std::setfill('0') << std::setw(8) << x); - INFO("Name: " << iter->GetName()); + //INFO("Name: " << *A32::GetNameASIMD(instruction)); INFO("iserr: " << iserr); - INFO("alternative: " << alternative->GetName()); + //INFO("alternative: " << alternative->GetName()); INFO("altiserr: " << altiserr); REQUIRE(((!iserr && alternative == iter) || (iserr && alternative != iter && !altiserr))); @@ -75,4 +67,4 @@ TEST_CASE("ASIMD Decoder: Ensure table order correctness", "[decode][a32][.]") { x = ((x | mask) + 1) & ~mask; } while (x != 0); } -} +} \ No newline at end of file diff --git a/src/dynarmic/tests/native/preserve_xmm.cpp b/src/dynarmic/tests/native/preserve_xmm.cpp index 0f69697b7a..7421252063 100644 --- a/src/dynarmic/tests/native/preserve_xmm.cpp +++ b/src/dynarmic/tests/native/preserve_xmm.cpp @@ -6,6 +6,7 @@ #include #include "../A64/testenv.h" +#include "../native/testenv.h" #include "dynarmic/common/fp/fpsr.h" #include "dynarmic/interface/exclusive_monitor.h" diff --git a/src/dynarmic/tests/print_info.cpp b/src/dynarmic/tests/print_info.cpp index 4b6c951c03..3d1268f467 100644 --- a/src/dynarmic/tests/print_info.cpp +++ b/src/dynarmic/tests/print_info.cpp @@ -32,27 +32,26 @@ #include "dynarmic/frontend/A64/translate/a64_translate.h" #include "dynarmic/frontend/A64/translate/impl/impl.h" #include "dynarmic/interface/A32/a32.h" +#include "dynarmic/interface/A32/config.h" #include "dynarmic/interface/A32/disassembler.h" #include "dynarmic/ir/basic_block.h" #include "dynarmic/ir/opt_passes.h" using namespace Dynarmic; -const char* GetNameOfA32Instruction(u32 instruction) { - if (auto vfp_decoder = A32::DecodeVFP(instruction)) { - return vfp_decoder->get().GetName(); - } else if (auto asimd_decoder = A32::DecodeASIMD(instruction)) { - return asimd_decoder->get().GetName(); - } else if (auto decoder = A32::DecodeArm(instruction)) { - return decoder->get().GetName(); - } +std::string_view GetNameOfA32Instruction(u32 instruction) { + //if (auto const vfp_decoder = A32::DecodeVFP(instruction)) + // return *A32::GetNameVFP(instruction); + //else if (auto const asimd_decoder = A32::DecodeASIMD(instruction)) + // return *A32::GetNameASIMD(instruction); + //else if (auto const decoder = A32::DecodeArm(instruction)) + // return *A32::GetNameARM(instruction); return ""; } -const char* GetNameOfA64Instruction(u32 instruction) { - if (auto decoder = A64::Decode(instruction)) { - return decoder->get().GetName(); - } +std::string_view GetNameOfA64Instruction(u32 instruction) { + //if (auto const decoder = A64::Decode(instruction)) + // return *A64::GetName(instruction); return ""; } @@ -66,7 +65,7 @@ void PrintA32Instruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A32::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } @@ -81,7 +80,7 @@ void PrintA64Instruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A64::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } @@ -99,7 +98,7 @@ void PrintThumbInstruction(u32 instruction) { fmt::print("should_continue: {}\n\n", should_continue); fmt::print("IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); - Optimization::Optimize(ir_block, conf, {}); + Optimization::Optimize(ir_block, A32::UserConfig{}, {}); fmt::print("Optimized IR:\n"); fmt::print("{}\n", IR::DumpBlock(ir_block)); } From c77ad128b9b4d03f45826d5e5ef32c1328779276 Mon Sep 17 00:00:00 2001 From: crueter Date: Sat, 27 Sep 2025 22:40:08 +0200 Subject: [PATCH 4/8] [cmake] whole-program LTO, prefer lld on clang (#2581) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2581 --- CMakeLists.txt | 42 ++++++++++++++++++++++---------- src/android/app/build.gradle.kts | 4 +-- src/core/CMakeLists.txt | 4 --- src/video_core/CMakeLists.txt | 4 --- 4 files changed, 30 insertions(+), 24 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index 994bc184fa..ef3c0bef6e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -147,7 +147,11 @@ if (MSVC OR ANDROID) set(EXT_DEFAULT ON) endif() -CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" ${EXT_DEFAULT} "ENABLE_SDL2;NOT MSVC" OFF) +if (ENABLE_SDL2) + # TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system + CMAKE_DEPENDENT_OPTION(YUZU_USE_EXTERNAL_SDL2 "Compile external SDL2" OFF "NOT MSVC" OFF) + option(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}") +endif() cmake_dependent_option(ENABLE_LIBUSB "Enable the use of LibUSB" ON "NOT ANDROID" OFF) @@ -185,8 +189,6 @@ option(YUZU_USE_PRECOMPILED_HEADERS "Use precompiled headers" ${EXT_DEFAULT}) # TODO(crueter): CI this? option(YUZU_DOWNLOAD_ANDROID_VVL "Download validation layer binary for android" ON) -# TODO(crueter): Cleanup, each dep that has a bundled option should allow to choose between bundled, external, system -CMAKE_DEPENDENT_OPTION(YUZU_USE_BUNDLED_SDL2 "Download bundled SDL2 build" "${MSVC}" "ENABLE_SDL2" OFF) CMAKE_DEPENDENT_OPTION(YUZU_ROOM "Enable dedicated room functionality" ON "NOT ANDROID" OFF) @@ -197,6 +199,14 @@ CMAKE_DEPENDENT_OPTION(YUZU_CMD "Compile the eden-cli executable" ON "ENABLE_SDL CMAKE_DEPENDENT_OPTION(YUZU_CRASH_DUMPS "Compile crash dump (Minidump) support" OFF "WIN32 OR LINUX" OFF) option(YUZU_ENABLE_LTO "Enable link-time optimization" OFF) +if(YUZU_ENABLE_LTO) + include(CheckIPOSupported) + check_ipo_supported(RESULT COMPILER_SUPPORTS_LTO) + if(NOT COMPILER_SUPPORTS_LTO) + message(FATAL_ERROR "Your compiler does not support interprocedural optimization (IPO). Re-run CMake with -DYUZU_ENABLE_LTO=OFF.") + endif() + set(CMAKE_INTERPROCEDURAL_OPTIMIZATION ${COMPILER_SUPPORTS_LTO}) +endif() option(YUZU_DOWNLOAD_TIME_ZONE_DATA "Always download time zone binaries" ON) @@ -884,19 +894,25 @@ if (MSVC AND CXX_CLANG) link_libraries(llvm-mingw-runtime) endif() -if (YUZU_USE_FASTER_LD AND CMAKE_CXX_COMPILER_ID STREQUAL "GNU") - # We will assume that if the compiler is GCC, it will attempt to use ld.bfd by default. - # Try to pick a faster linker. +if (YUZU_USE_FASTER_LD) + # clang should always use lld find_program(LLD lld) - find_program(MOLD mold) - if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") - message(NOTICE "Selecting mold as linker") - add_link_options("-fuse-ld=mold") - elseif (LLD) - message(NOTICE "Selecting lld as linker") - add_link_options("-fuse-ld=lld") + if (LLD) + set(LINKER lld) endif() + + # GNU appears to work better with mold + # TODO: mold has been slow lately, see if better options exist (search for gold?) + if (CXX_GCC) + find_program(MOLD mold) + if (MOLD AND CMAKE_CXX_COMPILER_VERSION VERSION_GREATER_EQUAL "12.1") + set(LINKER mold) + endif() + endif() + + message(NOTICE "Selecting ${LINKER} as linker") + add_link_options("-fuse-ld=${LINKER}") endif() # Set runtime library to MD/MDd for all configurations diff --git a/src/android/app/build.gradle.kts b/src/android/app/build.gradle.kts index c76b5e7162..d3a05cf3e2 100644 --- a/src/android/app/build.gradle.kts +++ b/src/android/app/build.gradle.kts @@ -175,12 +175,10 @@ android { "-DYUZU_USE_CPM=ON", "-DCPMUTIL_FORCE_BUNDLED=ON", "-DYUZU_USE_BUNDLED_FFMPEG=ON", - "-DYUZU_ENABLE_LTO=ON", "-DCMAKE_EXPORT_COMPILE_COMMANDS=ON", "-DBUILD_TESTING=OFF", "-DYUZU_TESTS=OFF", - "-DDYNARMIC_TESTS=OFF", - "-DDYNARMIC_ENABLE_LTO=ON" + "-DDYNARMIC_TESTS=OFF" ) abiFilters("arm64-v8a") diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 11c217fce6..62dab070e3 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1274,8 +1274,4 @@ if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(core PRIVATE precompiled_headers.h) endif() -if (YUZU_ENABLE_LTO) - set_property(TARGET core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() - create_target_directory_groups(core) diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt index 642494016e..27c8ed9c1d 100644 --- a/src/video_core/CMakeLists.txt +++ b/src/video_core/CMakeLists.txt @@ -399,10 +399,6 @@ if (YUZU_USE_PRECOMPILED_HEADERS) target_precompile_headers(video_core PRIVATE precompiled_headers.h) endif() -if (YUZU_ENABLE_LTO) - set_property(TARGET video_core PROPERTY INTERPROCEDURAL_OPTIMIZATION TRUE) -endif() - if (ANDROID AND ARCHITECTURE_arm64) target_link_libraries(video_core PRIVATE adrenotools) endif() From 02016697d6c63a976cf551b8c9d2cf11fea2fe6d Mon Sep 17 00:00:00 2001 From: nyx Date: Sat, 27 Sep 2025 22:40:18 +0200 Subject: [PATCH 5/8] [cmake, macos] Suppress warnings for unused private members (#2583) Co-authored-by: crueter Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2583 Reviewed-by: Lizzie Reviewed-by: crueter Reviewed-by: MaranBr Co-authored-by: nyx Co-committed-by: nyx --- src/CMakeLists.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 184b049d06..88470c4c42 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -141,7 +141,7 @@ else() -Wno-missing-field-initializers ) - if (CXX_CLANG OR CXX_ICC) # Clang or AppleClang + if (CXX_CLANG OR CXX_ICC OR CXX_APPLE) # Clang, AppleClang, or Intel C++ if (NOT MSVC) add_compile_options( -Werror=shadow-uncaptured-local From c725641f13772aa7d5705227e8fbe2c5b85ebb6a Mon Sep 17 00:00:00 2001 From: MaranBr Date: Sun, 28 Sep 2025 07:29:19 +0200 Subject: [PATCH 6/8] [video_core] Fix fast buffers without performance loss (#2605) Fixes games that have some elements flickering on the screen, such as Kirby Star Allies and others, without impacting performance. Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/2605 Reviewed-by: CamilleLaVey Reviewed-by: Lizzie Co-authored-by: MaranBr Co-committed-by: MaranBr --- src/video_core/buffer_cache/buffer_cache.h | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index eb18a4bd66..6f6e0c23a8 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h @@ -785,18 +785,13 @@ void BufferCache

::BindHostGraphicsUniformBuffers(size_t stage) { } template -void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, - bool needs_bind) { +void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 binding_index, bool needs_bind) { + ++channel_state->uniform_cache_shots[0]; const Binding& binding = channel_state->uniform_buffers[stage][index]; const DAddr device_addr = binding.device_addr; const u32 size = (std::min)(binding.size, (*channel_state->uniform_buffer_sizes)[stage][index]); Buffer& buffer = slot_buffers[binding.buffer_id]; TouchBuffer(buffer, binding.buffer_id); - const bool sync_buffer = SynchronizeBuffer(buffer, device_addr, size); - if (sync_buffer) { - ++channel_state->uniform_cache_hits[0]; - } - ++channel_state->uniform_cache_shots[0]; const bool use_fast_buffer = binding.buffer_id != NULL_BUFFER_ID && size <= channel_state->uniform_buffer_skip_cache_size && !memory_tracker.IsRegionGpuModified(device_addr, size); @@ -827,7 +822,10 @@ void BufferCache

::BindHostGraphicsUniformBuffer(size_t stage, u32 index, u32 device_memory.ReadBlockUnsafe(device_addr, span.data(), size); return; } - + // Classic cached path + if (SynchronizeBuffer(buffer, device_addr, size)) { + ++channel_state->uniform_cache_hits[0]; + } // Skip binding if it's not needed and if the bound buffer is not the fast version // This exists to avoid instances where the fast buffer is bound and a GPU write happens needs_bind |= HasFastUniformBufferBound(stage, binding_index); From 94498e3a276cd12008ca68bd1ad82e26b674f761 Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 26 Sep 2025 08:09:28 +0000 Subject: [PATCH 7/8] [core/memory] Remove defered heap allocation on Linux. Authored-by: weakboson Signed-off-by: lizzie --- src/common/heap_tracker.cpp | 82 ++++++++--------------- src/core/CMakeLists.txt | 1 - src/core/arm/dynarmic/arm_dynarmic.cpp | 49 -------------- src/core/arm/dynarmic/arm_dynarmic.h | 20 ------ src/core/arm/dynarmic/arm_dynarmic_32.cpp | 5 -- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 5 -- src/core/memory.cpp | 15 ----- src/core/memory.h | 2 - 8 files changed, 29 insertions(+), 150 deletions(-) delete mode 100644 src/core/arm/dynarmic/arm_dynarmic.cpp diff --git a/src/common/heap_tracker.cpp b/src/common/heap_tracker.cpp index a99d386d8a..48d1cdcddb 100644 --- a/src/common/heap_tracker.cpp +++ b/src/common/heap_tracker.cpp @@ -1,13 +1,13 @@ // SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later - // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #include +#include + #include "common/heap_tracker.h" #include "common/logging/log.h" -#include "common/assert.h" namespace Common { @@ -36,6 +36,8 @@ HeapTracker::~HeapTracker() = default; void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, MemoryPermission perm, bool is_separate_heap) { + bool rebuild_required = false; + // When mapping other memory, map pages immediately. if (!is_separate_heap) { m_buffer.Map(virtual_offset, host_offset, length, perm, false); @@ -57,11 +59,29 @@ void HeapTracker::Map(size_t virtual_offset, size_t host_offset, size_t length, // Insert into mappings. m_map_count++; - m_mappings.insert(*map); + const auto it = m_mappings.insert(*map); + + // Update tick before possible rebuild. + it->tick = m_tick++; + + // Check if we need to rebuild. + if (m_resident_map_count >= m_max_resident_map_count) { + rebuild_required = true; + } + + // Map the area. + m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); + + // This map is now resident. + it->is_resident = true; + m_resident_map_count++; + m_resident_mappings.insert(*it); } - // Finally, map. - this->DeferredMapSeparateHeap(virtual_offset); + if (rebuild_required) { + // A rebuild was required, so perform it now. + this->RebuildSeparateHeapAddressSpace(); + } } void HeapTracker::Unmap(size_t virtual_offset, size_t size, bool is_separate_heap) { @@ -147,7 +167,8 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p } // Clamp to end. - next = (std::min)(next, end); + next = std::min(next, end); + // Reprotect, if we need to. if (should_protect) { m_buffer.Protect(cur, next - cur, perm); @@ -158,51 +179,6 @@ void HeapTracker::Protect(size_t virtual_offset, size_t size, MemoryPermission p } } -bool HeapTracker::DeferredMapSeparateHeap(u8* fault_address) { - if (m_buffer.IsInVirtualRange(fault_address)) { - return this->DeferredMapSeparateHeap(fault_address - m_buffer.VirtualBasePointer()); - } - - return false; -} - -bool HeapTracker::DeferredMapSeparateHeap(size_t virtual_offset) { - bool rebuild_required = false; - - { - std::scoped_lock lk{m_lock}; - - // Check to ensure this was a non-resident separate heap mapping. - const auto it = this->GetNearestHeapMapLocked(virtual_offset); - if (it == m_mappings.end() || it->is_resident) { - return false; - } - - // Update tick before possible rebuild. - it->tick = m_tick++; - - // Check if we need to rebuild. - if (m_resident_map_count > m_max_resident_map_count) { - rebuild_required = true; - } - - // Map the area. - m_buffer.Map(it->vaddr, it->paddr, it->size, it->perm, false); - - // This map is now resident. - it->is_resident = true; - m_resident_map_count++; - m_resident_mappings.insert(*it); - } - - if (rebuild_required) { - // A rebuild was required, so perform it now. - this->RebuildSeparateHeapAddressSpace(); - } - - return true; -} - void HeapTracker::RebuildSeparateHeapAddressSpace() { std::scoped_lock lk{m_rebuild_lock, m_lock}; @@ -213,8 +189,8 @@ void HeapTracker::RebuildSeparateHeapAddressSpace() { // Despite being worse in theory, this has proven to be better in practice than more // regularly dumping a smaller amount, because it significantly reduces average case // lock contention. - std::size_t const desired_count = (std::min)(m_resident_map_count, m_max_resident_map_count) / 2; - std::size_t const evict_count = m_resident_map_count - desired_count; + const size_t desired_count = std::min(m_resident_map_count, m_max_resident_map_count) / 2; + const size_t evict_count = m_resident_map_count - desired_count; auto it = m_resident_mappings.begin(); for (size_t i = 0; i < evict_count && it != m_resident_mappings.end(); i++) { diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 62dab070e3..37920d6d4e 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -1229,7 +1229,6 @@ endif() if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) target_sources(core PRIVATE - arm/dynarmic/arm_dynarmic.cpp arm/dynarmic/arm_dynarmic.h arm/dynarmic/arm_dynarmic_64.cpp arm/dynarmic/arm_dynarmic_64.h diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp deleted file mode 100644 index e6e9fc45be..0000000000 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ /dev/null @@ -1,49 +0,0 @@ -// SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#ifdef __linux__ - -#include "common/signal_chain.h" - -#include "core/arm/dynarmic/arm_dynarmic.h" -#include "core/hle/kernel/k_process.h" -#include "core/memory.h" - -namespace Core { - -namespace { - -thread_local Core::Memory::Memory* g_current_memory{}; -std::once_flag g_registered{}; -struct sigaction g_old_segv {}; - -void HandleSigSegv(int sig, siginfo_t* info, void* ctx) { - if (g_current_memory && g_current_memory->InvalidateSeparateHeap(info->si_addr)) { - return; - } - - return g_old_segv.sa_sigaction(sig, info, ctx); -} - -} // namespace - -ScopedJitExecution::ScopedJitExecution(Kernel::KProcess* process) { - g_current_memory = std::addressof(process->GetMemory()); -} - -ScopedJitExecution::~ScopedJitExecution() { - g_current_memory = nullptr; -} - -void ScopedJitExecution::RegisterHandler() { - std::call_once(g_registered, [] { - struct sigaction sa {}; - sa.sa_sigaction = &HandleSigSegv; - sa.sa_flags = SA_SIGINFO | SA_ONSTACK; - Common::SigAction(SIGSEGV, std::addressof(sa), std::addressof(g_old_segv)); - }); -} - -} // namespace Core - -#endif diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index 53dd188151..eef7c31160 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -26,24 +26,4 @@ constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { return static_cast(hr); } -#ifdef __linux__ - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process); - ~ScopedJitExecution(); - static void RegisterHandler(); -}; - -#else - -class ScopedJitExecution { -public: - explicit ScopedJitExecution(Kernel::KProcess* process) {} - ~ScopedJitExecution() {} - static void RegisterHandler() {} -}; - -#endif - } // namespace Core diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index d2035d0fe0..4e83e5243b 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -343,15 +343,11 @@ bool ArmDynarmic32::IsInThumbMode() const { } HaltReason ArmDynarmic32::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic32::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -393,7 +389,6 @@ ArmDynarmic32::ArmDynarmic32(System& system, bool uses_wall_clock, Kernel::KProc m_cp15(std::make_shared(*this)), m_core_index{core_index} { auto& page_table_impl = process->GetPageTable().GetBasePageTable().GetImpl(); m_jit = MakeJit(&page_table_impl); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic32::~ArmDynarmic32() = default; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 438b7b691c..2745aeb862 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -374,15 +374,11 @@ std::shared_ptr ArmDynarmic64::MakeJit(Common::PageTable* pa } HaltReason ArmDynarmic64::RunThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Run()); } HaltReason ArmDynarmic64::StepThread(Kernel::KThread* thread) { - ScopedJitExecution sj(thread->GetOwnerProcess()); - m_jit->ClearExclusiveState(); return TranslateHaltReason(m_jit->Step()); } @@ -422,7 +418,6 @@ ArmDynarmic64::ArmDynarmic64(System& system, bool uses_wall_clock, Kernel::KProc auto& page_table = process->GetPageTable().GetBasePageTable(); auto& page_table_impl = page_table.GetImpl(); m_jit = MakeJit(&page_table_impl, page_table.GetAddressSpaceWidth()); - ScopedJitExecution::RegisterHandler(); } ArmDynarmic64::~ArmDynarmic64() = default; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 2583aae867..4f1854a2e5 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -1230,22 +1230,7 @@ bool Memory::InvalidateNCE(Common::ProcessAddress vaddr, size_t size) { if (rasterizer) { impl->InvalidateGPUMemory(ptr, size); } - -#ifdef __linux__ - if (!rasterizer && mapped) { - impl->buffer->DeferredMapSeparateHeap(GetInteger(vaddr)); - } -#endif - return mapped && ptr != nullptr; } -bool Memory::InvalidateSeparateHeap(void* fault_address) { -#ifdef __linux__ - return impl->buffer->DeferredMapSeparateHeap(static_cast(fault_address)); -#else - return false; -#endif -} - } // namespace Core::Memory diff --git a/src/core/memory.h b/src/core/memory.h index dcca26892b..c99bb37377 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -492,8 +492,6 @@ public: bool InvalidateNCE(Common::ProcessAddress vaddr, size_t size); - bool InvalidateSeparateHeap(void* fault_address); - private: Core::System& system; From b17b696f51c8e0863dc0192d5eb4e6c96d67e23c Mon Sep 17 00:00:00 2001 From: lizzie Date: Fri, 26 Sep 2025 08:11:15 +0000 Subject: [PATCH 8/8] fix Signed-off-by: lizzie --- src/core/arm/dynarmic/arm_dynarmic.h | 3 +++ src/core/memory.h | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h index eef7c31160..0633a9eb5a 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.h +++ b/src/core/arm/dynarmic/arm_dynarmic.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later diff --git a/src/core/memory.h b/src/core/memory.h index c99bb37377..c23b41a111 100644 --- a/src/core/memory.h +++ b/src/core/memory.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: 2014 Citra Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later