Jelajahi Sumber

Core: Refactor CPU Management.

This commit moves ARM Interface and Scheduler handling into the kernel.
Fernando Sahmkow 6 tahun lalu
induk
melakukan
4d6a86b03f

+ 2 - 0
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

+ 22 - 13
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::seconds>(
             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() {

+ 10 - 66
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<ARM_Dynarmic>(system, exclusive_monitor, core_index);
-#else
-    arm_interface = std::make_unique<ARM_Unicorn>(system);
-    LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
-#endif
-
-    scheduler = std::make_unique<Kernel::Scheduler>(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<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(
-    [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) {
-#ifdef ARCHITECTURE_x86_64
-    return std::make_unique<DynarmicExclusiveMonitor>(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

+ 3 - 58
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<bool> 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<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
-                                                                  std::size_t num_cores);
-
 private:
     void Reschedule();
 
-    std::unique_ptr<ARM_Interface> arm_interface;
-    CpuBarrier& cpu_barrier;
     Kernel::GlobalScheduler& global_scheduler;
-    std::unique_ptr<Kernel::Scheduler> scheduler;
+    Kernel::PhysicalCore& physical_core;
     Timing::CoreTiming& core_timing;
 
     std::atomic<bool> reschedule_pending = false;

+ 1 - 62
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<CpuBarrier>();
-    exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size());
 
     for (std::size_t index = 0; index < cores.size(); ++index) {
-        cores[index] = std::make_unique<Cpu>(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<std::thread>(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<Cpu>(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

+ 3 - 13
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<ExclusiveMonitor> exclusive_monitor;
-    std::unique_ptr<CpuBarrier> barrier;
     std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cores;
-    std::array<std::unique_ptr<std::thread>, 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<std::thread::id, Cpu*> thread_to_cpu;
-
     System& system;
 };
 

+ 63 - 1
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<Core::ExclusiveMonitor> MakeExclusiveMonitor() {
+    #ifdef ARCHITECTURE_x86_64
+        return std::make_unique<Core::DynarmicExclusiveMonitor>(system.Memory(),
+                                                              global_scheduler.CpuCoresCount());
+    #else
+        // TODO(merry): Passthrough exclusive monitor
+        return nullptr;
+    #endif
+    }
+
     std::atomic<u32> next_object_id{0};
     std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
     std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
@@ -186,6 +217,9 @@ struct KernelCore::Impl {
     /// the ConnectToPort SVC.
     NamedPortTable named_ports;
 
+    std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
+    std::vector<Kernel::PhysicalCore> 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<ClientPort> port) {
     impl->named_ports.emplace(std::move(name), std::move(port));
 }

+ 17 - 0
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<ClientPort> port);
 

+ 33 - 3
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<ARM_Dynarmic>(system, exclusive_monitor, core_index);
+    arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
 #else
-    arm_interface = std::make_unique<ARM_Unicorn>(system);
+    arm_interface = std::make_unique<Core::ARM_Unicorn>(system);
     LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
 #endif
 
     scheduler = std::make_unique<Kernel::Scheduler>(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

+ 14 - 8
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> arm_interface;
-    std::unique_ptr<Kernel::Scheduler> scheduler;
     KernelCore& kernel;
-}
+    std::unique_ptr<Core::ARM_Interface> arm_interface;
+    std::unique_ptr<Kernel::Scheduler> scheduler;
+};
 
 } // namespace Kernel