kernel: unlayer CPU interrupt handling
This commit is contained in:
		| @@ -1,8 +1,6 @@ | ||||
| add_library(core STATIC | ||||
|     arm/arm_interface.h | ||||
|     arm/arm_interface.cpp | ||||
|     arm/cpu_interrupt_handler.cpp | ||||
|     arm/cpu_interrupt_handler.h | ||||
|     arm/dynarmic/arm_dynarmic_32.cpp | ||||
|     arm/dynarmic/arm_dynarmic_32.h | ||||
|     arm/dynarmic/arm_dynarmic_64.cpp | ||||
|   | ||||
| @@ -28,7 +28,6 @@ namespace Core { | ||||
| class System; | ||||
| class CPUInterruptHandler; | ||||
|  | ||||
| using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>; | ||||
| using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; | ||||
|  | ||||
| /// Generic ARMv8 CPU interface | ||||
| @@ -37,10 +36,8 @@ public: | ||||
|     YUZU_NON_COPYABLE(ARM_Interface); | ||||
|     YUZU_NON_MOVEABLE(ARM_Interface); | ||||
|  | ||||
|     explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers_, | ||||
|                            bool uses_wall_clock_) | ||||
|         : system{system_}, interrupt_handlers{interrupt_handlers_}, uses_wall_clock{ | ||||
|                                                                         uses_wall_clock_} {} | ||||
|     explicit ARM_Interface(System& system_, bool uses_wall_clock_) | ||||
|         : system{system_}, uses_wall_clock{uses_wall_clock_} {} | ||||
|     virtual ~ARM_Interface() = default; | ||||
|  | ||||
|     struct ThreadContext32 { | ||||
| @@ -182,6 +179,9 @@ public: | ||||
|     /// Signal an interrupt and ask the core to halt as soon as possible. | ||||
|     virtual void SignalInterrupt() = 0; | ||||
|  | ||||
|     /// Clear a previous interrupt. | ||||
|     virtual void ClearInterrupt() = 0; | ||||
|  | ||||
|     struct BacktraceEntry { | ||||
|         std::string module; | ||||
|         u64 address; | ||||
| @@ -209,7 +209,6 @@ public: | ||||
| protected: | ||||
|     /// System context that this ARM interface is running under. | ||||
|     System& system; | ||||
|     CPUInterrupts& interrupt_handlers; | ||||
|     const WatchpointArray* watchpoints; | ||||
|     bool uses_wall_clock; | ||||
|  | ||||
|   | ||||
| @@ -1,24 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "common/thread.h" | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {} | ||||
|  | ||||
| CPUInterruptHandler::~CPUInterruptHandler() = default; | ||||
|  | ||||
| void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) { | ||||
|     if (is_interrupted_) { | ||||
|         interrupt_event->Set(); | ||||
|     } | ||||
|     is_interrupted = is_interrupted_; | ||||
| } | ||||
|  | ||||
| void CPUInterruptHandler::AwaitInterrupt() { | ||||
|     interrupt_event->Wait(); | ||||
| } | ||||
|  | ||||
| } // namespace Core | ||||
| @@ -1,39 +0,0 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #pragma once | ||||
|  | ||||
| #include <atomic> | ||||
| #include <memory> | ||||
|  | ||||
| namespace Common { | ||||
| class Event; | ||||
| } | ||||
|  | ||||
| namespace Core { | ||||
|  | ||||
| class CPUInterruptHandler { | ||||
| public: | ||||
|     CPUInterruptHandler(); | ||||
|     ~CPUInterruptHandler(); | ||||
|  | ||||
|     CPUInterruptHandler(const CPUInterruptHandler&) = delete; | ||||
|     CPUInterruptHandler& operator=(const CPUInterruptHandler&) = delete; | ||||
|  | ||||
|     CPUInterruptHandler(CPUInterruptHandler&&) = delete; | ||||
|     CPUInterruptHandler& operator=(CPUInterruptHandler&&) = delete; | ||||
|  | ||||
|     bool IsInterrupted() const { | ||||
|         return is_interrupted; | ||||
|     } | ||||
|  | ||||
|     void SetInterrupt(bool is_interrupted); | ||||
|  | ||||
|     void AwaitInterrupt(); | ||||
|  | ||||
| private: | ||||
|     std::unique_ptr<Common::Event> interrupt_event; | ||||
|     std::atomic_bool is_interrupted{false}; | ||||
| }; | ||||
|  | ||||
| } // namespace Core | ||||
| @@ -11,7 +11,6 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "common/page_table.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_cp15.h" | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| @@ -311,11 +310,9 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() { | ||||
|     LoadContext(breakpoint_context); | ||||
| } | ||||
|  | ||||
| ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, | ||||
|                                  bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | ||||
|                                  std::size_t core_index_) | ||||
|     : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, | ||||
|       cb(std::make_unique<DynarmicCallbacks32>(*this)), | ||||
| ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, | ||||
|                                  ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) | ||||
|     : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)), | ||||
|       cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, | ||||
|       exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, | ||||
|       null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} | ||||
| @@ -394,6 +391,10 @@ void ARM_Dynarmic_32::SignalInterrupt() { | ||||
|     jit.load()->HaltExecution(break_loop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::ClearInterrupt() { | ||||
|     jit.load()->ClearHalt(break_loop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_32::ClearInstructionCache() { | ||||
|     jit.load()->ClearCache(); | ||||
| } | ||||
|   | ||||
| @@ -28,8 +28,8 @@ class System; | ||||
|  | ||||
| class ARM_Dynarmic_32 final : public ARM_Interface { | ||||
| public: | ||||
|     ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, | ||||
|                     ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); | ||||
|     ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | ||||
|                     std::size_t core_index_); | ||||
|     ~ARM_Dynarmic_32() override; | ||||
|  | ||||
|     void SetPC(u64 pc) override; | ||||
| @@ -56,6 +56,7 @@ public: | ||||
|     void LoadContext(const ThreadContext64& ctx) override {} | ||||
|  | ||||
|     void SignalInterrupt() override; | ||||
|     void ClearInterrupt() override; | ||||
|     void ClearExclusiveState() override; | ||||
|  | ||||
|     void ClearInstructionCache() override; | ||||
|   | ||||
| @@ -10,7 +10,6 @@ | ||||
| #include "common/logging/log.h" | ||||
| #include "common/page_table.h" | ||||
| #include "common/settings.h" | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_64.h" | ||||
| #include "core/arm/dynarmic/arm_exclusive_monitor.h" | ||||
| #include "core/core.h" | ||||
| @@ -371,10 +370,9 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() { | ||||
|     LoadContext(breakpoint_context); | ||||
| } | ||||
|  | ||||
| ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, | ||||
|                                  bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | ||||
|                                  std::size_t core_index_) | ||||
|     : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, | ||||
| ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, | ||||
|                                  ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_) | ||||
|     : ARM_Interface{system_, uses_wall_clock_}, | ||||
|       cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, | ||||
|       exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, | ||||
|       null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} | ||||
| @@ -461,6 +459,10 @@ void ARM_Dynarmic_64::SignalInterrupt() { | ||||
|     jit.load()->HaltExecution(break_loop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::ClearInterrupt() { | ||||
|     jit.load()->ClearHalt(break_loop); | ||||
| } | ||||
|  | ||||
| void ARM_Dynarmic_64::ClearInstructionCache() { | ||||
|     jit.load()->ClearCache(); | ||||
| } | ||||
|   | ||||
| @@ -20,14 +20,13 @@ class Memory; | ||||
| namespace Core { | ||||
|  | ||||
| class DynarmicCallbacks64; | ||||
| class CPUInterruptHandler; | ||||
| class DynarmicExclusiveMonitor; | ||||
| class System; | ||||
|  | ||||
| class ARM_Dynarmic_64 final : public ARM_Interface { | ||||
| public: | ||||
|     ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, | ||||
|                     ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); | ||||
|     ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, | ||||
|                     std::size_t core_index_); | ||||
|     ~ARM_Dynarmic_64() override; | ||||
|  | ||||
|     void SetPC(u64 pc) override; | ||||
| @@ -50,6 +49,7 @@ public: | ||||
|     void LoadContext(const ThreadContext64& ctx) override; | ||||
|  | ||||
|     void SignalInterrupt() override; | ||||
|     void ClearInterrupt() override; | ||||
|     void ClearExclusiveState() override; | ||||
|  | ||||
|     void ClearInstructionCache() override; | ||||
|   | ||||
| @@ -15,6 +15,7 @@ | ||||
| #include "core/debugger/debugger_interface.h" | ||||
| #include "core/debugger/gdbstub.h" | ||||
| #include "core/hle/kernel/global_scheduler_context.h" | ||||
| #include "core/hle/kernel/k_scheduler.h" | ||||
|  | ||||
| template <typename Readable, typename Buffer, typename Callback> | ||||
| static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { | ||||
| @@ -230,13 +231,12 @@ private: | ||||
|     } | ||||
|  | ||||
|     void PauseEmulation() { | ||||
|         Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||||
|  | ||||
|         // Put all threads to sleep on next scheduler round. | ||||
|         for (auto* thread : ThreadList()) { | ||||
|             thread->RequestSuspend(Kernel::SuspendType::Debug); | ||||
|         } | ||||
|  | ||||
|         // Signal an interrupt so that scheduler will fire. | ||||
|         system.Kernel().InterruptAllPhysicalCores(); | ||||
|     } | ||||
|  | ||||
|     void ResumeEmulation(Kernel::KThread* except = nullptr) { | ||||
| @@ -253,7 +253,8 @@ private: | ||||
|  | ||||
|     template <typename Callback> | ||||
|     void MarkResumed(Callback&& cb) { | ||||
|         std::scoped_lock lk{connection_lock}; | ||||
|         Kernel::KScopedSchedulerLock sl{system.Kernel()}; | ||||
|         std::scoped_lock cl{connection_lock}; | ||||
|         stopped = false; | ||||
|         cb(); | ||||
|     } | ||||
|   | ||||
| @@ -17,7 +17,6 @@ | ||||
| #include "common/thread.h" | ||||
| #include "common/thread_worker.h" | ||||
| #include "core/arm/arm_interface.h" | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
| #include "core/arm/exclusive_monitor.h" | ||||
| #include "core/core.h" | ||||
| #include "core/core_timing.h" | ||||
| @@ -82,7 +81,7 @@ struct KernelCore::Impl { | ||||
|  | ||||
|     void InitializeCores() { | ||||
|         for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { | ||||
|             cores[core_id].Initialize((*current_process).Is64BitProcess()); | ||||
|             cores[core_id]->Initialize((*current_process).Is64BitProcess()); | ||||
|             system.Memory().SetCurrentPageTable(*current_process, core_id); | ||||
|         } | ||||
|     } | ||||
| @@ -100,7 +99,9 @@ struct KernelCore::Impl { | ||||
|         next_user_process_id = KProcess::ProcessIDMin; | ||||
|         next_thread_id = 1; | ||||
|  | ||||
|         cores.clear(); | ||||
|         for (auto& core : cores) { | ||||
|             core = nullptr; | ||||
|         } | ||||
|  | ||||
|         global_handle_table->Finalize(); | ||||
|         global_handle_table.reset(); | ||||
| @@ -199,7 +200,7 @@ struct KernelCore::Impl { | ||||
|             const s32 core{static_cast<s32>(i)}; | ||||
|  | ||||
|             schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); | ||||
|             cores.emplace_back(i, system, *schedulers[i], interrupts); | ||||
|             cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]); | ||||
|  | ||||
|             auto* main_thread{Kernel::KThread::Create(system.Kernel())}; | ||||
|             main_thread->SetName(fmt::format("MainThread:{}", core)); | ||||
| @@ -761,7 +762,7 @@ struct KernelCore::Impl { | ||||
|     std::unordered_set<KAutoObject*> registered_in_use_objects; | ||||
|  | ||||
|     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; | ||||
|     std::vector<Kernel::PhysicalCore> cores; | ||||
|     std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores; | ||||
|  | ||||
|     // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others | ||||
|     std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; | ||||
| @@ -785,7 +786,6 @@ struct KernelCore::Impl { | ||||
|     Common::ThreadWorker service_threads_manager; | ||||
|  | ||||
|     std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; | ||||
|     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{}; | ||||
|     std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; | ||||
|  | ||||
|     bool is_multicore{}; | ||||
| @@ -874,11 +874,11 @@ const Kernel::KScheduler& KernelCore::Scheduler(std::size_t id) const { | ||||
| } | ||||
|  | ||||
| Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { | ||||
|     return impl->cores[id]; | ||||
|     return *impl->cores[id]; | ||||
| } | ||||
|  | ||||
| const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { | ||||
|     return impl->cores[id]; | ||||
|     return *impl->cores[id]; | ||||
| } | ||||
|  | ||||
| size_t KernelCore::CurrentPhysicalCoreIndex() const { | ||||
| @@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const { | ||||
| } | ||||
|  | ||||
| Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { | ||||
|     return impl->cores[CurrentPhysicalCoreIndex()]; | ||||
|     return *impl->cores[CurrentPhysicalCoreIndex()]; | ||||
| } | ||||
|  | ||||
| const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { | ||||
|     return impl->cores[CurrentPhysicalCoreIndex()]; | ||||
|     return *impl->cores[CurrentPhysicalCoreIndex()]; | ||||
| } | ||||
|  | ||||
| Kernel::KScheduler* KernelCore::CurrentScheduler() { | ||||
| @@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() { | ||||
|     return impl->schedulers[core_id].get(); | ||||
| } | ||||
|  | ||||
| std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() { | ||||
|     return impl->interrupts; | ||||
| } | ||||
|  | ||||
| const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() | ||||
|     const { | ||||
|     return impl->interrupts; | ||||
| } | ||||
|  | ||||
| Kernel::TimeManager& KernelCore::TimeManager() { | ||||
|     return impl->time_manager; | ||||
| } | ||||
| @@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { | ||||
|     return *impl->global_object_list_container; | ||||
| } | ||||
|  | ||||
| void KernelCore::InterruptAllPhysicalCores() { | ||||
|     for (auto& physical_core : impl->cores) { | ||||
|         physical_core.Interrupt(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void KernelCore::InvalidateAllInstructionCaches() { | ||||
|     for (auto& physical_core : impl->cores) { | ||||
|         physical_core.ArmInterface().ClearInstructionCache(); | ||||
|         physical_core->ArmInterface().ClearInstructionCache(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { | ||||
|     for (auto& physical_core : impl->cores) { | ||||
|         if (!physical_core.IsInitialized()) { | ||||
|         if (!physical_core->IsInitialized()) { | ||||
|             continue; | ||||
|         } | ||||
|         physical_core.ArmInterface().InvalidateCacheRange(addr, size); | ||||
|         physical_core->ArmInterface().InvalidateCacheRange(addr, size); | ||||
|     } | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -9,14 +9,12 @@ | ||||
| #include <string> | ||||
| #include <unordered_map> | ||||
| #include <vector> | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
| #include "core/hardware_properties.h" | ||||
| #include "core/hle/kernel/k_auto_object.h" | ||||
| #include "core/hle/kernel/k_slab_heap.h" | ||||
| #include "core/hle/kernel/svc_common.h" | ||||
|  | ||||
| namespace Core { | ||||
| class CPUInterruptHandler; | ||||
| class ExclusiveMonitor; | ||||
| class System; | ||||
| } // namespace Core | ||||
| @@ -183,12 +181,6 @@ public: | ||||
|  | ||||
|     const KAutoObjectWithListContainer& ObjectListContainer() const; | ||||
|  | ||||
|     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts(); | ||||
|  | ||||
|     const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const; | ||||
|  | ||||
|     void InterruptAllPhysicalCores(); | ||||
|  | ||||
|     void InvalidateAllInstructionCaches(); | ||||
|  | ||||
|     void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); | ||||
|   | ||||
| @@ -1,7 +1,6 @@ | ||||
| // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | ||||
| // SPDX-License-Identifier: GPL-2.0-or-later | ||||
|  | ||||
| #include "core/arm/cpu_interrupt_handler.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_32.h" | ||||
| #include "core/arm/dynarmic/arm_dynarmic_64.h" | ||||
| #include "core/core.h" | ||||
| @@ -11,16 +10,14 @@ | ||||
|  | ||||
| namespace Kernel { | ||||
|  | ||||
| PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, | ||||
|                            Core::CPUInterrupts& interrupts_) | ||||
|     : core_index{core_index_}, system{system_}, scheduler{scheduler_}, | ||||
|       interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} { | ||||
| PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_) | ||||
|     : core_index{core_index_}, system{system_}, scheduler{scheduler_} { | ||||
| #ifdef ARCHITECTURE_x86_64 | ||||
|     // 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(); | ||||
|     arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( | ||||
|         system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | ||||
|         system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | ||||
| #else | ||||
| #error Platform not supported yet. | ||||
| #endif | ||||
| @@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) { | ||||
|     if (!is_64_bit) { | ||||
|         // We already initialized a 64-bit core, replace with a 32-bit one. | ||||
|         arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( | ||||
|             system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | ||||
|             system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); | ||||
|     } | ||||
| #else | ||||
| #error Platform not supported yet. | ||||
| @@ -47,24 +44,26 @@ void PhysicalCore::Run() { | ||||
| } | ||||
|  | ||||
| void PhysicalCore::Idle() { | ||||
|     interrupts[core_index].AwaitInterrupt(); | ||||
|     std::unique_lock lk{guard}; | ||||
|     on_interrupt.wait(lk, [this] { return is_interrupted; }); | ||||
| } | ||||
|  | ||||
| bool PhysicalCore::IsInterrupted() const { | ||||
|     return interrupts[core_index].IsInterrupted(); | ||||
|     return is_interrupted; | ||||
| } | ||||
|  | ||||
| void PhysicalCore::Interrupt() { | ||||
|     guard->lock(); | ||||
|     interrupts[core_index].SetInterrupt(true); | ||||
|     std::unique_lock lk{guard}; | ||||
|     is_interrupted = true; | ||||
|     arm_interface->SignalInterrupt(); | ||||
|     guard->unlock(); | ||||
|     on_interrupt.notify_all(); | ||||
| } | ||||
|  | ||||
| void PhysicalCore::ClearInterrupt() { | ||||
|     guard->lock(); | ||||
|     interrupts[core_index].SetInterrupt(false); | ||||
|     guard->unlock(); | ||||
|     std::unique_lock lk{guard}; | ||||
|     is_interrupted = false; | ||||
|     arm_interface->ClearInterrupt(); | ||||
|     on_interrupt.notify_all(); | ||||
| } | ||||
|  | ||||
| } // namespace Kernel | ||||
|   | ||||
| @@ -14,7 +14,6 @@ class KScheduler; | ||||
| } // namespace Kernel | ||||
|  | ||||
| namespace Core { | ||||
| class CPUInterruptHandler; | ||||
| class ExclusiveMonitor; | ||||
| class System; | ||||
| } // namespace Core | ||||
| @@ -23,15 +22,11 @@ namespace Kernel { | ||||
|  | ||||
| class PhysicalCore { | ||||
| public: | ||||
|     PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, | ||||
|                  Core::CPUInterrupts& interrupts_); | ||||
|     PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_); | ||||
|     ~PhysicalCore(); | ||||
|  | ||||
|     PhysicalCore(const PhysicalCore&) = delete; | ||||
|     PhysicalCore& operator=(const PhysicalCore&) = delete; | ||||
|  | ||||
|     PhysicalCore(PhysicalCore&&) = default; | ||||
|     PhysicalCore& operator=(PhysicalCore&&) = delete; | ||||
|     YUZU_NON_COPYABLE(PhysicalCore); | ||||
|     YUZU_NON_MOVEABLE(PhysicalCore); | ||||
|  | ||||
|     /// Initialize the core for the specified parameters. | ||||
|     void Initialize(bool is_64_bit); | ||||
| @@ -86,9 +81,11 @@ private: | ||||
|     const std::size_t core_index; | ||||
|     Core::System& system; | ||||
|     Kernel::KScheduler& scheduler; | ||||
|     Core::CPUInterrupts& interrupts; | ||||
|     std::unique_ptr<std::mutex> guard; | ||||
|  | ||||
|     std::mutex guard; | ||||
|     std::condition_variable on_interrupt; | ||||
|     std::unique_ptr<Core::ARM_Interface> arm_interface; | ||||
|     bool is_interrupted; | ||||
| }; | ||||
|  | ||||
| } // namespace Kernel | ||||
|   | ||||
		Reference in New Issue
	
	Block a user