core: decouple ARM interface from Dynarmic
This commit is contained in:
		| @@ -4,8 +4,6 @@ | ||||
| add_library(core STATIC | ||||
|     arm/arm_interface.h | ||||
|     arm/arm_interface.cpp | ||||
|     arm/dynarmic/arm_exclusive_monitor.cpp | ||||
|     arm/dynarmic/arm_exclusive_monitor.h | ||||
|     arm/exclusive_monitor.cpp | ||||
|     arm/exclusive_monitor.h | ||||
|     arm/symbols.cpp | ||||
| @@ -849,12 +847,15 @@ endif() | ||||
|  | ||||
| if (ARCHITECTURE_x86_64 OR ARCHITECTURE_arm64) | ||||
|     target_sources(core PRIVATE | ||||
|         arm/dynarmic/arm_dynarmic.h | ||||
|         arm/dynarmic/arm_dynarmic_64.cpp | ||||
|         arm/dynarmic/arm_dynarmic_64.h | ||||
|         arm/dynarmic/arm_dynarmic_32.cpp | ||||
|         arm/dynarmic/arm_dynarmic_32.h | ||||
|         arm/dynarmic/arm_dynarmic_cp15.cpp | ||||
|         arm/dynarmic/arm_dynarmic_cp15.h | ||||
|         arm/dynarmic/dynarmic_cp15.cpp | ||||
|         arm/dynarmic/dynarmic_cp15.h | ||||
|         arm/dynarmic/dynarmic_exclusive_monitor.cpp | ||||
|         arm/dynarmic/dynarmic_exclusive_monitor.h | ||||
|         hle/service/jit/jit_context.cpp | ||||
|         hle/service/jit/jit_context.h | ||||
|         hle/service/jit/jit.cpp | ||||
|   | ||||
| @@ -13,25 +13,68 @@ | ||||
| #include "core/core.h" | ||||
| #include "core/debugger/debugger.h" | ||||
| #include "core/hle/kernel/k_process.h" | ||||
| #include "core/hle/kernel/k_thread.h" | ||||
| #include "core/hle/kernel/svc.h" | ||||
| #include "core/loader/loader.h" | ||||
| #include "core/memory.h" | ||||
|  | ||||
| #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_64.h" | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| constexpr u64 SEGMENT_BASE = 0x7100000000ull; | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext( | ||||
|     Core::System& system, const ARM_Interface::ThreadContext32& ctx) { | ||||
|     return ARM_Dynarmic_32::GetBacktraceFromContext(system, ctx); | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = system.ApplicationMemory(); | ||||
|  | ||||
|     const auto& reg = ctx.cpu_registers; | ||||
|     u32 pc = reg[15], lr = reg[14], fp = reg[11]; | ||||
|     out.push_back({"", 0, pc, 0, ""}); | ||||
|  | ||||
|     // fp (= r11) points to the last frame record. | ||||
|     // Frame records are two words long: | ||||
|     // fp+0 : pointer to previous frame record | ||||
|     // fp+4 : value of lr for frame | ||||
|     for (size_t i = 0; i < 256; i++) { | ||||
|         out.push_back({"", 0, lr, 0, ""}); | ||||
|         if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { | ||||
|             break; | ||||
|         } | ||||
|         lr = memory.Read32(fp + 4); | ||||
|         fp = memory.Read32(fp); | ||||
|     } | ||||
|  | ||||
|     SymbolicateBacktrace(system, out); | ||||
|  | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktraceFromContext( | ||||
|     Core::System& system, const ARM_Interface::ThreadContext64& ctx) { | ||||
|     return ARM_Dynarmic_64::GetBacktraceFromContext(system, ctx); | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = system.ApplicationMemory(); | ||||
|  | ||||
|     const auto& reg = ctx.cpu_registers; | ||||
|     u64 pc = ctx.pc, lr = reg[30], fp = reg[29]; | ||||
|  | ||||
|     out.push_back({"", 0, pc, 0, ""}); | ||||
|  | ||||
|     // fp (= x29) points to the previous frame record. | ||||
|     // Frame records are two words long: | ||||
|     // fp+0 : pointer to previous frame record | ||||
|     // fp+8 : value of lr for frame | ||||
|     for (size_t i = 0; i < 256; i++) { | ||||
|         out.push_back({"", 0, lr, 0, ""}); | ||||
|         if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { | ||||
|             break; | ||||
|         } | ||||
|         lr = memory.Read64(fp + 8); | ||||
|         fp = memory.Read64(fp); | ||||
|     } | ||||
|  | ||||
|     SymbolicateBacktrace(system, out); | ||||
|  | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<BacktraceEntry>& out) { | ||||
| @@ -76,6 +119,18 @@ void ARM_Interface::SymbolicateBacktrace(Core::System& system, std::vector<Backt | ||||
|     } | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Interface::GetBacktrace() const { | ||||
|     if (GetArchitecture() == Architecture::Aarch64) { | ||||
|         ThreadContext64 ctx; | ||||
|         SaveContext(ctx); | ||||
|         return GetBacktraceFromContext(system, ctx); | ||||
|     } else { | ||||
|         ThreadContext32 ctx; | ||||
|         SaveContext(ctx); | ||||
|         return GetBacktraceFromContext(system, ctx); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void ARM_Interface::LogBacktrace() const { | ||||
|     const VAddr sp = GetSP(); | ||||
|     const VAddr pc = GetPC(); | ||||
| @@ -83,7 +138,6 @@ void ARM_Interface::LogBacktrace() const { | ||||
|     LOG_ERROR(Core_ARM, "{:20}{:20}{:20}{:20}{}", "Module Name", "Address", "Original Address", | ||||
|               "Offset", "Symbol"); | ||||
|     LOG_ERROR(Core_ARM, ""); | ||||
|  | ||||
|     const auto backtrace = GetBacktrace(); | ||||
|     for (const auto& entry : backtrace) { | ||||
|         LOG_ERROR(Core_ARM, "{:20}{:016X}    {:016X}    {:016X}    {}", entry.module, entry.address, | ||||
| @@ -97,7 +151,7 @@ void ARM_Interface::Run() { | ||||
|  | ||||
|     while (true) { | ||||
|         Kernel::KThread* current_thread{Kernel::GetCurrentThreadPointer(system.Kernel())}; | ||||
|         Dynarmic::HaltReason hr{}; | ||||
|         HaltReason hr{}; | ||||
|  | ||||
|         // Notify the debugger and go to sleep if a step was performed | ||||
|         // and this thread has been scheduled again. | ||||
| @@ -108,17 +162,17 @@ void ARM_Interface::Run() { | ||||
|         } | ||||
|  | ||||
|         // Otherwise, run the thread. | ||||
|         system.EnterDynarmicProfile(); | ||||
|         system.EnterCPUProfile(); | ||||
|         if (current_thread->GetStepState() == StepState::StepPending) { | ||||
|             hr = StepJit(); | ||||
|  | ||||
|             if (Has(hr, step_thread)) { | ||||
|             if (True(hr & HaltReason::StepThread)) { | ||||
|                 current_thread->SetStepState(StepState::StepPerformed); | ||||
|             } | ||||
|         } else { | ||||
|             hr = RunJit(); | ||||
|         } | ||||
|         system.ExitDynarmicProfile(); | ||||
|         system.ExitCPUProfile(); | ||||
|  | ||||
|         // If the thread is scheduled for termination, exit the thread. | ||||
|         if (current_thread->HasDpc()) { | ||||
| @@ -130,8 +184,8 @@ void ARM_Interface::Run() { | ||||
|  | ||||
|         // Notify the debugger and go to sleep if a breakpoint was hit, | ||||
|         // or if the thread is unable to continue for any reason. | ||||
|         if (Has(hr, breakpoint) || Has(hr, no_execute)) { | ||||
|             if (!Has(hr, no_execute)) { | ||||
|         if (True(hr & HaltReason::InstructionBreakpoint) || True(hr & HaltReason::PrefetchAbort)) { | ||||
|             if (!True(hr & HaltReason::InstructionBreakpoint)) { | ||||
|                 RewindBreakpointInstruction(); | ||||
|             } | ||||
|             if (system.DebuggerEnabled()) { | ||||
| @@ -144,7 +198,7 @@ void ARM_Interface::Run() { | ||||
|         } | ||||
|  | ||||
|         // Notify the debugger and go to sleep if a watchpoint was hit. | ||||
|         if (Has(hr, watchpoint)) { | ||||
|         if (True(hr & HaltReason::DataAbort)) { | ||||
|             if (system.DebuggerEnabled()) { | ||||
|                 system.GetDebugger().NotifyThreadWatchpoint(current_thread, *HaltedWatchpoint()); | ||||
|             } | ||||
| @@ -153,11 +207,11 @@ void ARM_Interface::Run() { | ||||
|         } | ||||
|  | ||||
|         // Handle syscalls and scheduling (this may change the current thread/core) | ||||
|         if (Has(hr, svc_call)) { | ||||
|         if (True(hr & HaltReason::SupervisorCall)) { | ||||
|             Kernel::Svc::Call(system, GetSvcNumber()); | ||||
|             break; | ||||
|         } | ||||
|         if (Has(hr, break_loop) || !uses_wall_clock) { | ||||
|         if (True(hr & HaltReason::BreakLoop) || !uses_wall_clock) { | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -8,8 +8,6 @@ | ||||
| #include <string> | ||||
| #include <vector> | ||||
|  | ||||
| #include <dynarmic/interface/halt_reason.h> | ||||
|  | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_types.h" | ||||
| #include "core/hardware_properties.h" | ||||
| @@ -30,6 +28,22 @@ class CPUInterruptHandler; | ||||
|  | ||||
| using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; | ||||
|  | ||||
| // NOTE: these values match the HaltReason enum in Dynarmic | ||||
| enum class HaltReason : u64 { | ||||
|     StepThread = 0x00000001, | ||||
|     DataAbort = 0x00000004, | ||||
|     BreakLoop = 0x02000000, | ||||
|     SupervisorCall = 0x04000000, | ||||
|     InstructionBreakpoint = 0x08000000, | ||||
|     PrefetchAbort = 0x20000000, | ||||
| }; | ||||
| DECLARE_ENUM_FLAG_OPERATORS(HaltReason); | ||||
|  | ||||
| enum class Architecture { | ||||
|     Aarch32, | ||||
|     Aarch64, | ||||
| }; | ||||
|  | ||||
| /// Generic ARMv8 CPU interface | ||||
| class ARM_Interface { | ||||
| public: | ||||
| @@ -167,8 +181,9 @@ public: | ||||
|      */ | ||||
|     virtual void SetTPIDR_EL0(u64 value) = 0; | ||||
|  | ||||
|     virtual void SaveContext(ThreadContext32& ctx) = 0; | ||||
|     virtual void SaveContext(ThreadContext64& ctx) = 0; | ||||
|     virtual Architecture GetArchitecture() const = 0; | ||||
|     virtual void SaveContext(ThreadContext32& ctx) const = 0; | ||||
|     virtual void SaveContext(ThreadContext64& ctx) const = 0; | ||||
|     virtual void LoadContext(const ThreadContext32& ctx) = 0; | ||||
|     virtual void LoadContext(const ThreadContext64& ctx) = 0; | ||||
|     void LoadWatchpointArray(const WatchpointArray& wp); | ||||
| @@ -195,17 +210,9 @@ public: | ||||
|     static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system, | ||||
|                                                                const ThreadContext64& ctx); | ||||
|  | ||||
|     virtual std::vector<BacktraceEntry> GetBacktrace() const = 0; | ||||
|  | ||||
|     std::vector<BacktraceEntry> GetBacktrace() const; | ||||
|     void LogBacktrace() const; | ||||
|  | ||||
|     static constexpr Dynarmic::HaltReason step_thread = Dynarmic::HaltReason::Step; | ||||
|     static constexpr Dynarmic::HaltReason break_loop = Dynarmic::HaltReason::UserDefined2; | ||||
|     static constexpr Dynarmic::HaltReason svc_call = Dynarmic::HaltReason::UserDefined3; | ||||
|     static constexpr Dynarmic::HaltReason breakpoint = Dynarmic::HaltReason::UserDefined4; | ||||
|     static constexpr Dynarmic::HaltReason watchpoint = Dynarmic::HaltReason::MemoryAbort; | ||||
|     static constexpr Dynarmic::HaltReason no_execute = Dynarmic::HaltReason::UserDefined6; | ||||
|  | ||||
| protected: | ||||
|     /// System context that this ARM interface is running under. | ||||
|     System& system; | ||||
| @@ -216,8 +223,8 @@ protected: | ||||
|     const Kernel::DebugWatchpoint* MatchingWatchpoint( | ||||
|         u64 addr, u64 size, Kernel::DebugWatchpointType access_type) const; | ||||
|  | ||||
|     virtual Dynarmic::HaltReason RunJit() = 0; | ||||
|     virtual Dynarmic::HaltReason StepJit() = 0; | ||||
|     virtual HaltReason RunJit() = 0; | ||||
|     virtual HaltReason StepJit() = 0; | ||||
|     virtual u32 GetSvcNumber() const = 0; | ||||
|     virtual const Kernel::DebugWatchpoint* HaltedWatchpoint() const = 0; | ||||
|     virtual void RewindBreakpointInstruction() = 0; | ||||
|   | ||||
							
								
								
									
										29
									
								
								src/core/arm/dynarmic/arm_dynarmic.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/core/arm/dynarmic/arm_dynarmic.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include <dynarmic/interface/halt_reason.h> | ||||
|  | ||||
| #include "core/arm/arm_interface.h" | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| constexpr Dynarmic::HaltReason StepThread = Dynarmic::HaltReason::Step; | ||||
| constexpr Dynarmic::HaltReason DataAbort = Dynarmic::HaltReason::MemoryAbort; | ||||
| constexpr Dynarmic::HaltReason BreakLoop = Dynarmic::HaltReason::UserDefined2; | ||||
| constexpr Dynarmic::HaltReason SupervisorCall = Dynarmic::HaltReason::UserDefined3; | ||||
| constexpr Dynarmic::HaltReason InstructionBreakpoint = Dynarmic::HaltReason::UserDefined4; | ||||
| constexpr Dynarmic::HaltReason PrefetchAbort = Dynarmic::HaltReason::UserDefined6; | ||||
|  | ||||
| constexpr HaltReason TranslateHaltReason(Dynarmic::HaltReason hr) { | ||||
|     static_assert(static_cast<u64>(HaltReason::StepThread) == static_cast<u64>(StepThread)); | ||||
|     static_assert(static_cast<u64>(HaltReason::DataAbort) == static_cast<u64>(DataAbort)); | ||||
|     static_assert(static_cast<u64>(HaltReason::BreakLoop) == static_cast<u64>(BreakLoop)); | ||||
|     static_assert(static_cast<u64>(HaltReason::SupervisorCall) == static_cast<u64>(SupervisorCall)); | ||||
|     static_assert(static_cast<u64>(HaltReason::InstructionBreakpoint) == | ||||
|                   static_cast<u64>(InstructionBreakpoint)); | ||||
|     static_assert(static_cast<u64>(HaltReason::PrefetchAbort) == static_cast<u64>(PrefetchAbort)); | ||||
|  | ||||
|     return static_cast<HaltReason>(hr); | ||||
| } | ||||
|  | ||||
| } // namespace Core | ||||
| @@ -10,9 +10,10 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "common/page_table.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/arm/dynarmic/dynarmic_cp15.h" | ||||
| #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/debugger/debugger.h" | ||||
| @@ -104,11 +105,11 @@ public: | ||||
|         switch (exception) { | ||||
|         case Dynarmic::A32::Exception::NoExecuteFault: | ||||
|             LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#08x}", pc); | ||||
|             ReturnException(pc, ARM_Interface::no_execute); | ||||
|             ReturnException(pc, PrefetchAbort); | ||||
|             return; | ||||
|         default: | ||||
|             if (debugger_enabled) { | ||||
|                 ReturnException(pc, ARM_Interface::breakpoint); | ||||
|                 ReturnException(pc, InstructionBreakpoint); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -121,7 +122,7 @@ public: | ||||
|  | ||||
|     void CallSVC(u32 swi) override { | ||||
|         parent.svc_swi = swi; | ||||
|         parent.jit.load()->HaltExecution(ARM_Interface::svc_call); | ||||
|         parent.jit.load()->HaltExecution(SupervisorCall); | ||||
|     } | ||||
|  | ||||
|     void AddTicks(u64 ticks) override { | ||||
| @@ -162,7 +163,7 @@ public: | ||||
|         if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||||
|             LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||||
|                          addr); | ||||
|             parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||||
|             parent.jit.load()->HaltExecution(PrefetchAbort); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| @@ -173,7 +174,7 @@ public: | ||||
|         const auto match{parent.MatchingWatchpoint(addr, size, type)}; | ||||
|         if (match) { | ||||
|             parent.halted_watchpoint = match; | ||||
|             parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); | ||||
|             parent.jit.load()->HaltExecution(DataAbort); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| @@ -329,12 +330,12 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | ||||
|     return std::make_unique<Dynarmic::A32::Jit>(config); | ||||
| } | ||||
|  | ||||
| Dynarmic::HaltReason ARM_Dynarmic_32::RunJit() { | ||||
|     return jit.load()->Run(); | ||||
| HaltReason ARM_Dynarmic_32::RunJit() { | ||||
|     return TranslateHaltReason(jit.load()->Run()); | ||||
| } | ||||
|  | ||||
| Dynarmic::HaltReason ARM_Dynarmic_32::StepJit() { | ||||
|     return jit.load()->Step(); | ||||
| HaltReason ARM_Dynarmic_32::StepJit() { | ||||
|     return TranslateHaltReason(jit.load()->Step()); | ||||
| } | ||||
|  | ||||
| u32 ARM_Dynarmic_32::GetSvcNumber() const { | ||||
| @@ -408,7 +409,7 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) { | ||||
|     cp15->uprw = static_cast<u32>(value); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { | ||||
| void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) const { | ||||
|     Dynarmic::A32::Jit* j = jit.load(); | ||||
|     ctx.cpu_registers = j->Regs(); | ||||
|     ctx.extension_registers = j->ExtRegs(); | ||||
| @@ -425,11 +426,11 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) { | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::SignalInterrupt() { | ||||
|     jit.load()->HaltExecution(break_loop); | ||||
|     jit.load()->HaltExecution(BreakLoop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::ClearInterrupt() { | ||||
|     jit.load()->ClearHalt(break_loop); | ||||
|     jit.load()->ClearHalt(BreakLoop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::ClearInstructionCache() { | ||||
| @@ -462,39 +463,4 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, | ||||
|     jit_cache.emplace(key, std::move(new_jit)); | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace(Core::System& system, | ||||
|                                                                          u64 fp, u64 lr, u64 pc) { | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = system.ApplicationMemory(); | ||||
|  | ||||
|     out.push_back({"", 0, pc, 0, ""}); | ||||
|  | ||||
|     // fp (= r11) points to the last frame record. | ||||
|     // Frame records are two words long: | ||||
|     // fp+0 : pointer to previous frame record | ||||
|     // fp+4 : value of lr for frame | ||||
|     for (size_t i = 0; i < 256; i++) { | ||||
|         out.push_back({"", 0, lr, 0, ""}); | ||||
|         if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 8)) { | ||||
|             break; | ||||
|         } | ||||
|         lr = memory.Read32(fp + 4); | ||||
|         fp = memory.Read32(fp); | ||||
|     } | ||||
|  | ||||
|     SymbolicateBacktrace(system, out); | ||||
|  | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktraceFromContext( | ||||
|     System& system, const ThreadContext32& ctx) { | ||||
|     const auto& reg = ctx.cpu_registers; | ||||
|     return GetBacktrace(system, reg[11], reg[14], reg[15]); | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_32::GetBacktrace() const { | ||||
|     return GetBacktrace(system, GetReg(11), GetReg(14), GetReg(15)); | ||||
| } | ||||
|  | ||||
| } // namespace Core | ||||
|   | ||||
| @@ -50,8 +50,11 @@ public: | ||||
|         return (GetPSTATE() & 0x20) != 0; | ||||
|     } | ||||
|  | ||||
|     void SaveContext(ThreadContext32& ctx) override; | ||||
|     void SaveContext(ThreadContext64& ctx) override {} | ||||
|     Architecture GetArchitecture() const override { | ||||
|         return Architecture::Aarch32; | ||||
|     } | ||||
|     void SaveContext(ThreadContext32& ctx) const override; | ||||
|     void SaveContext(ThreadContext64& ctx) const override {} | ||||
|     void LoadContext(const ThreadContext32& ctx) override; | ||||
|     void LoadContext(const ThreadContext64& ctx) override {} | ||||
|  | ||||
| @@ -64,14 +67,9 @@ public: | ||||
|     void PageTableChanged(Common::PageTable& new_page_table, | ||||
|                           std::size_t new_address_space_size_in_bits) override; | ||||
|  | ||||
|     static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system, | ||||
|                                                                const ThreadContext32& ctx); | ||||
|  | ||||
|     std::vector<BacktraceEntry> GetBacktrace() const override; | ||||
|  | ||||
| protected: | ||||
|     Dynarmic::HaltReason RunJit() override; | ||||
|     Dynarmic::HaltReason StepJit() override; | ||||
|     HaltReason RunJit() override; | ||||
|     HaltReason StepJit() override; | ||||
|     u32 GetSvcNumber() const override; | ||||
|     const Kernel::DebugWatchpoint* HaltedWatchpoint() const override; | ||||
|     void RewindBreakpointInstruction() override; | ||||
|   | ||||
| @@ -10,8 +10,9 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "common/page_table.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_64.h" | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| #include "core/debugger/debugger.h" | ||||
| @@ -113,7 +114,7 @@ public: | ||||
|         LOG_ERROR(Core_ARM, | ||||
|                   "Unimplemented instruction @ 0x{:X} for {} instructions (instr = {:08X})", pc, | ||||
|                   num_instructions, memory.Read32(pc)); | ||||
|         ReturnException(pc, ARM_Interface::no_execute); | ||||
|         ReturnException(pc, PrefetchAbort); | ||||
|     } | ||||
|  | ||||
|     void InstructionCacheOperationRaised(Dynarmic::A64::InstructionCacheOperation op, | ||||
| @@ -148,11 +149,11 @@ public: | ||||
|             return; | ||||
|         case Dynarmic::A64::Exception::NoExecuteFault: | ||||
|             LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc); | ||||
|             ReturnException(pc, ARM_Interface::no_execute); | ||||
|             ReturnException(pc, PrefetchAbort); | ||||
|             return; | ||||
|         default: | ||||
|             if (debugger_enabled) { | ||||
|                 ReturnException(pc, ARM_Interface::breakpoint); | ||||
|                 ReturnException(pc, InstructionBreakpoint); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
| @@ -164,7 +165,7 @@ public: | ||||
|  | ||||
|     void CallSVC(u32 swi) override { | ||||
|         parent.svc_swi = swi; | ||||
|         parent.jit.load()->HaltExecution(ARM_Interface::svc_call); | ||||
|         parent.jit.load()->HaltExecution(SupervisorCall); | ||||
|     } | ||||
|  | ||||
|     void AddTicks(u64 ticks) override { | ||||
| @@ -207,7 +208,7 @@ public: | ||||
|         if (!memory.IsValidVirtualAddressRange(addr, size)) { | ||||
|             LOG_CRITICAL(Core_ARM, "Stopping execution due to unmapped memory access at {:#x}", | ||||
|                          addr); | ||||
|             parent.jit.load()->HaltExecution(ARM_Interface::no_execute); | ||||
|             parent.jit.load()->HaltExecution(PrefetchAbort); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| @@ -218,7 +219,7 @@ public: | ||||
|         const auto match{parent.MatchingWatchpoint(addr, size, type)}; | ||||
|         if (match) { | ||||
|             parent.halted_watchpoint = match; | ||||
|             parent.jit.load()->HaltExecution(ARM_Interface::watchpoint); | ||||
|             parent.jit.load()->HaltExecution(DataAbort); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
| @@ -383,12 +384,12 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | ||||
|     return std::make_shared<Dynarmic::A64::Jit>(config); | ||||
| } | ||||
|  | ||||
| Dynarmic::HaltReason ARM_Dynarmic_64::RunJit() { | ||||
|     return jit.load()->Run(); | ||||
| HaltReason ARM_Dynarmic_64::RunJit() { | ||||
|     return TranslateHaltReason(jit.load()->Run()); | ||||
| } | ||||
|  | ||||
| Dynarmic::HaltReason ARM_Dynarmic_64::StepJit() { | ||||
|     return jit.load()->Step(); | ||||
| HaltReason ARM_Dynarmic_64::StepJit() { | ||||
|     return TranslateHaltReason(jit.load()->Step()); | ||||
| } | ||||
|  | ||||
| u32 ARM_Dynarmic_64::GetSvcNumber() const { | ||||
| @@ -464,7 +465,7 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) { | ||||
|     cb->tpidr_el0 = value; | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { | ||||
| void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) const { | ||||
|     Dynarmic::A64::Jit* j = jit.load(); | ||||
|     ctx.cpu_registers = j->GetRegisters(); | ||||
|     ctx.sp = j->GetSP(); | ||||
| @@ -489,11 +490,11 @@ void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::SignalInterrupt() { | ||||
|     jit.load()->HaltExecution(break_loop); | ||||
|     jit.load()->HaltExecution(BreakLoop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::ClearInterrupt() { | ||||
|     jit.load()->ClearHalt(break_loop); | ||||
|     jit.load()->ClearHalt(BreakLoop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::ClearInstructionCache() { | ||||
| @@ -526,39 +527,4 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, | ||||
|     jit_cache.emplace(key, std::move(new_jit)); | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace(Core::System& system, | ||||
|                                                                          u64 fp, u64 lr, u64 pc) { | ||||
|     std::vector<BacktraceEntry> out; | ||||
|     auto& memory = system.ApplicationMemory(); | ||||
|  | ||||
|     out.push_back({"", 0, pc, 0, ""}); | ||||
|  | ||||
|     // fp (= x29) points to the previous frame record. | ||||
|     // Frame records are two words long: | ||||
|     // fp+0 : pointer to previous frame record | ||||
|     // fp+8 : value of lr for frame | ||||
|     for (size_t i = 0; i < 256; i++) { | ||||
|         out.push_back({"", 0, lr, 0, ""}); | ||||
|         if (!fp || (fp % 4 != 0) || !memory.IsValidVirtualAddressRange(fp, 16)) { | ||||
|             break; | ||||
|         } | ||||
|         lr = memory.Read64(fp + 8); | ||||
|         fp = memory.Read64(fp); | ||||
|     } | ||||
|  | ||||
|     SymbolicateBacktrace(system, out); | ||||
|  | ||||
|     return out; | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktraceFromContext( | ||||
|     System& system, const ThreadContext64& ctx) { | ||||
|     const auto& reg = ctx.cpu_registers; | ||||
|     return GetBacktrace(system, reg[29], reg[30], ctx.pc); | ||||
| } | ||||
|  | ||||
| std::vector<ARM_Interface::BacktraceEntry> ARM_Dynarmic_64::GetBacktrace() const { | ||||
|     return GetBacktrace(system, GetReg(29), GetReg(30), GetPC()); | ||||
| } | ||||
|  | ||||
| } // namespace Core | ||||
|   | ||||
| @@ -43,8 +43,11 @@ public: | ||||
|     void SetTPIDR_EL0(u64 value) override; | ||||
|     u64 GetTPIDR_EL0() const override; | ||||
|  | ||||
|     void SaveContext(ThreadContext32& ctx) override {} | ||||
|     void SaveContext(ThreadContext64& ctx) override; | ||||
|     Architecture GetArchitecture() const override { | ||||
|         return Architecture::Aarch64; | ||||
|     } | ||||
|     void SaveContext(ThreadContext32& ctx) const override {} | ||||
|     void SaveContext(ThreadContext64& ctx) const override; | ||||
|     void LoadContext(const ThreadContext32& ctx) override {} | ||||
|     void LoadContext(const ThreadContext64& ctx) override; | ||||
|  | ||||
| @@ -57,14 +60,9 @@ public: | ||||
|     void PageTableChanged(Common::PageTable& new_page_table, | ||||
|                           std::size_t new_address_space_size_in_bits) override; | ||||
|  | ||||
|     static std::vector<BacktraceEntry> GetBacktraceFromContext(System& system, | ||||
|                                                                const ThreadContext64& ctx); | ||||
|  | ||||
|     std::vector<BacktraceEntry> GetBacktrace() const override; | ||||
|  | ||||
| protected: | ||||
|     Dynarmic::HaltReason RunJit() override; | ||||
|     Dynarmic::HaltReason StepJit() override; | ||||
|     HaltReason RunJit() override; | ||||
|     HaltReason StepJit() override; | ||||
|     u32 GetSvcNumber() const override; | ||||
|     const Kernel::DebugWatchpoint* HaltedWatchpoint() const override; | ||||
|     void RewindBreakpointInstruction() override; | ||||
| @@ -73,8 +71,6 @@ private: | ||||
|     std::shared_ptr<Dynarmic::A64::Jit> MakeJit(Common::PageTable* page_table, | ||||
|                                                 std::size_t address_space_bits) const; | ||||
|  | ||||
|     static std::vector<BacktraceEntry> GetBacktrace(Core::System& system, u64 fp, u64 lr, u64 pc); | ||||
|  | ||||
|     using JitCacheKey = std::pair<Common::PageTable*, std::size_t>; | ||||
|     using JitCacheType = | ||||
|         std::unordered_map<JitCacheKey, std::shared_ptr<Dynarmic::A64::Jit>, Common::PairHash>; | ||||
|   | ||||
| @@ -4,7 +4,7 @@ | ||||
| #include <fmt/format.h> | ||||
| #include "common/logging/log.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | ||||
| #include "core/arm/dynarmic/dynarmic_cp15.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| 
 | ||||
| @@ -1,7 +1,7 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project
 | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later
 | ||||
| 
 | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" | ||||
| #include "core/memory.h" | ||||
| 
 | ||||
| namespace Core { | ||||
| @@ -2,7 +2,7 @@ | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" | ||||
| #endif | ||||
| #include "core/arm/exclusive_monitor.h" | ||||
| #include "core/memory.h" | ||||
|   | ||||
| @@ -54,10 +54,10 @@ | ||||
| #include "video_core/renderer_base.h" | ||||
| #include "video_core/video_core.h" | ||||
|  | ||||
| MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU0, "ARM JIT", "Dynarmic CPU 0", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU1, "ARM JIT", "Dynarmic CPU 1", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU2, "ARM JIT", "Dynarmic CPU 2", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_Jit_Dynarmic_CPU3, "ARM JIT", "Dynarmic CPU 3", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_CPU0, "ARM", "CPU 0", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_CPU1, "ARM", "CPU 1", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_CPU2, "ARM", "CPU 2", MP_RGB(255, 64, 64)); | ||||
| MICROPROFILE_DEFINE(ARM_CPU3, "ARM", "CPU 3", MP_RGB(255, 64, 64)); | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| @@ -259,10 +259,10 @@ struct System::Impl { | ||||
|         is_powered_on = true; | ||||
|         exit_lock = false; | ||||
|  | ||||
|         microprofile_dynarmic[0] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU0); | ||||
|         microprofile_dynarmic[1] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU1); | ||||
|         microprofile_dynarmic[2] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU2); | ||||
|         microprofile_dynarmic[3] = MICROPROFILE_TOKEN(ARM_Jit_Dynarmic_CPU3); | ||||
|         microprofile_cpu[0] = MICROPROFILE_TOKEN(ARM_CPU0); | ||||
|         microprofile_cpu[1] = MICROPROFILE_TOKEN(ARM_CPU1); | ||||
|         microprofile_cpu[2] = MICROPROFILE_TOKEN(ARM_CPU2); | ||||
|         microprofile_cpu[3] = MICROPROFILE_TOKEN(ARM_CPU3); | ||||
|  | ||||
|         LOG_DEBUG(Core, "Initialized OK"); | ||||
|  | ||||
| @@ -539,7 +539,7 @@ struct System::Impl { | ||||
|     ExitCallback exit_callback; | ||||
|  | ||||
|     std::array<u64, Core::Hardware::NUM_CPU_CORES> dynarmic_ticks{}; | ||||
|     std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_dynarmic{}; | ||||
|     std::array<MicroProfileToken, Core::Hardware::NUM_CPU_CORES> microprofile_cpu{}; | ||||
| }; | ||||
|  | ||||
| System::System() : impl{std::make_unique<Impl>(*this)} {} | ||||
| @@ -927,14 +927,14 @@ void System::RegisterHostThread() { | ||||
|     impl->kernel.RegisterHostThread(); | ||||
| } | ||||
|  | ||||
| void System::EnterDynarmicProfile() { | ||||
| void System::EnterCPUProfile() { | ||||
|     std::size_t core = impl->kernel.GetCurrentHostThreadID(); | ||||
|     impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_dynarmic[core]); | ||||
|     impl->dynarmic_ticks[core] = MicroProfileEnter(impl->microprofile_cpu[core]); | ||||
| } | ||||
|  | ||||
| void System::ExitDynarmicProfile() { | ||||
| void System::ExitCPUProfile() { | ||||
|     std::size_t core = impl->kernel.GetCurrentHostThreadID(); | ||||
|     MicroProfileLeave(impl->microprofile_dynarmic[core], impl->dynarmic_ticks[core]); | ||||
|     MicroProfileLeave(impl->microprofile_cpu[core], impl->dynarmic_ticks[core]); | ||||
| } | ||||
|  | ||||
| bool System::IsMulticore() const { | ||||
|   | ||||
| @@ -412,11 +412,11 @@ public: | ||||
|     /// Register a host thread as an auxiliary thread. | ||||
|     void RegisterHostThread(); | ||||
|  | ||||
|     /// Enter Dynarmic Microprofile | ||||
|     void EnterDynarmicProfile(); | ||||
|     /// Enter CPU Microprofile | ||||
|     void EnterCPUProfile(); | ||||
|  | ||||
|     /// Exit Dynarmic Microprofile | ||||
|     void ExitDynarmicProfile(); | ||||
|     /// Exit CPU Microprofile | ||||
|     void ExitCPUProfile(); | ||||
|  | ||||
|     /// Tells if system is running on multicore. | ||||
|     [[nodiscard]] bool IsMulticore() const; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Liam
					Liam