From 2fafeb5013b40546c8d8fd882a9269ca3eee1e5a Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Tue, 1 Aug 2023 12:33:00 +0200 Subject: [PATCH] early-access version 3786 --- README.md | 2 +- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- src/core/core.cpp | 38 ++------ src/core/core.h | 23 +---- src/core/cpu_manager.cpp | 22 ++--- src/core/hle/kernel/k_address_arbiter.cpp | 4 +- src/core/hle/kernel/k_condition_variable.cpp | 2 +- src/core/hle/kernel/k_process.cpp | 19 ++++ src/core/hle/kernel/k_process.h | 13 +++ src/core/hle/kernel/k_scheduler.cpp | 33 ++++--- src/core/hle/kernel/k_thread.cpp | 4 +- src/core/hle/kernel/kernel.cpp | 57 ++++++------ src/core/hle/kernel/kernel.h | 13 +-- src/core/hle/kernel/physical_core.cpp | 92 ++++++++++--------- src/core/hle/kernel/physical_core.h | 39 ++------ src/core/hle/kernel/svc.cpp | 8 +- src/core/hle/kernel/svc/svc_exception.cpp | 4 +- src/core/hle/kernel/svc/svc_light_ipc.cpp | 2 +- src/core/hle/kernel/svc/svc_processor.cpp | 2 +- .../kernel/svc/svc_secure_monitor_call.cpp | 4 +- src/core/hle/kernel/svc/svc_thread.cpp | 2 - src/core/hle/kernel/svc_generator.py | 8 +- src/core/memory.cpp | 3 +- src/core/reporter.cpp | 4 +- 25 files changed, 187 insertions(+), 215 deletions(-) diff --git a/README.md b/README.md index bdcbc1209..2ba5f8c44 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3785. +This is the source code for early-access 3786. ## Legal Notice diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 0e5359904..0bea0f516 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -188,7 +188,7 @@ public: } bool IsInterrupted() { - return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); + return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted(); } ARM_Dynarmic_32& parent; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 94521260b..e24813da7 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -233,7 +233,7 @@ public: } bool IsInterrupted() { - return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); + return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted(); } ARM_Dynarmic_64& parent; diff --git a/src/core/core.cpp b/src/core/core.cpp index af042d808..6c65ad53a 100755 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -14,7 +14,6 @@ #include "common/settings.h" #include "common/settings_enums.h" #include "common/string_util.h" -#include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" #include "core/cpu_manager.h" @@ -327,7 +326,6 @@ struct System::Impl { static_cast(SystemResultStatus::ErrorLoader) + static_cast(load_result)); } AddGlueRegistrationForProcess(*app_loader, *main_process); - kernel.InitializeCores(); // Initialize cheat engine if (cheat_engine) { @@ -644,10 +642,6 @@ bool System::IsPoweredOn() const { return impl->is_powered_on.load(std::memory_order::relaxed); } -void System::PrepareReschedule(const u32 core_index) { - impl->kernel.PrepareReschedule(core_index); -} - Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() { const std::size_t core = impl->kernel.GetCurrentHostThreadID(); return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES @@ -685,14 +679,6 @@ const TelemetrySession& System::TelemetrySession() const { return *impl->telemetry_session; } -ARM_Interface& System::CurrentArmInterface() { - return impl->kernel.CurrentPhysicalCore().ArmInterface(); -} - -const ARM_Interface& System::CurrentArmInterface() const { - return impl->kernel.CurrentPhysicalCore().ArmInterface(); -} - Kernel::PhysicalCore& System::CurrentPhysicalCore() { return impl->kernel.CurrentPhysicalCore(); } @@ -701,6 +687,14 @@ const Kernel::PhysicalCore& System::CurrentPhysicalCore() const { return impl->kernel.CurrentPhysicalCore(); } +Core::ExclusiveMonitor& System::GetCurrentExclusiveMonitor() { + return impl->kernel.GetCurrentExclusiveMonitor(); +} + +Core::ARM_Interface& System::GetCurrentArmInterface() { + return impl->kernel.GetCurrentArmInterface(); +} + /// Gets the global scheduler Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() { return impl->kernel.GlobalSchedulerContext(); @@ -727,22 +721,6 @@ const Kernel::KProcess* System::ApplicationProcess() const { return impl->kernel.ApplicationProcess(); } -ARM_Interface& System::ArmInterface(std::size_t core_index) { - return impl->kernel.PhysicalCore(core_index).ArmInterface(); -} - -const ARM_Interface& System::ArmInterface(std::size_t core_index) const { - return impl->kernel.PhysicalCore(core_index).ArmInterface(); -} - -ExclusiveMonitor& System::Monitor() { - return impl->kernel.GetExclusiveMonitor(); -} - -const ExclusiveMonitor& System::Monitor() const { - return impl->kernel.GetExclusiveMonitor(); -} - Memory::Memory& System::ApplicationMemory() { return impl->memory; } diff --git a/src/core/core.h b/src/core/core.h index 58fa9ab4e..b79000344 100755 --- a/src/core/core.h +++ b/src/core/core.h @@ -223,9 +223,6 @@ public: /// Gets a reference to the telemetry session for this emulation session. [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; - /// Prepare the core emulation for a reschedule - void PrepareReschedule(u32 core_index); - /// Provides a reference to the gou dirty memory manager. [[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager(); @@ -239,23 +236,17 @@ public: /// Gets and resets core performance statistics [[nodiscard]] PerfStatsResults GetAndResetPerfStats(); - /// Gets an ARM interface to the CPU core that is currently running - [[nodiscard]] ARM_Interface& CurrentArmInterface(); - - /// Gets an ARM interface to the CPU core that is currently running - [[nodiscard]] const ARM_Interface& CurrentArmInterface() const; - /// Gets the physical core for the CPU core that is currently running [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); /// Gets the physical core for the CPU core that is currently running [[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const; - /// Gets a reference to an ARM interface for the CPU core with the specified index - [[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index); + /// Gets the exclusive monitor for the process on the current core + Core::ExclusiveMonitor& GetCurrentExclusiveMonitor(); - /// Gets a const reference to an ARM interface from the CPU core with the specified index - [[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const; + /// Gets the JIT instance for the process on the current core + Core::ARM_Interface& GetCurrentArmInterface(); /// Gets a reference to the underlying CPU manager. [[nodiscard]] CpuManager& GetCpuManager(); @@ -263,12 +254,6 @@ public: /// Gets a const reference to the underlying CPU manager [[nodiscard]] const CpuManager& GetCpuManager() const; - /// Gets a reference to the exclusive monitor - [[nodiscard]] ExclusiveMonitor& Monitor(); - - /// Gets a constant reference to the exclusive monitor - [[nodiscard]] const ExclusiveMonitor& Monitor() const; - /// Gets a mutable reference to the system memory instance. [[nodiscard]] Core::Memory::Memory& ApplicationMemory(); diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 60f2566bf..20f5c3242 100755 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -9,6 +9,7 @@ #include "core/core_timing.h" #include "core/cpu_manager.h" #include "core/hle/kernel/k_interrupt_manager.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" @@ -73,13 +74,15 @@ void CpuManager::HandleInterrupt() { void CpuManager::MultiCoreRunGuestThread() { // Similar to UserModeThreadStarter in HOS auto& kernel = system.Kernel(); + auto& process = Kernel::GetCurrentProcess(kernel); kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - while (!physical_core->IsInterrupted()) { - physical_core->Run(); - physical_core = &kernel.CurrentPhysicalCore(); + auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex()); + + if (physical_core->Run(*arm_interface)) { + continue; } HandleInterrupt(); @@ -95,11 +98,7 @@ void CpuManager::MultiCoreRunIdleThread() { kernel.CurrentScheduler()->OnThreadStart(); while (true) { - auto& physical_core = kernel.CurrentPhysicalCore(); - if (!physical_core.IsInterrupted()) { - physical_core.Idle(); - } - + kernel.CurrentPhysicalCore().WaitForInterrupt(); HandleInterrupt(); } } @@ -110,14 +109,13 @@ void CpuManager::MultiCoreRunIdleThread() { void CpuManager::SingleCoreRunGuestThread() { auto& kernel = system.Kernel(); + auto& process = Kernel::GetCurrentProcess(kernel); kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - if (!physical_core->IsInterrupted()) { - physical_core->Run(); - physical_core = &kernel.CurrentPhysicalCore(); - } + auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex()); + physical_core->Run(*arm_interface); kernel.SetIsPhantomModeForSingleCore(true); system.CoreTiming().Advance(); diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index 18dd2cb45..deb98c263 100755 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -27,7 +27,7 @@ bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) { } bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) { - auto& monitor = system.Monitor(); + auto& monitor = system.GetCurrentExclusiveMonitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. @@ -68,7 +68,7 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 value, s32 new_value) { - auto& monitor = system.Monitor(); + auto& monitor = system.GetCurrentExclusiveMonitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index c848b6093..e4449a948 100755 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -30,7 +30,7 @@ bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) { bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u32 if_zero, u32 new_orr_mask) { - auto& monitor = system.Monitor(); + auto& monitor = system.GetCurrentExclusiveMonitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); u32 expected{}; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index 4b96180dd..d888bd450 100755 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -11,6 +11,9 @@ #include "common/logging/log.h" #include "common/scope_exit.h" #include "common/settings.h" +#include "core/arm/dynarmic/arm_dynarmic_32.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h" +#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" #include "core/core.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.h" @@ -427,6 +430,22 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) { this->ChangeState(State::Running); + auto exclusive_monitor = std::make_unique( + m_kernel.System().ApplicationMemory(), Core::Hardware::NUM_CPU_CORES); + for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { + if (m_is_64bit_process) { + m_arm_interfaces[i] = std::make_unique( + m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i); + } else { + m_arm_interfaces[i] = std::make_unique( + m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i); + } + + this->GetMemory().SetCurrentPageTable(*this, static_cast(i)); + } + + m_exclusive_monitor = std::move(exclusive_monitor); + SetupMainThread(m_kernel.System(), *this, main_thread_priority, m_main_thread_stack_top); } diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 04d8880fc..6eaef2445 100755 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -407,6 +407,14 @@ public: return name; } + Core::ExclusiveMonitor* GetExclusiveMonitor() { + return m_exclusive_monitor.get(); + } + + Core::ARM_Interface* GetArmInterface(size_t i) { + return m_arm_interfaces[i].get(); + } + private: void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -537,6 +545,11 @@ private: using TLPIterator = TLPTree::iterator; TLPTree m_fully_used_tlp_tree; TLPTree m_partially_used_tlp_tree; + +private: + std::unique_ptr m_exclusive_monitor{}; + std::array, Core::Hardware::NUM_CPU_CORES> + m_arm_interfaces{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 239f5c6c9..23c83cbd7 100755 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -494,12 +494,15 @@ void KScheduler::ScheduleImplFiber() { } void KScheduler::Unload(KThread* thread) { - auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); - cpu_core.SaveContext(thread->GetContext32()); - cpu_core.SaveContext(thread->GetContext64()); - // Save the TPIDR_EL0 system register in case it was modified. - thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0()); - cpu_core.ClearExclusiveState(); + if (thread->GetThreadType() == ThreadType::User) { + auto* process = thread->GetOwnerProcess(); + auto& cpu_core = *process->GetArmInterface(m_core_id); + cpu_core.SaveContext(thread->GetContext32()); + cpu_core.SaveContext(thread->GetContext64()); + // Save the TPIDR_EL0 system register in case it was modified. + thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0()); + cpu_core.ClearExclusiveState(); + } // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast(DpcFlag::Terminated)) == 0) { @@ -509,14 +512,16 @@ void KScheduler::Unload(KThread* thread) { } void KScheduler::Reload(KThread* thread) { - auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); - auto* process = thread->GetOwnerProcess(); - cpu_core.LoadContext(thread->GetContext32()); - cpu_core.LoadContext(thread->GetContext64()); - cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); - cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); - cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr); - cpu_core.ClearExclusiveState(); + if (thread->GetThreadType() == ThreadType::User) { + auto* process = thread->GetOwnerProcess(); + auto& cpu_core = *process->GetArmInterface(m_core_id); + cpu_core.LoadContext(thread->GetContext32()); + cpu_core.LoadContext(thread->GetContext64()); + cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); + cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); + cpu_core.LoadWatchpointArray(&process->GetWatchpoints()); + cpu_core.ClearExclusiveState(); + } } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index a49a0e97f..1eefaf364 100755 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -823,14 +823,14 @@ void KThread::CloneFpuStatus() { if (this->GetOwnerProcess()->Is64BitProcess()) { // Clone FPSR and FPCR. ThreadContext64 cur_ctx{}; - m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx); this->GetContext64().fpcr = cur_ctx.fpcr; this->GetContext64().fpsr = cur_ctx.fpsr; } else { // Clone FPSCR. ThreadContext32 cur_ctx{}; - m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); + m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx); this->GetContext32().fpscr = cur_ctx.fpscr; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 42c13e7df..97e18bb23 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -99,13 +99,6 @@ struct KernelCore::Impl { RegisterHostThread(nullptr); } - void InitializeCores() { - for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { - cores[core_id]->Initialize((*application_process).Is64BitProcess()); - system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id); - } - } - void CloseApplicationProcess() { KProcess* old_process = application_process.exchange(nullptr); if (old_process == nullptr) { @@ -137,8 +130,6 @@ struct KernelCore::Impl { preemption_event = nullptr; - exclusive_monitor.reset(); - // Cleanup persistent kernel objects auto CleanupObject = [](KAutoObject* obj) { if (obj) { @@ -205,13 +196,11 @@ struct KernelCore::Impl { } void InitializePhysicalCores() { - exclusive_monitor = - Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES); for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { const s32 core{static_cast(i)}; schedulers[i] = std::make_unique(system.Kernel()); - cores[i] = std::make_unique(i, system, *schedulers[i]); + cores[i] = std::make_unique(i, system); auto* main_thread{Kernel::KThread::Create(system.Kernel())}; main_thread->SetCurrentCore(core); @@ -804,7 +793,6 @@ struct KernelCore::Impl { std::mutex server_lock; std::vector> server_managers; - std::unique_ptr exclusive_monitor; std::array, Core::Hardware::NUM_CPU_CORES> cores; // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others @@ -865,10 +853,6 @@ void KernelCore::Initialize() { impl->Initialize(*this); } -void KernelCore::InitializeCores() { - impl->InitializeCores(); -} - void KernelCore::Shutdown() { impl->Shutdown(); } @@ -966,12 +950,12 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() { return *impl->hardware_timer; } -Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { - return *impl->exclusive_monitor; +Core::ExclusiveMonitor& KernelCore::GetCurrentExclusiveMonitor() { + return *GetCurrentProcess(*this).GetExclusiveMonitor(); } -const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { - return *impl->exclusive_monitor; +Core::ARM_Interface& KernelCore::GetCurrentArmInterface() { + return *GetCurrentProcess(*this).GetArmInterface(this->CurrentPhysicalCoreIndex()); } KAutoObjectWithListContainer& KernelCore::ObjectListContainer() { @@ -983,22 +967,33 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { } void KernelCore::InvalidateAllInstructionCaches() { - for (auto& physical_core : impl->cores) { - physical_core->ArmInterface().ClearInstructionCache(); + // TODO: we need to make sure the JIT is not running during this + auto process = this->ApplicationProcess(); + if (process == nullptr) { + return; + } + + for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { + auto* arm_interface = process->GetArmInterface(i); + if (arm_interface) { + arm_interface->ClearInstructionCache(); + } } } void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) { - for (auto& physical_core : impl->cores) { - if (!physical_core->IsInitialized()) { - continue; - } - physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size); + // TODO: we need to make sure the JIT is not running during this + auto process = this->ApplicationProcess(); + if (process == nullptr) { + return; } -} -void KernelCore::PrepareReschedule(std::size_t id) { - // TODO: Reimplement, this + for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { + auto* arm_interface = process->GetArmInterface(i); + if (arm_interface) { + arm_interface->InvalidateCacheRange(GetInteger(addr), size); + } + } } void KernelCore::RegisterKernelObject(KAutoObject* object) { diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index d035ced10..5636931f2 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -18,6 +18,7 @@ #include "core/hle/kernel/svc_common.h" namespace Core { +class ARM_Interface; class ExclusiveMonitor; class System; } // namespace Core @@ -104,9 +105,6 @@ public: /// Resets the kernel to a clean slate for use. void Initialize(); - /// Initializes the CPU cores. - void InitializeCores(); - /// Clears all resources in use by the kernel instance. void Shutdown(); @@ -173,12 +171,11 @@ public: /// Gets the an instance of the hardware timer. Kernel::KHardwareTimer& HardwareTimer(); - /// Stops execution of 'id' core, in order to reschedule a new thread. - void PrepareReschedule(std::size_t id); + /// Gets the exclusive monitor for the process on the current core + Core::ExclusiveMonitor& GetCurrentExclusiveMonitor(); - Core::ExclusiveMonitor& GetExclusiveMonitor(); - - const Core::ExclusiveMonitor& GetExclusiveMonitor() const; + /// Gets the JIT instance for the process on the current core + Core::ARM_Interface& GetCurrentArmInterface(); KAutoObjectWithListContainer& ObjectListContainer(); diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index a8512a061..527dfcf3a 100755 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -4,69 +4,77 @@ #include "core/arm/dynarmic/arm_dynarmic_32.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/core.h" -#include "core/hle/kernel/k_scheduler.h" +#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" namespace Kernel { -PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KScheduler& scheduler) - : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) - // TODO(bunnei): Initialization relies on a core being available. We may later replace this with - // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. - auto& kernel = system.Kernel(); - m_arm_interface = std::make_unique( - system, kernel.IsMulticore(), - reinterpret_cast(kernel.GetExclusiveMonitor()), - m_core_index); -#else -#error Platform not supported yet. -#endif -} +PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system) + : m_core_index{core_index}, m_system{system} {} PhysicalCore::~PhysicalCore() = default; -void PhysicalCore::Initialize(bool is_64_bit) { -#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) - auto& kernel = m_system.Kernel(); - if (!is_64_bit) { - // We already initialized a 64-bit core, replace with a 32-bit one. - m_arm_interface = std::make_unique( - m_system, kernel.IsMulticore(), - reinterpret_cast(kernel.GetExclusiveMonitor()), - m_core_index); +bool PhysicalCore::Run(Core::ARM_Interface& current_arm_interface) { + // SAFETY: we need to lock around storing the JIT instance member to serialize + // access with another thread that wants to send us an interrupt. Otherwise we + // may end up sending an interrupt to an instance that is not current. + + // Mark the instance as current. + { + std::scoped_lock lk{m_guard}; + + // If this core is already interrupted, return immediately. + if (m_is_interrupted) { + return false; + } + + m_current_arm_interface = std::addressof(current_arm_interface); + } + + // Run the instance. + current_arm_interface.Run(); + current_arm_interface.ClearExclusiveState(); + + { + std::scoped_lock lk{m_guard}; + + // Mark the instance as no longer current. + m_current_arm_interface = nullptr; + + // Return whether we ran to completion. + return !m_is_interrupted; } -#else -#error Platform not supported yet. -#endif } -void PhysicalCore::Run() { - m_arm_interface->Run(); - m_arm_interface->ClearExclusiveState(); -} - -void PhysicalCore::Idle() { +void PhysicalCore::WaitForInterrupt() { + // Wait for a signal. std::unique_lock lk{m_guard}; m_on_interrupt.wait(lk, [this] { return m_is_interrupted; }); } -bool PhysicalCore::IsInterrupted() const { - return m_is_interrupted; -} - void PhysicalCore::Interrupt() { - std::unique_lock lk{m_guard}; - m_is_interrupted = true; - m_arm_interface->SignalInterrupt(); + { + std::scoped_lock lk{m_guard}; + + // Mark as interrupted. + m_is_interrupted = true; + + // If we are currently executing code, interrupt the JIT. + if (m_current_arm_interface) { + m_current_arm_interface->SignalInterrupt(); + } + } + + // Signal. m_on_interrupt.notify_all(); } void PhysicalCore::ClearInterrupt() { - std::unique_lock lk{m_guard}; + std::scoped_lock lk{m_guard}; + + // Remove interrupt flag. m_is_interrupted = false; - m_arm_interface->ClearInterrupt(); } } // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 18f8891d6..eb6ab45c7 100755 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -23,19 +23,16 @@ namespace Kernel { class PhysicalCore { public: - PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_); + PhysicalCore(std::size_t core_index_, Core::System& system_); ~PhysicalCore(); YUZU_NON_COPYABLE(PhysicalCore); YUZU_NON_MOVEABLE(PhysicalCore); - /// Initialize the core for the specified parameters. - void Initialize(bool is_64_bit); + /// Execute JIT and return whether we ran to completion + bool Run(Core::ARM_Interface& current_arm_interface); - /// Execute current jit state - void Run(); - - void Idle(); + void WaitForInterrupt(); /// Interrupt this physical core. void Interrupt(); @@ -43,42 +40,22 @@ public: /// Clear this core's interrupt void ClearInterrupt(); - /// Check if this core is interrupted - bool IsInterrupted() const; - - bool IsInitialized() const { - return m_arm_interface != nullptr; + bool GetIsInterrupted() const { + return m_is_interrupted; } - Core::ARM_Interface& ArmInterface() { - return *m_arm_interface; - } - - const Core::ARM_Interface& ArmInterface() const { - return *m_arm_interface; - } - - std::size_t CoreIndex() const { + std::size_t GetCoreIndex() const { return m_core_index; } - Kernel::KScheduler& Scheduler() { - return m_scheduler; - } - - const Kernel::KScheduler& Scheduler() const { - return m_scheduler; - } - private: const std::size_t m_core_index; Core::System& m_system; - Kernel::KScheduler& m_scheduler; std::mutex m_guard; std::condition_variable m_on_interrupt; - std::unique_ptr m_arm_interface; bool m_is_interrupted{}; + Core::ARM_Interface* m_current_arm_interface{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index 0d5f7d0b7..d48a6304e 100755 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -13,19 +13,19 @@ namespace Kernel::Svc { static uint32_t GetReg32(Core::System& system, int n) { - return static_cast(system.CurrentArmInterface().GetReg(n)); + return static_cast(system.GetCurrentArmInterface().GetReg(n)); } static void SetReg32(Core::System& system, int n, uint32_t result) { - system.CurrentArmInterface().SetReg(n, static_cast(result)); + system.GetCurrentArmInterface().SetReg(n, static_cast(result)); } static uint64_t GetReg64(Core::System& system, int n) { - return system.CurrentArmInterface().GetReg(n); + return system.GetCurrentArmInterface().GetReg(n); } static void SetReg64(Core::System& system, int n, uint64_t result) { - system.CurrentArmInterface().SetReg(n, result); + system.GetCurrentArmInterface().SetReg(n, result); } // Like bit_cast, but handles the case when the source and dest diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index 580cf2f75..cc7c9ce7d 100755 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -102,9 +102,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { handle_debug_buffer(info1, info2); - auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); - const auto thread_processor_id = current_thread->GetActiveCore(); - system.ArmInterface(static_cast(thread_processor_id)).LogBacktrace(); + system.GetCurrentArmInterface().LogBacktrace(); } if (system.DebuggerEnabled()) { diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index b76ce984c..9add82d5f 100755 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -38,7 +38,7 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle, template static void SvcWrap_LightIpc(Core::System& system, F&& cb) { - auto& core = system.CurrentArmInterface(); + auto& core = system.GetCurrentArmInterface(); std::array arguments{}; Handle session_handle = static_cast(core.GetReg(0)); diff --git a/src/core/hle/kernel/svc/svc_processor.cpp b/src/core/hle/kernel/svc/svc_processor.cpp index 7602ce6c0..c795b9a22 100755 --- a/src/core/hle/kernel/svc/svc_processor.cpp +++ b/src/core/hle/kernel/svc/svc_processor.cpp @@ -11,7 +11,7 @@ namespace Kernel::Svc { /// Get which CPU core is executing the current thread int32_t GetCurrentProcessorNumber(Core::System& system) { LOG_TRACE(Kernel_SVC, "called"); - return static_cast(system.CurrentPhysicalCore().CoreIndex()); + return static_cast(system.CurrentPhysicalCore().GetCoreIndex()); } int32_t GetCurrentProcessorNumber64(Core::System& system) { diff --git a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp index 62c781551..0dbc88b80 100755 --- a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp +++ b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp @@ -23,7 +23,7 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen // Custom ABI for CallSecureMonitor. void SvcWrap_CallSecureMonitor64(Core::System& system) { - auto& core = system.CurrentPhysicalCore().ArmInterface(); + auto& core = system.GetCurrentArmInterface(); lp64::SecureMonitorArguments args{}; for (int i = 0; i < 8; i++) { args.r[i] = core.GetReg(i); @@ -37,7 +37,7 @@ void SvcWrap_CallSecureMonitor64(Core::System& system) { } void SvcWrap_CallSecureMonitor64From32(Core::System& system) { - auto& core = system.CurrentPhysicalCore().ArmInterface(); + auto& core = system.GetCurrentArmInterface(); ilp32::SecureMonitorArguments args{}; for (int i = 0; i < 8; i++) { args.r[i] = static_cast(core.GetReg(i)); diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 92bcea72b..688d9e817 100755 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -93,8 +93,6 @@ Result StartThread(Core::System& system, Handle thread_handle) { /// Called when a thread exits void ExitThread(Core::System& system) { - LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); - auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GlobalSchedulerContext().RemoveThread(current_thread); current_thread->Exit(); diff --git a/src/core/hle/kernel/svc_generator.py b/src/core/hle/kernel/svc_generator.py index 7fcbb1ba1..39640f0fe 100755 --- a/src/core/hle/kernel/svc_generator.py +++ b/src/core/hle/kernel/svc_generator.py @@ -551,19 +551,19 @@ PROLOGUE_CPP = """ namespace Kernel::Svc { static uint32_t GetReg32(Core::System& system, int n) { - return static_cast(system.CurrentArmInterface().GetReg(n)); + return static_cast(system.GetCurrentArmInterface().GetReg(n)); } static void SetReg32(Core::System& system, int n, uint32_t result) { - system.CurrentArmInterface().SetReg(n, static_cast(result)); + system.GetCurrentArmInterface().SetReg(n, static_cast(result)); } static uint64_t GetReg64(Core::System& system, int n) { - return system.CurrentArmInterface().GetReg(n); + return system.GetCurrentArmInterface().GetReg(n); } static void SetReg64(Core::System& system, int n, uint64_t result) { - system.CurrentArmInterface().SetReg(n, result); + system.GetCurrentArmInterface().SetReg(n, result); } // Like bit_cast, but handles the case when the source and dest diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 28eb4cd0e..6b58c5ba6 100755 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -46,7 +46,8 @@ struct Memory::Impl { const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth(); - system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); + process.GetArmInterface(core_id)->PageTableChanged(*current_page_table, + address_space_width); } void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index d2e05fa43..dc601b1cd 100755 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -111,7 +111,7 @@ json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 json GetProcessorStateDataAuto(Core::System& system) { const auto* process{system.ApplicationProcess()}; - auto& arm{system.CurrentArmInterface()}; + auto& arm{system.GetCurrentArmInterface()}; Core::ARM_Interface::ThreadContext64 context{}; arm.SaveContext(context); @@ -123,7 +123,7 @@ json GetProcessorStateDataAuto(Core::System& system) { json GetBacktraceData(Core::System& system) { auto out = json::array(); - const auto& backtrace{system.CurrentArmInterface().GetBacktrace()}; + const auto& backtrace{system.GetCurrentArmInterface().GetBacktrace()}; for (const auto& entry : backtrace) { out.push_back({ {"module", entry.module},