From ab89ced244db69616d29c91470d870b73b09cc69 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Fri, 24 Jan 2020 15:38:20 -0400 Subject: [PATCH 1/7] Kernel: Implement Physical Core. --- src/core/hle/kernel/physical_core.cpp | 19 ++++++++ src/core/hle/kernel/physical_core.h | 62 +++++++++++++++++++++++++++ 2 files changed, 81 insertions(+) create mode 100644 src/core/hle/kernel/physical_core.cpp create mode 100644 src/core/hle/kernel/physical_core.h diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp new file mode 100644 index 0000000000..17faef3483 --- /dev/null +++ b/src/core/hle/kernel/physical_core.cpp @@ -0,0 +1,19 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +namespace Kernel { + +PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t id, ExclusiveMonitor& exclusive_monitor) + : core_index{id}, kernel{kernel} { +#ifdef ARCHITECTURE_x86_64 + arm_interface = std::make_unique(system, exclusive_monitor, core_index); +#else + arm_interface = std::make_unique(system); + LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); +#endif + + scheduler = std::make_unique(system, *arm_interface, core_index); +} + +} // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h new file mode 100644 index 0000000000..225b31d3ed --- /dev/null +++ b/src/core/hle/kernel/physical_core.h @@ -0,0 +1,62 @@ +// Copyright 2020 yuzu Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +namespace Kernel { +class Scheduler; +} // namespace Kernel + +class ARM_Interface; +class ExclusiveMonitor; + +namespace Kernel { + +class PhysicalCore { +public: + PhysicalCore(KernelCore& kernel, std::size_t id, ExclusiveMonitor& exclusive_monitor); + + /// Execute current jit state + void Run(); + /// Execute a single instruction in current jit. + void Step(); + /// Stop JIT execution/exit + void Stop(); + + ARM_Interface& ArmInterface() { + return *arm_interface; + } + + const ARM_Interface& ArmInterface() const { + return *arm_interface; + } + + bool IsMainCore() const { + return core_index == 0; + } + + bool IsSystemCore() const { + return core_index == 3; + } + + std::size_t CoreIndex() const { + return core_index; + } + + Scheduler& Scheduler() { + return *scheduler; + } + + const Scheduler& Scheduler() const { + return *scheduler; + } + +private: + std::size_t core_index; + std::unique_ptr arm_interface; + std::unique_ptr scheduler; + KernelCore& kernel; +} + +} // namespace Kernel From 4d6a86b03fe6ae0d98838a21613b66d5196150af Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sat, 25 Jan 2020 18:55:32 -0400 Subject: [PATCH 2/7] Core: Refactor CPU Management. This commit moves ARM Interface and Scheduler handling into the kernel. --- src/core/CMakeLists.txt | 2 + src/core/core.cpp | 35 +++++++----- src/core/core_cpu.cpp | 76 ++++----------------------- src/core/core_cpu.h | 61 ++------------------- src/core/cpu_core_manager.cpp | 63 +--------------------- src/core/cpu_core_manager.h | 16 ++---- src/core/hle/kernel/kernel.cpp | 64 +++++++++++++++++++++- src/core/hle/kernel/kernel.h | 17 ++++++ src/core/hle/kernel/physical_core.cpp | 36 +++++++++++-- src/core/hle/kernel/physical_core.h | 22 +++++--- 10 files changed, 168 insertions(+), 224 deletions(-) diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 1a3647a673..d5b8091aef 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -158,6 +158,8 @@ add_library(core STATIC hle/kernel/mutex.h hle/kernel/object.cpp hle/kernel/object.h + hle/kernel/physical_core.cpp + hle/kernel/physical_core.h hle/kernel/process.cpp hle/kernel/process.h hle/kernel/process_capability.cpp diff --git a/src/core/core.cpp b/src/core/core.cpp index d697b80eff..27b8d34087 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -28,6 +28,7 @@ #include "core/hardware_interrupt_manager.h" #include "core/hle/kernel/client_port.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" @@ -119,6 +120,15 @@ struct System::Impl { return cpu_core_manager.GetCurrentCore(); } + Kernel::PhysicalCore& CurrentPhysicalCore() { + const auto i = cpu_core_manager.GetCurrentCoreIndex(); + return kernel.PhysicalCore(i); + } + + Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) { + return kernel.PhysicalCore(index); + } + ResultStatus RunLoop(bool tight_loop) { status = ResultStatus::Success; @@ -131,8 +141,8 @@ struct System::Impl { LOG_DEBUG(HW_Memory, "initialized OK"); core_timing.Initialize(); - cpu_core_manager.Initialize(); kernel.Initialize(); + cpu_core_manager.Initialize(); const auto current_time = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()); @@ -205,7 +215,6 @@ struct System::Impl { // Main process has been loaded and been made current. // Begin GPU and CPU execution. gpu_core->Start(); - cpu_core_manager.StartThreads(); // Initialize cheat engine if (cheat_engine) { @@ -394,7 +403,7 @@ System::ResultStatus System::SingleStep() { } void System::InvalidateCpuInstructionCaches() { - impl->cpu_core_manager.InvalidateAllInstructionCaches(); + impl->kernel.InvalidateAllInstructionCaches(); } System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { @@ -428,11 +437,11 @@ const TelemetrySession& System::TelemetrySession() const { } ARM_Interface& System::CurrentArmInterface() { - return CurrentCpuCore().ArmInterface(); + return impl->CurrentPhysicalCore().ArmInterface(); } const ARM_Interface& System::CurrentArmInterface() const { - return CurrentCpuCore().ArmInterface(); + return impl->CurrentPhysicalCore().ArmInterface(); } std::size_t System::CurrentCoreIndex() const { @@ -440,19 +449,19 @@ std::size_t System::CurrentCoreIndex() const { } Kernel::Scheduler& System::CurrentScheduler() { - return CurrentCpuCore().Scheduler(); + return impl->CurrentPhysicalCore().Scheduler(); } const Kernel::Scheduler& System::CurrentScheduler() const { - return CurrentCpuCore().Scheduler(); + return impl->CurrentPhysicalCore().Scheduler(); } Kernel::Scheduler& System::Scheduler(std::size_t core_index) { - return CpuCore(core_index).Scheduler(); + return impl->GetPhysicalCore(core_index).Scheduler(); } const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { - return CpuCore(core_index).Scheduler(); + return impl->GetPhysicalCore(core_index).Scheduler(); } /// Gets the global scheduler @@ -474,11 +483,11 @@ const Kernel::Process* System::CurrentProcess() const { } ARM_Interface& System::ArmInterface(std::size_t core_index) { - return CpuCore(core_index).ArmInterface(); + return impl->GetPhysicalCore(core_index).ArmInterface(); } const ARM_Interface& System::ArmInterface(std::size_t core_index) const { - return CpuCore(core_index).ArmInterface(); + return impl->GetPhysicalCore(core_index).ArmInterface(); } Cpu& System::CpuCore(std::size_t core_index) { @@ -491,11 +500,11 @@ const Cpu& System::CpuCore(std::size_t core_index) const { } ExclusiveMonitor& System::Monitor() { - return impl->cpu_core_manager.GetExclusiveMonitor(); + return impl->kernel.GetExclusiveMonitor(); } const ExclusiveMonitor& System::Monitor() const { - return impl->cpu_core_manager.GetExclusiveMonitor(); + return impl->kernel.GetExclusiveMonitor(); } Memory::Memory& System::Memory() { diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp index 630cd4feb0..bcfdf01985 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_cpu.cpp @@ -14,6 +14,8 @@ #include "core/core.h" #include "core/core_cpu.h" #include "core/core_timing.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/scheduler.h" #include "core/hle/kernel/thread.h" #include "core/hle/lock.h" @@ -21,68 +23,15 @@ namespace Core { -void CpuBarrier::NotifyEnd() { - std::unique_lock lock{mutex}; - end = true; - condition.notify_all(); -} - -bool CpuBarrier::Rendezvous() { - if (!Settings::values.use_multi_core) { - // Meaningless when running in single-core mode - return true; - } - - if (!end) { - std::unique_lock lock{mutex}; - - --cores_waiting; - if (!cores_waiting) { - cores_waiting = NUM_CPU_CORES; - condition.notify_all(); - return true; - } - - condition.wait(lock); - return true; - } - - return false; -} - -Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, - std::size_t core_index) - : cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()}, - core_timing{system.CoreTiming()}, core_index{core_index} { -#ifdef ARCHITECTURE_x86_64 - arm_interface = std::make_unique(system, exclusive_monitor, core_index); -#else - arm_interface = std::make_unique(system); - LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); -#endif - - scheduler = std::make_unique(system, *arm_interface, core_index); +Cpu::Cpu(System& system, std::size_t core_index) + : global_scheduler{system.GlobalScheduler()}, + physical_core{system.Kernel().PhysicalCore(core_index)}, core_timing{system.CoreTiming()}, + core_index{core_index} { } Cpu::~Cpu() = default; -std::unique_ptr Cpu::MakeExclusiveMonitor( - [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) { -#ifdef ARCHITECTURE_x86_64 - return std::make_unique(memory, num_cores); -#else - // TODO(merry): Passthrough exclusive monitor - return nullptr; -#endif -} - void Cpu::RunLoop(bool tight_loop) { - // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step - if (!cpu_barrier.Rendezvous()) { - // If rendezvous failed, session has been killed - return; - } - Reschedule(); // If we don't have a currently active thread then don't execute instructions, @@ -92,12 +41,10 @@ void Cpu::RunLoop(bool tight_loop) { core_timing.Idle(); } else { if (tight_loop) { - arm_interface->Run(); + physical_core.Run(); } else { - arm_interface->Step(); + physical_core.Step(); } - // We are stopping a run, exclusive state must be cleared - arm_interface->ClearExclusiveState(); } core_timing.Advance(); @@ -109,7 +56,7 @@ void Cpu::SingleStep() { } void Cpu::PrepareReschedule() { - arm_interface->PrepareReschedule(); + physical_core.Stop(); } void Cpu::Reschedule() { @@ -117,11 +64,8 @@ void Cpu::Reschedule() { std::lock_guard lock(HLE::g_hle_lock); global_scheduler.SelectThread(core_index); - scheduler->TryDoContextSwitch(); -} -void Cpu::Shutdown() { - scheduler->Shutdown(); + physical_core.Scheduler().TryDoContextSwitch(); } } // namespace Core diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h index 78f5021a22..6f7aec8f98 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_cpu.h @@ -13,7 +13,7 @@ namespace Kernel { class GlobalScheduler; -class Scheduler; +class PhysicalCore; } // namespace Kernel namespace Core { @@ -30,32 +30,11 @@ class Memory; namespace Core { -class ARM_Interface; -class ExclusiveMonitor; - constexpr unsigned NUM_CPU_CORES{4}; -class CpuBarrier { -public: - bool IsAlive() const { - return !end; - } - - void NotifyEnd(); - - bool Rendezvous(); - -private: - unsigned cores_waiting{NUM_CPU_CORES}; - std::mutex mutex; - std::condition_variable condition; - std::atomic end{}; -}; - class Cpu { public: - Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier, - std::size_t core_index); + Cpu(System& system, std::size_t core_index); ~Cpu(); void RunLoop(bool tight_loop = true); @@ -64,22 +43,6 @@ public: void PrepareReschedule(); - ARM_Interface& ArmInterface() { - return *arm_interface; - } - - const ARM_Interface& ArmInterface() const { - return *arm_interface; - } - - Kernel::Scheduler& Scheduler() { - return *scheduler; - } - - const Kernel::Scheduler& Scheduler() const { - return *scheduler; - } - bool IsMainCore() const { return core_index == 0; } @@ -88,29 +51,11 @@ public: return core_index; } - void Shutdown(); - - /** - * Creates an exclusive monitor to handle exclusive reads/writes. - * - * @param memory The current memory subsystem that the monitor may wish - * to keep track of. - * - * @param num_cores The number of cores to assume about the CPU. - * - * @returns The constructed exclusive monitor instance, or nullptr if the current - * CPU backend is unable to use an exclusive monitor. - */ - static std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, - std::size_t num_cores); - private: void Reschedule(); - std::unique_ptr arm_interface; - CpuBarrier& cpu_barrier; Kernel::GlobalScheduler& global_scheduler; - std::unique_ptr scheduler; + Kernel::PhysicalCore& physical_core; Timing::CoreTiming& core_timing; std::atomic reschedule_pending = false; diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp index f04a341336..ab03e8fdf2 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_core_manager.cpp @@ -24,46 +24,16 @@ CpuCoreManager::CpuCoreManager(System& system) : system{system} {} CpuCoreManager::~CpuCoreManager() = default; void CpuCoreManager::Initialize() { - barrier = std::make_unique(); - exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size()); for (std::size_t index = 0; index < cores.size(); ++index) { - cores[index] = std::make_unique(system, *exclusive_monitor, *barrier, index); - } -} - -void CpuCoreManager::StartThreads() { - // Create threads for CPU cores 1-3, and build thread_to_cpu map - // CPU core 0 is run on the main thread - thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); - if (!Settings::values.use_multi_core) { - return; - } - - for (std::size_t index = 0; index < core_threads.size(); ++index) { - core_threads[index] = std::make_unique(RunCpuCore, std::cref(system), - std::ref(*cores[index + 1])); - thread_to_cpu[core_threads[index]->get_id()] = cores[index + 1].get(); + cores[index] = std::make_unique(system, index); } } void CpuCoreManager::Shutdown() { - barrier->NotifyEnd(); - if (Settings::values.use_multi_core) { - for (auto& thread : core_threads) { - thread->join(); - thread.reset(); - } - } - - thread_to_cpu.clear(); for (auto& cpu_core : cores) { - cpu_core->Shutdown(); cpu_core.reset(); } - - exclusive_monitor.reset(); - barrier.reset(); } Cpu& CpuCoreManager::GetCore(std::size_t index) { @@ -74,42 +44,17 @@ const Cpu& CpuCoreManager::GetCore(std::size_t index) const { return *cores.at(index); } -ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() { - return *exclusive_monitor; -} - -const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const { - return *exclusive_monitor; -} - Cpu& CpuCoreManager::GetCurrentCore() { - if (Settings::values.use_multi_core) { - const auto& search = thread_to_cpu.find(std::this_thread::get_id()); - ASSERT(search != thread_to_cpu.end()); - ASSERT(search->second); - return *search->second; - } - // Otherwise, use single-threaded mode active_core variable return *cores[active_core]; } const Cpu& CpuCoreManager::GetCurrentCore() const { - if (Settings::values.use_multi_core) { - const auto& search = thread_to_cpu.find(std::this_thread::get_id()); - ASSERT(search != thread_to_cpu.end()); - ASSERT(search->second); - return *search->second; - } - // Otherwise, use single-threaded mode active_core variable return *cores[active_core]; } void CpuCoreManager::RunLoop(bool tight_loop) { - // Update thread_to_cpu in case Core 0 is run from a different host thread - thread_to_cpu[std::this_thread::get_id()] = cores[0].get(); - if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -143,10 +88,4 @@ void CpuCoreManager::RunLoop(bool tight_loop) { } } -void CpuCoreManager::InvalidateAllInstructionCaches() { - for (auto& cpu : cores) { - cpu->ArmInterface().ClearInstructionCache(); - } -} - } // namespace Core diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h index 2cbbf8216d..2a7f84d5cf 100644 --- a/src/core/cpu_core_manager.h +++ b/src/core/cpu_core_manager.h @@ -12,8 +12,6 @@ namespace Core { class Cpu; -class CpuBarrier; -class ExclusiveMonitor; class System; class CpuCoreManager { @@ -28,7 +26,6 @@ public: CpuCoreManager& operator=(CpuCoreManager&&) = delete; void Initialize(); - void StartThreads(); void Shutdown(); Cpu& GetCore(std::size_t index); @@ -37,25 +34,18 @@ public: Cpu& GetCurrentCore(); const Cpu& GetCurrentCore() const; - ExclusiveMonitor& GetExclusiveMonitor(); - const ExclusiveMonitor& GetExclusiveMonitor() const; + std::size_t GetCurrentCoreIndex() const { + return active_core; + } void RunLoop(bool tight_loop); - void InvalidateAllInstructionCaches(); - private: static constexpr std::size_t NUM_CPU_CORES = 4; - std::unique_ptr exclusive_monitor; - std::unique_ptr barrier; std::array, NUM_CPU_CORES> cores; - std::array, NUM_CPU_CORES - 1> core_threads; std::size_t active_core{}; ///< Active core, only used in single thread mode - /// Map of guest threads to CPU cores - std::map thread_to_cpu; - System& system; }; diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1d0783bd32..b7fd480d10 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -9,7 +9,11 @@ #include "common/assert.h" #include "common/logging/log.h" - +#include "core/arm/arm_interface.h" +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif +#include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" #include "core/core_timing_util.h" @@ -17,6 +21,7 @@ #include "core/hle/kernel/errors.h" #include "core/hle/kernel/handle_table.h" #include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/resource_limit.h" #include "core/hle/kernel/scheduler.h" @@ -98,6 +103,7 @@ struct KernelCore::Impl { void Initialize(KernelCore& kernel) { Shutdown(); + InitializePhysicalCores(kernel); InitializeSystemResourceLimit(kernel); InitializeThreads(); InitializePreemption(); @@ -121,6 +127,20 @@ struct KernelCore::Impl { global_scheduler.Shutdown(); named_ports.clear(); + + for (auto& core : cores) { + core.Shutdown(); + } + cores.clear(); + + exclusive_monitor.reset(nullptr); + } + + void InitializePhysicalCores(KernelCore& kernel) { + exclusive_monitor = MakeExclusiveMonitor(); + for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { + cores.emplace_back(system, kernel, i, *exclusive_monitor); + } } // Creates the default system resource limit @@ -136,6 +156,7 @@ struct KernelCore::Impl { ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); } + void InitializeThreads() { thread_wakeup_event_type = Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback); @@ -163,6 +184,16 @@ struct KernelCore::Impl { system.Memory().SetCurrentPageTable(*process); } + std::unique_ptr MakeExclusiveMonitor() { + #ifdef ARCHITECTURE_x86_64 + return std::make_unique(system.Memory(), + global_scheduler.CpuCoresCount()); + #else + // TODO(merry): Passthrough exclusive monitor + return nullptr; + #endif + } + std::atomic next_object_id{0}; std::atomic next_kernel_process_id{Process::InitialKIPIDMin}; std::atomic next_user_process_id{Process::ProcessIDMin}; @@ -186,6 +217,9 @@ struct KernelCore::Impl { /// the ConnectToPort SVC. NamedPortTable named_ports; + std::unique_ptr exclusive_monitor; + std::vector cores; + // System context Core::System& system; }; @@ -240,6 +274,34 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const { return impl->global_scheduler; } +Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { + return impl->cores[id]; +} + +const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { + return impl->cores[id]; +} + +Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { + return *impl->exclusive_monitor; +} + +const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { + return *impl->exclusive_monitor; +} + +void KernelCore::InvalidateAllInstructionCaches() { + for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) { + PhysicalCore(i).ArmInterface().ClearInstructionCache(); + } +} + +void KernelCore::PrepareReschedule(std::size_t id) { + if (id >= 0 && id < impl->global_scheduler.CpuCoresCount()) { + impl->cores[id].Stop(); + } +} + void KernelCore::AddNamedPort(std::string name, std::shared_ptr port) { impl->named_ports.emplace(std::move(name), std::move(port)); } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3bf0068ed9..536068f74e 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -11,6 +11,7 @@ #include "core/hle/kernel/object.h" namespace Core { +class ExclusiveMonitor; class System; } @@ -25,6 +26,7 @@ class AddressArbiter; class ClientPort; class GlobalScheduler; class HandleTable; +class PhysicalCore; class Process; class ResourceLimit; class Thread; @@ -84,6 +86,21 @@ public: /// Gets the sole instance of the global scheduler const Kernel::GlobalScheduler& GlobalScheduler() const; + /// Gets the an instance of the respective physical CPU core. + Kernel::PhysicalCore& PhysicalCore(std::size_t id); + + /// Gets the an instance of the respective physical CPU core. + const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const; + + /// Stops execution of 'id' core, in order to reschedule a new thread. + void PrepareReschedule(std::size_t id); + + Core::ExclusiveMonitor& GetExclusiveMonitor(); + + const Core::ExclusiveMonitor& GetExclusiveMonitor() const; + + void InvalidateAllInstructionCaches(); + /// Adds a port to the named port table void AddNamedPort(std::string name, std::shared_ptr port); diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 17faef3483..7d84e3d282 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -2,18 +2,48 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include "common/logging/log.h" +#include "core/arm/arm_interface.h" +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif +#include "core/arm/exclusive_monitor.h" +#include "core/arm/unicorn/arm_unicorn.h" +#include "core/core.h" +#include "core/hle/kernel/kernel.h" +#include "core/hle/kernel/physical_core.h" +#include "core/hle/kernel/scheduler.h" +#include "core/hle/kernel/thread.h" + namespace Kernel { -PhysicalCore::PhysicalCore(KernelCore& kernel, std::size_t id, ExclusiveMonitor& exclusive_monitor) +PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor) : core_index{id}, kernel{kernel} { #ifdef ARCHITECTURE_x86_64 - arm_interface = std::make_unique(system, exclusive_monitor, core_index); + arm_interface = std::make_unique(system, exclusive_monitor, core_index); #else - arm_interface = std::make_unique(system); + arm_interface = std::make_unique(system); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif scheduler = std::make_unique(system, *arm_interface, core_index); } +void PhysicalCore::Run() { + arm_interface->Run(); + arm_interface->ClearExclusiveState(); +} + +void PhysicalCore::Step() { + arm_interface->Step(); +} + +void PhysicalCore::Stop() { + arm_interface->PrepareReschedule(); +} + +void PhysicalCore::Shutdown() { + scheduler->Shutdown(); +} + } // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 225b31d3ed..a7848e030f 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -8,14 +8,17 @@ namespace Kernel { class Scheduler; } // namespace Kernel +namespace Core { class ARM_Interface; class ExclusiveMonitor; +class System; +} // namespace Core namespace Kernel { class PhysicalCore { public: - PhysicalCore(KernelCore& kernel, std::size_t id, ExclusiveMonitor& exclusive_monitor); + PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor); /// Execute current jit state void Run(); @@ -24,11 +27,14 @@ public: /// Stop JIT execution/exit void Stop(); - ARM_Interface& ArmInterface() { + // Shutdown this physical core. + void Shutdown(); + + Core::ARM_Interface& ArmInterface() { return *arm_interface; } - const ARM_Interface& ArmInterface() const { + const Core::ARM_Interface& ArmInterface() const { return *arm_interface; } @@ -44,19 +50,19 @@ public: return core_index; } - Scheduler& Scheduler() { + Kernel::Scheduler& Scheduler() { return *scheduler; } - const Scheduler& Scheduler() const { + const Kernel::Scheduler& Scheduler() const { return *scheduler; } private: std::size_t core_index; - std::unique_ptr arm_interface; - std::unique_ptr scheduler; KernelCore& kernel; -} + std::unique_ptr arm_interface; + std::unique_ptr scheduler; +}; } // namespace Kernel From 450341b397766caa32138882acb52790f4120963 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 26 Jan 2020 10:28:23 -0400 Subject: [PATCH 3/7] ArmInterface: Delegate Exclusive monitor factory to exclusive monitor interfasce. --- src/core/arm/exclusive_monitor.cpp | 13 +++++++++++++ src/core/arm/exclusive_monitor.h | 10 +++++++++- src/core/hle/kernel/kernel.cpp | 17 ++--------------- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp index abd59ff4bc..00e6a19d55 100644 --- a/src/core/arm/exclusive_monitor.cpp +++ b/src/core/arm/exclusive_monitor.cpp @@ -2,10 +2,23 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#ifdef ARCHITECTURE_x86_64 +#include "core/arm/dynarmic/arm_dynarmic.h" +#endif #include "core/arm/exclusive_monitor.h" +#include "core/memory.h" namespace Core { ExclusiveMonitor::~ExclusiveMonitor() = default; +std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, std::size_t num_cores) { +#ifdef ARCHITECTURE_x86_64 + return std::make_unique(memory, num_cores); +#else + // TODO(merry): Passthrough exclusive monitor + return nullptr; +#endif +} + } // namespace Core diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h index f59aca6678..18461f2963 100644 --- a/src/core/arm/exclusive_monitor.h +++ b/src/core/arm/exclusive_monitor.h @@ -1,11 +1,17 @@ -// Copyright 2018 yuzu emulator team +// Copyright 2020 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. #pragma once +#include + #include "common/common_types.h" +namespace Memory { +class Memory; +} + namespace Core { class ExclusiveMonitor { @@ -22,4 +28,6 @@ public: virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0; }; +std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, std::size_t num_cores); + } // namespace Core diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index b7fd480d10..1986cf65c5 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include #include #include @@ -10,9 +11,6 @@ #include "common/assert.h" #include "common/logging/log.h" #include "core/arm/arm_interface.h" -#ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" -#endif #include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" @@ -137,7 +135,7 @@ struct KernelCore::Impl { } void InitializePhysicalCores(KernelCore& kernel) { - exclusive_monitor = MakeExclusiveMonitor(); + exclusive_monitor = Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { cores.emplace_back(system, kernel, i, *exclusive_monitor); } @@ -156,7 +154,6 @@ struct KernelCore::Impl { ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess()); } - void InitializeThreads() { thread_wakeup_event_type = Core::Timing::CreateEvent("ThreadWakeupCallback", ThreadWakeupCallback); @@ -184,16 +181,6 @@ struct KernelCore::Impl { system.Memory().SetCurrentPageTable(*process); } - std::unique_ptr MakeExclusiveMonitor() { - #ifdef ARCHITECTURE_x86_64 - return std::make_unique(system.Memory(), - global_scheduler.CpuCoresCount()); - #else - // TODO(merry): Passthrough exclusive monitor - return nullptr; - #endif - } - std::atomic next_object_id{0}; std::atomic next_kernel_process_id{Process::InitialKIPIDMin}; std::atomic next_user_process_id{Process::ProcessIDMin}; From e4a1ead897575ee9222b4fc1021aaa9cc58f12c8 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 26 Jan 2020 14:07:22 -0400 Subject: [PATCH 4/7] Core: Refactor CpuCoreManager to CpuManager and Cpu to Core Manager. This commit instends on better naming the new purpose of this classes. --- src/core/CMakeLists.txt | 8 +-- src/core/arm/dynarmic/arm_dynarmic.cpp | 2 +- src/core/core.cpp | 44 ++++++++-------- src/core/core.h | 10 ++-- src/core/{core_cpu.cpp => core_manager.cpp} | 14 ++--- src/core/{core_cpu.h => core_manager.h} | 6 +-- src/core/cpu_core_manager.h | 52 ------------------- .../{cpu_core_manager.cpp => cpu_manager.cpp} | 45 +++++++--------- src/core/cpu_manager.h | 52 +++++++++++++++++++ src/core/gdbstub/gdbstub.cpp | 2 +- src/core/hle/kernel/address_arbiter.cpp | 1 - src/core/hle/kernel/scheduler.cpp | 1 - src/core/hle/kernel/svc.cpp | 2 +- src/core/hle/kernel/thread.cpp | 3 +- src/core/hle/kernel/wait_object.cpp | 1 - 15 files changed, 115 insertions(+), 128 deletions(-) rename src/core/{core_cpu.cpp => core_manager.cpp} (85%) rename src/core/{core_cpu.h => core_manager.h} (91%) delete mode 100644 src/core/cpu_core_manager.h rename src/core/{cpu_core_manager.cpp => cpu_manager.cpp} (59%) create mode 100644 src/core/cpu_manager.h diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index d5b8091aef..d342cafe03 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -15,14 +15,14 @@ add_library(core STATIC constants.h core.cpp core.h - core_cpu.cpp - core_cpu.h + core_manager.cpp + core_manager.h core_timing.cpp core_timing.h core_timing_util.cpp core_timing_util.h - cpu_core_manager.cpp - cpu_core_manager.h + cpu_manager.cpp + cpu_manager.h crypto/aes_util.cpp crypto/aes_util.h crypto/encryption_layer.cpp diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp index e825c05268..f468e57e46 100644 --- a/src/core/arm/dynarmic/arm_dynarmic.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic.cpp @@ -10,7 +10,7 @@ #include "common/microprofile.h" #include "core/arm/dynarmic/arm_dynarmic.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/gdbstub/gdbstub.h" diff --git a/src/core/core.cpp b/src/core/core.cpp index 27b8d34087..bfe9525150 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -11,9 +11,9 @@ #include "common/string_util.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/core_timing.h" -#include "core/cpu_core_manager.h" +#include "core/cpu_manager.h" #include "core/file_sys/bis_factory.h" #include "core/file_sys/card_image.h" #include "core/file_sys/mode.h" @@ -114,14 +114,14 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs, struct System::Impl { explicit Impl(System& system) : kernel{system}, fs_controller{system}, memory{system}, - cpu_core_manager{system}, reporter{system}, applet_manager{system} {} + cpu_manager{system}, reporter{system}, applet_manager{system} {} - Cpu& CurrentCpuCore() { - return cpu_core_manager.GetCurrentCore(); + CoreManager& CurrentCoreManager() { + return cpu_manager.GetCurrentCoreManager(); } Kernel::PhysicalCore& CurrentPhysicalCore() { - const auto i = cpu_core_manager.GetCurrentCoreIndex(); + const auto i = cpu_manager.GetActiveCoreIndex(); return kernel.PhysicalCore(i); } @@ -132,7 +132,7 @@ struct System::Impl { ResultStatus RunLoop(bool tight_loop) { status = ResultStatus::Success; - cpu_core_manager.RunLoop(tight_loop); + cpu_manager.RunLoop(tight_loop); return status; } @@ -142,7 +142,7 @@ struct System::Impl { core_timing.Initialize(); kernel.Initialize(); - cpu_core_manager.Initialize(); + cpu_manager.Initialize(); const auto current_time = std::chrono::duration_cast( std::chrono::system_clock::now().time_since_epoch()); @@ -281,7 +281,7 @@ struct System::Impl { gpu_core.reset(); // Close all CPU/threading state - cpu_core_manager.Shutdown(); + cpu_manager.Shutdown(); // Shutdown kernel and core timing kernel.Shutdown(); @@ -351,7 +351,7 @@ struct System::Impl { std::unique_ptr gpu_core; std::unique_ptr interrupt_manager; Memory::Memory memory; - CpuCoreManager cpu_core_manager; + CpuManager cpu_manager; bool is_powered_on = false; bool exit_lock = false; @@ -386,12 +386,12 @@ struct System::Impl { System::System() : impl{std::make_unique(*this)} {} System::~System() = default; -Cpu& System::CurrentCpuCore() { - return impl->CurrentCpuCore(); +CoreManager& System::CurrentCoreManager() { + return impl->CurrentCoreManager(); } -const Cpu& System::CurrentCpuCore() const { - return impl->CurrentCpuCore(); +const CoreManager& System::CurrentCoreManager() const { + return impl->CurrentCoreManager(); } System::ResultStatus System::RunLoop(bool tight_loop) { @@ -415,13 +415,11 @@ bool System::IsPoweredOn() const { } void System::PrepareReschedule() { - CurrentCpuCore().PrepareReschedule(); + CurrentCoreManager().PrepareReschedule(); } void System::PrepareReschedule(const u32 core_index) { - if (core_index < GlobalScheduler().CpuCoresCount()) { - CpuCore(core_index).PrepareReschedule(); - } + impl->kernel.PrepareReschedule(core_index); } PerfStatsResults System::GetAndResetPerfStats() { @@ -445,7 +443,7 @@ const ARM_Interface& System::CurrentArmInterface() const { } std::size_t System::CurrentCoreIndex() const { - return CurrentCpuCore().CoreIndex(); + return impl->cpu_manager.GetActiveCoreIndex(); } Kernel::Scheduler& System::CurrentScheduler() { @@ -490,13 +488,13 @@ const ARM_Interface& System::ArmInterface(std::size_t core_index) const { return impl->GetPhysicalCore(core_index).ArmInterface(); } -Cpu& System::CpuCore(std::size_t core_index) { - return impl->cpu_core_manager.GetCore(core_index); +CoreManager& System::GetCoreManager(std::size_t core_index) { + return impl->cpu_manager.GetCoreManager(core_index); } -const Cpu& System::CpuCore(std::size_t core_index) const { +const CoreManager& System::GetCoreManager(std::size_t core_index) const { ASSERT(core_index < NUM_CPU_CORES); - return impl->cpu_core_manager.GetCore(core_index); + return impl->cpu_manager.GetCoreManager(core_index); } ExclusiveMonitor& System::Monitor() { diff --git a/src/core/core.h b/src/core/core.h index e240c5c585..e69d68fcf9 100644 --- a/src/core/core.h +++ b/src/core/core.h @@ -93,7 +93,7 @@ class Memory; namespace Core { class ARM_Interface; -class Cpu; +class CoreManager; class ExclusiveMonitor; class FrameLimiter; class PerfStats; @@ -218,10 +218,10 @@ public: const ARM_Interface& ArmInterface(std::size_t core_index) const; /// Gets a CPU interface to the CPU core with the specified index - Cpu& CpuCore(std::size_t core_index); + CoreManager& GetCoreManager(std::size_t core_index); /// Gets a CPU interface to the CPU core with the specified index - const Cpu& CpuCore(std::size_t core_index) const; + const CoreManager& GetCoreManager(std::size_t core_index) const; /// Gets a reference to the exclusive monitor ExclusiveMonitor& Monitor(); @@ -364,10 +364,10 @@ private: System(); /// Returns the currently running CPU core - Cpu& CurrentCpuCore(); + CoreManager& CurrentCoreManager(); /// Returns the currently running CPU core - const Cpu& CurrentCpuCore() const; + const CoreManager& CurrentCoreManager() const; /** * Initialize the emulated system. diff --git a/src/core/core_cpu.cpp b/src/core/core_manager.cpp similarity index 85% rename from src/core/core_cpu.cpp rename to src/core/core_manager.cpp index bcfdf01985..bb03857d5b 100644 --- a/src/core/core_cpu.cpp +++ b/src/core/core_manager.cpp @@ -12,7 +12,7 @@ #include "core/arm/exclusive_monitor.h" #include "core/arm/unicorn/arm_unicorn.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/core_timing.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" @@ -23,15 +23,15 @@ namespace Core { -Cpu::Cpu(System& system, std::size_t core_index) +CoreManager::CoreManager(System& system, std::size_t core_index) : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore(core_index)}, core_timing{system.CoreTiming()}, core_index{core_index} { } -Cpu::~Cpu() = default; +CoreManager::~CoreManager() = default; -void Cpu::RunLoop(bool tight_loop) { +void CoreManager::RunLoop(bool tight_loop) { Reschedule(); // If we don't have a currently active thread then don't execute instructions, @@ -51,15 +51,15 @@ void Cpu::RunLoop(bool tight_loop) { Reschedule(); } -void Cpu::SingleStep() { +void CoreManager::SingleStep() { return RunLoop(false); } -void Cpu::PrepareReschedule() { +void CoreManager::PrepareReschedule() { physical_core.Stop(); } -void Cpu::Reschedule() { +void CoreManager::Reschedule() { // Lock the global kernel mutex when we manipulate the HLE state std::lock_guard lock(HLE::g_hle_lock); diff --git a/src/core/core_cpu.h b/src/core/core_manager.h similarity index 91% rename from src/core/core_cpu.h rename to src/core/core_manager.h index 6f7aec8f98..7bc9679c16 100644 --- a/src/core/core_cpu.h +++ b/src/core/core_manager.h @@ -32,10 +32,10 @@ namespace Core { constexpr unsigned NUM_CPU_CORES{4}; -class Cpu { +class CoreManager { public: - Cpu(System& system, std::size_t core_index); - ~Cpu(); + CoreManager(System& system, std::size_t core_index); + ~CoreManager(); void RunLoop(bool tight_loop = true); diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h deleted file mode 100644 index 2a7f84d5cf..0000000000 --- a/src/core/cpu_core_manager.h +++ /dev/null @@ -1,52 +0,0 @@ -// Copyright 2018 yuzu emulator team -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include -#include -#include -#include - -namespace Core { - -class Cpu; -class System; - -class CpuCoreManager { -public: - explicit CpuCoreManager(System& system); - CpuCoreManager(const CpuCoreManager&) = delete; - CpuCoreManager(CpuCoreManager&&) = delete; - - ~CpuCoreManager(); - - CpuCoreManager& operator=(const CpuCoreManager&) = delete; - CpuCoreManager& operator=(CpuCoreManager&&) = delete; - - void Initialize(); - void Shutdown(); - - Cpu& GetCore(std::size_t index); - const Cpu& GetCore(std::size_t index) const; - - Cpu& GetCurrentCore(); - const Cpu& GetCurrentCore() const; - - std::size_t GetCurrentCoreIndex() const { - return active_core; - } - - void RunLoop(bool tight_loop); - -private: - static constexpr std::size_t NUM_CPU_CORES = 4; - - std::array, NUM_CPU_CORES> cores; - std::size_t active_core{}; ///< Active core, only used in single thread mode - - System& system; -}; - -} // namespace Core diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_manager.cpp similarity index 59% rename from src/core/cpu_core_manager.cpp rename to src/core/cpu_manager.cpp index ab03e8fdf2..abc8aad9ef 100644 --- a/src/core/cpu_core_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -5,56 +5,49 @@ #include "common/assert.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/core_timing.h" -#include "core/cpu_core_manager.h" +#include "core/cpu_manager.h" #include "core/gdbstub/gdbstub.h" #include "core/settings.h" namespace Core { -namespace { -void RunCpuCore(const System& system, Cpu& cpu_state) { - while (system.IsPoweredOn()) { - cpu_state.RunLoop(true); - } -} -} // Anonymous namespace -CpuCoreManager::CpuCoreManager(System& system) : system{system} {} -CpuCoreManager::~CpuCoreManager() = default; +CpuManager::CpuManager(System& system) : system{system} {} +CpuManager::~CpuManager() = default; -void CpuCoreManager::Initialize() { +void CpuManager::Initialize() { - for (std::size_t index = 0; index < cores.size(); ++index) { - cores[index] = std::make_unique(system, index); + for (std::size_t index = 0; index < core_managers.size(); ++index) { + core_managers[index] = std::make_unique(system, index); } } -void CpuCoreManager::Shutdown() { - for (auto& cpu_core : cores) { +void CpuManager::Shutdown() { + for (auto& cpu_core : core_managers) { cpu_core.reset(); } } -Cpu& CpuCoreManager::GetCore(std::size_t index) { - return *cores.at(index); +CoreManager& CpuManager::GetCoreManager(std::size_t index) { + return *core_managers.at(index); } -const Cpu& CpuCoreManager::GetCore(std::size_t index) const { - return *cores.at(index); +const CoreManager& CpuManager::GetCoreManager(std::size_t index) const { + return *core_managers.at(index); } -Cpu& CpuCoreManager::GetCurrentCore() { +CoreManager& CpuManager::GetCurrentCoreManager() { // Otherwise, use single-threaded mode active_core variable - return *cores[active_core]; + return *core_managers[active_core]; } -const Cpu& CpuCoreManager::GetCurrentCore() const { +const CoreManager& CpuManager::GetCurrentCoreManager() const { // Otherwise, use single-threaded mode active_core variable - return *cores[active_core]; + return *core_managers[active_core]; } -void CpuCoreManager::RunLoop(bool tight_loop) { +void CpuManager::RunLoop(bool tight_loop) { if (GDBStub::IsServerEnabled()) { GDBStub::HandlePacket(); @@ -77,7 +70,7 @@ void CpuCoreManager::RunLoop(bool tight_loop) { for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) { core_timing.SwitchContext(active_core); if (core_timing.CanCurrentContextRun()) { - cores[active_core]->RunLoop(tight_loop); + core_managers[active_core]->RunLoop(tight_loop); } keep_running |= core_timing.CanCurrentContextRun(); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h new file mode 100644 index 0000000000..5371d448e1 --- /dev/null +++ b/src/core/cpu_manager.h @@ -0,0 +1,52 @@ +// Copyright 2018 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include +#include +#include +#include + +namespace Core { + +class CoreManager; +class System; + +class CpuManager { +public: + explicit CpuManager(System& system); + CpuManager(const CpuManager&) = delete; + CpuManager(CpuManager&&) = delete; + + ~CpuManager(); + + CpuManager& operator=(const CpuManager&) = delete; + CpuManager& operator=(CpuManager&&) = delete; + + void Initialize(); + void Shutdown(); + + CoreManager& GetCoreManager(std::size_t index); + const CoreManager& GetCoreManager(std::size_t index) const; + + CoreManager& GetCurrentCoreManager(); + const CoreManager& GetCurrentCoreManager() const; + + std::size_t GetActiveCoreIndex() const { + return active_core; + } + + void RunLoop(bool tight_loop); + +private: + static constexpr std::size_t NUM_CPU_CORES = 4; + + std::array, NUM_CPU_CORES> core_managers; + std::size_t active_core{}; ///< Active core, only used in single thread mode + + System& system; +}; + +} // namespace Core diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp index 37cb288483..67e95999d8 100644 --- a/src/core/gdbstub/gdbstub.cpp +++ b/src/core/gdbstub/gdbstub.cpp @@ -35,7 +35,7 @@ #include "common/swap.h" #include "core/arm/arm_interface.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/gdbstub/gdbstub.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/scheduler.h" diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp index db189c8e35..2ea3dcb61a 100644 --- a/src/core/hle/kernel/address_arbiter.cpp +++ b/src/core/hle/kernel/address_arbiter.cpp @@ -8,7 +8,6 @@ #include "common/assert.h" #include "common/common_types.h" #include "core/core.h" -#include "core/core_cpu.h" #include "core/hle/kernel/address_arbiter.h" #include "core/hle/kernel/errors.h" #include "core/hle/kernel/scheduler.h" diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index d36fcd7d99..eb196a6904 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -14,7 +14,6 @@ #include "common/logging/log.h" #include "core/arm/arm_interface.h" #include "core/core.h" -#include "core/core_cpu.h" #include "core/core_timing.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index dbcdb0b881..1d99bf7a25 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -15,7 +15,7 @@ #include "common/string_util.h" #include "core/arm/exclusive_monitor.h" #include "core/core.h" -#include "core/core_cpu.h" +#include "core/core_manager.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/hle/kernel/address_arbiter.h" diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index e84e5ce0d0..278e46bad4 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -13,7 +13,6 @@ #include "common/thread_queue_list.h" #include "core/arm/arm_interface.h" #include "core/core.h" -#include "core/core_cpu.h" #include "core/core_timing.h" #include "core/core_timing_util.h" #include "core/hle/kernel/errors.h" @@ -356,7 +355,7 @@ void Thread::SetActivity(ThreadActivity value) { // Set status if not waiting if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { SetStatus(ThreadStatus::Paused); - Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); + Core::System::GetInstance().PrepareReschedule(processor_id); } } else if (status == ThreadStatus::Paused) { // Ready to reschedule diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index 745f2c4e81..aa72889df5 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -7,7 +7,6 @@ #include "common/common_types.h" #include "common/logging/log.h" #include "core/core.h" -#include "core/core_cpu.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/object.h" #include "core/hle/kernel/process.h" From a1630ab53e70420d5fa69a5d9454b2a5e2e499e3 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 26 Jan 2020 14:23:46 -0400 Subject: [PATCH 5/7] Kernel: Remove a few global instances from the kernel. --- src/core/hle/kernel/thread.cpp | 2 +- src/core/hle/kernel/wait_object.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 278e46bad4..e965b5b046 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -355,7 +355,7 @@ void Thread::SetActivity(ThreadActivity value) { // Set status if not waiting if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { SetStatus(ThreadStatus::Paused); - Core::System::GetInstance().PrepareReschedule(processor_id); + kernel.PrepareReschedule(processor_id); } } else if (status == ThreadStatus::Paused) { // Ready to reschedule diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp index aa72889df5..a0c806e8f0 100644 --- a/src/core/hle/kernel/wait_object.cpp +++ b/src/core/hle/kernel/wait_object.cpp @@ -95,7 +95,7 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr thread) { } if (resume) { thread->ResumeFromWait(); - Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID()); + kernel.PrepareReschedule(thread->GetProcessorID()); } } From de4b01f75df19c1674a2b4424b4f0d8060829844 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 26 Jan 2020 14:32:50 -0400 Subject: [PATCH 6/7] System: Correct PrepareReschedule. --- src/core/core.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/core.cpp b/src/core/core.cpp index bfe9525150..c2295f69cd 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -415,7 +415,7 @@ bool System::IsPoweredOn() const { } void System::PrepareReschedule() { - CurrentCoreManager().PrepareReschedule(); + impl->CurrentPhysicalCore().Stop(); } void System::PrepareReschedule(const u32 core_index) { From 2d1984c20c75e03ec79eeb3806b12efa1679b977 Mon Sep 17 00:00:00 2001 From: Fernando Sahmkow Date: Sun, 26 Jan 2020 16:14:18 -0400 Subject: [PATCH 7/7] System: Address Feedback --- src/core/arm/exclusive_monitor.cpp | 3 ++- src/core/arm/exclusive_monitor.h | 5 +++-- src/core/core.cpp | 4 ++-- src/core/core_manager.cpp | 7 +++---- src/core/core_manager.h | 2 -- src/core/cpu_manager.cpp | 1 - src/core/cpu_manager.h | 2 -- src/core/hle/kernel/kernel.cpp | 5 +++-- src/core/hle/kernel/kernel.h | 2 +- src/core/hle/kernel/physical_core.cpp | 11 +++++++---- src/core/hle/kernel/physical_core.h | 12 +++++++++--- 11 files changed, 30 insertions(+), 24 deletions(-) diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp index 00e6a19d55..94570e5200 100644 --- a/src/core/arm/exclusive_monitor.cpp +++ b/src/core/arm/exclusive_monitor.cpp @@ -12,7 +12,8 @@ namespace Core { ExclusiveMonitor::~ExclusiveMonitor() = default; -std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, std::size_t num_cores) { +std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, + std::size_t num_cores) { #ifdef ARCHITECTURE_x86_64 return std::make_unique(memory, num_cores); #else diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h index 18461f2963..4ef418b90c 100644 --- a/src/core/arm/exclusive_monitor.h +++ b/src/core/arm/exclusive_monitor.h @@ -1,4 +1,4 @@ -// Copyright 2020 yuzu emulator team +// Copyright 2018 yuzu emulator team // Licensed under GPLv2 or any later version // Refer to the license.txt file included. @@ -28,6 +28,7 @@ public: virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0; }; -std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, std::size_t num_cores); +std::unique_ptr MakeExclusiveMonitor(Memory::Memory& memory, + std::size_t num_cores); } // namespace Core diff --git a/src/core/core.cpp b/src/core/core.cpp index c2295f69cd..c53d122be8 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -121,8 +121,8 @@ struct System::Impl { } Kernel::PhysicalCore& CurrentPhysicalCore() { - const auto i = cpu_manager.GetActiveCoreIndex(); - return kernel.PhysicalCore(i); + const auto index = cpu_manager.GetActiveCoreIndex(); + return kernel.PhysicalCore(index); } Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) { diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp index bb03857d5b..8eacf92dda 100644 --- a/src/core/core_manager.cpp +++ b/src/core/core_manager.cpp @@ -24,10 +24,9 @@ namespace Core { CoreManager::CoreManager(System& system, std::size_t core_index) - : global_scheduler{system.GlobalScheduler()}, - physical_core{system.Kernel().PhysicalCore(core_index)}, core_timing{system.CoreTiming()}, - core_index{core_index} { -} + : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore( + core_index)}, + core_timing{system.CoreTiming()}, core_index{core_index} {} CoreManager::~CoreManager() = default; diff --git a/src/core/core_manager.h b/src/core/core_manager.h index 7bc9679c16..b14e723d7b 100644 --- a/src/core/core_manager.h +++ b/src/core/core_manager.h @@ -5,10 +5,8 @@ #pragma once #include -#include #include #include -#include #include "common/common_types.h" namespace Kernel { diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index abc8aad9ef..752534868a 100644 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -17,7 +17,6 @@ CpuManager::CpuManager(System& system) : system{system} {} CpuManager::~CpuManager() = default; void CpuManager::Initialize() { - for (std::size_t index = 0; index < core_managers.size(); ++index) { core_managers[index] = std::make_unique(system, index); } diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h index 5371d448e1..feb619e1b0 100644 --- a/src/core/cpu_manager.h +++ b/src/core/cpu_manager.h @@ -5,9 +5,7 @@ #pragma once #include -#include #include -#include namespace Core { diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 1986cf65c5..0cf3c8f70c 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -135,7 +135,8 @@ struct KernelCore::Impl { } void InitializePhysicalCores(KernelCore& kernel) { - exclusive_monitor = Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); + exclusive_monitor = + Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount()); for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) { cores.emplace_back(system, kernel, i, *exclusive_monitor); } @@ -284,7 +285,7 @@ void KernelCore::InvalidateAllInstructionCaches() { } void KernelCore::PrepareReschedule(std::size_t id) { - if (id >= 0 && id < impl->global_scheduler.CpuCoresCount()) { + if (id < impl->global_scheduler.CpuCoresCount()) { impl->cores[id].Stop(); } } diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 536068f74e..fccffaf3a9 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -13,7 +13,7 @@ namespace Core { class ExclusiveMonitor; class System; -} +} // namespace Core namespace Core::Timing { class CoreTiming; diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 7d84e3d282..896a1a87ad 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -17,18 +17,21 @@ namespace Kernel { -PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor) +PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, + Core::ExclusiveMonitor& exclusive_monitor) : core_index{id}, kernel{kernel} { #ifdef ARCHITECTURE_x86_64 - arm_interface = std::make_unique(system, exclusive_monitor, core_index); + arm_interface = std::make_shared(system, exclusive_monitor, core_index); #else - arm_interface = std::make_unique(system); + arm_interface = std::make_shared(system); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif - scheduler = std::make_unique(system, *arm_interface, core_index); + scheduler = std::make_shared(system, *arm_interface, core_index); } +PhysicalCore::~PhysicalCore() = default; + void PhysicalCore::Run() { arm_interface->Run(); arm_interface->ClearExclusiveState(); diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index a7848e030f..fbef0801fa 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -4,6 +4,9 @@ #pragma once +#include +#include + namespace Kernel { class Scheduler; } // namespace Kernel @@ -18,7 +21,10 @@ namespace Kernel { class PhysicalCore { public: - PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor); + PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id, + Core::ExclusiveMonitor& exclusive_monitor); + + ~PhysicalCore(); /// Execute current jit state void Run(); @@ -61,8 +67,8 @@ public: private: std::size_t core_index; KernelCore& kernel; - std::unique_ptr arm_interface; - std::unique_ptr scheduler; + std::shared_ptr arm_interface; + std::shared_ptr scheduler; }; } // namespace Kernel