Merge pull request #8637 from liamwhite/bad-interrupts

kernel: unlayer CPU interrupt handling
This commit is contained in:
bunnei 2022-08-07 17:48:55 -07:00 committed by GitHub
commit 01bb5d5c4d
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
13 changed files with 64 additions and 152 deletions

View file

@ -6,8 +6,6 @@ add_library(core STATIC
announce_multiplayer_session.h announce_multiplayer_session.h
arm/arm_interface.h arm/arm_interface.h
arm/arm_interface.cpp 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.cpp
arm/dynarmic/arm_dynarmic_32.h arm/dynarmic/arm_dynarmic_32.h
arm/dynarmic/arm_dynarmic_64.cpp arm/dynarmic/arm_dynarmic_64.cpp

View file

@ -27,7 +27,6 @@ namespace Core {
class System; class System;
class CPUInterruptHandler; class CPUInterruptHandler;
using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>;
using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
/// Generic ARMv8 CPU interface /// Generic ARMv8 CPU interface
@ -36,10 +35,8 @@ public:
YUZU_NON_COPYABLE(ARM_Interface); YUZU_NON_COPYABLE(ARM_Interface);
YUZU_NON_MOVEABLE(ARM_Interface); YUZU_NON_MOVEABLE(ARM_Interface);
explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers_, explicit ARM_Interface(System& system_, bool uses_wall_clock_)
bool uses_wall_clock_) : system{system_}, uses_wall_clock{uses_wall_clock_} {}
: system{system_}, interrupt_handlers{interrupt_handlers_}, uses_wall_clock{
uses_wall_clock_} {}
virtual ~ARM_Interface() = default; virtual ~ARM_Interface() = default;
struct ThreadContext32 { struct ThreadContext32 {
@ -181,6 +178,9 @@ public:
/// Signal an interrupt and ask the core to halt as soon as possible. /// Signal an interrupt and ask the core to halt as soon as possible.
virtual void SignalInterrupt() = 0; virtual void SignalInterrupt() = 0;
/// Clear a previous interrupt.
virtual void ClearInterrupt() = 0;
struct BacktraceEntry { struct BacktraceEntry {
std::string module; std::string module;
u64 address; u64 address;
@ -208,7 +208,6 @@ public:
protected: protected:
/// System context that this ARM interface is running under. /// System context that this ARM interface is running under.
System& system; System& system;
CPUInterrupts& interrupt_handlers;
const WatchpointArray* watchpoints; const WatchpointArray* watchpoints;
bool uses_wall_clock; bool uses_wall_clock;

View file

@ -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

View file

@ -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

View file

@ -11,7 +11,6 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/page_table.h" #include "common/page_table.h"
#include "common/settings.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_32.h"
#include "core/arm/dynarmic/arm_dynarmic_cp15.h" #include "core/arm/dynarmic/arm_dynarmic_cp15.h"
#include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/arm/dynarmic/arm_exclusive_monitor.h"
@ -318,11 +317,9 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() {
LoadContext(breakpoint_context); LoadContext(breakpoint_context);
} }
ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
std::size_t core_index_) : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
: ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
cb(std::make_unique<DynarmicCallbacks32>(*this)),
cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
@ -401,6 +398,10 @@ void ARM_Dynarmic_32::SignalInterrupt() {
jit.load()->HaltExecution(break_loop); jit.load()->HaltExecution(break_loop);
} }
void ARM_Dynarmic_32::ClearInterrupt() {
jit.load()->ClearHalt(break_loop);
}
void ARM_Dynarmic_32::ClearInstructionCache() { void ARM_Dynarmic_32::ClearInstructionCache() {
jit.load()->ClearCache(); jit.load()->ClearCache();
} }

View file

@ -28,8 +28,8 @@ class System;
class ARM_Dynarmic_32 final : public ARM_Interface { class ARM_Dynarmic_32 final : public ARM_Interface {
public: public:
ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); std::size_t core_index_);
~ARM_Dynarmic_32() override; ~ARM_Dynarmic_32() override;
void SetPC(u64 pc) override; void SetPC(u64 pc) override;
@ -56,6 +56,7 @@ public:
void LoadContext(const ThreadContext64& ctx) override {} void LoadContext(const ThreadContext64& ctx) override {}
void SignalInterrupt() override; void SignalInterrupt() override;
void ClearInterrupt() override;
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;

View file

@ -10,7 +10,6 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/page_table.h" #include "common/page_table.h"
#include "common/settings.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_dynarmic_64.h"
#include "core/arm/dynarmic/arm_exclusive_monitor.h" #include "core/arm/dynarmic/arm_exclusive_monitor.h"
#include "core/core.h" #include "core/core.h"
@ -378,10 +377,9 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() {
LoadContext(breakpoint_context); LoadContext(breakpoint_context);
} }
ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
std::size_t core_index_) : ARM_Interface{system_, uses_wall_clock_},
: ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
@ -468,6 +466,10 @@ void ARM_Dynarmic_64::SignalInterrupt() {
jit.load()->HaltExecution(break_loop); jit.load()->HaltExecution(break_loop);
} }
void ARM_Dynarmic_64::ClearInterrupt() {
jit.load()->ClearHalt(break_loop);
}
void ARM_Dynarmic_64::ClearInstructionCache() { void ARM_Dynarmic_64::ClearInstructionCache() {
jit.load()->ClearCache(); jit.load()->ClearCache();
} }

View file

@ -20,14 +20,13 @@ class Memory;
namespace Core { namespace Core {
class DynarmicCallbacks64; class DynarmicCallbacks64;
class CPUInterruptHandler;
class DynarmicExclusiveMonitor; class DynarmicExclusiveMonitor;
class System; class System;
class ARM_Dynarmic_64 final : public ARM_Interface { class ARM_Dynarmic_64 final : public ARM_Interface {
public: public:
ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); std::size_t core_index_);
~ARM_Dynarmic_64() override; ~ARM_Dynarmic_64() override;
void SetPC(u64 pc) override; void SetPC(u64 pc) override;
@ -50,6 +49,7 @@ public:
void LoadContext(const ThreadContext64& ctx) override; void LoadContext(const ThreadContext64& ctx) override;
void SignalInterrupt() override; void SignalInterrupt() override;
void ClearInterrupt() override;
void ClearExclusiveState() override; void ClearExclusiveState() override;
void ClearInstructionCache() override; void ClearInstructionCache() override;

View file

@ -15,6 +15,7 @@
#include "core/debugger/debugger_interface.h" #include "core/debugger/debugger_interface.h"
#include "core/debugger/gdbstub.h" #include "core/debugger/gdbstub.h"
#include "core/hle/kernel/global_scheduler_context.h" #include "core/hle/kernel/global_scheduler_context.h"
#include "core/hle/kernel/k_scheduler.h"
template <typename Readable, typename Buffer, typename Callback> template <typename Readable, typename Buffer, typename Callback>
static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
@ -230,13 +231,12 @@ private:
} }
void PauseEmulation() { void PauseEmulation() {
Kernel::KScopedSchedulerLock sl{system.Kernel()};
// Put all threads to sleep on next scheduler round. // Put all threads to sleep on next scheduler round.
for (auto* thread : ThreadList()) { for (auto* thread : ThreadList()) {
thread->RequestSuspend(Kernel::SuspendType::Debug); thread->RequestSuspend(Kernel::SuspendType::Debug);
} }
// Signal an interrupt so that scheduler will fire.
system.Kernel().InterruptAllPhysicalCores();
} }
void ResumeEmulation(Kernel::KThread* except = nullptr) { void ResumeEmulation(Kernel::KThread* except = nullptr) {
@ -253,7 +253,8 @@ private:
template <typename Callback> template <typename Callback>
void MarkResumed(Callback&& cb) { void MarkResumed(Callback&& cb) {
std::scoped_lock lk{connection_lock}; Kernel::KScopedSchedulerLock sl{system.Kernel()};
std::scoped_lock cl{connection_lock};
stopped = false; stopped = false;
cb(); cb();
} }

View file

@ -17,7 +17,6 @@
#include "common/thread.h" #include "common/thread.h"
#include "common/thread_worker.h" #include "common/thread_worker.h"
#include "core/arm/arm_interface.h" #include "core/arm/arm_interface.h"
#include "core/arm/cpu_interrupt_handler.h"
#include "core/arm/exclusive_monitor.h" #include "core/arm/exclusive_monitor.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
@ -82,7 +81,7 @@ struct KernelCore::Impl {
void InitializeCores() { void InitializeCores() {
for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 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); system.Memory().SetCurrentPageTable(*current_process, core_id);
} }
} }
@ -100,7 +99,9 @@ struct KernelCore::Impl {
next_user_process_id = KProcess::ProcessIDMin; next_user_process_id = KProcess::ProcessIDMin;
next_thread_id = 1; next_thread_id = 1;
cores.clear(); for (auto& core : cores) {
core = nullptr;
}
global_handle_table->Finalize(); global_handle_table->Finalize();
global_handle_table.reset(); global_handle_table.reset();
@ -199,7 +200,7 @@ struct KernelCore::Impl {
const s32 core{static_cast<s32>(i)}; const s32 core{static_cast<s32>(i)};
schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); 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())}; auto* main_thread{Kernel::KThread::Create(system.Kernel())};
main_thread->SetName(fmt::format("MainThread:{}", core)); main_thread->SetName(fmt::format("MainThread:{}", core));
@ -761,7 +762,7 @@ struct KernelCore::Impl {
std::unordered_set<KAutoObject*> registered_in_use_objects; std::unordered_set<KAutoObject*> registered_in_use_objects;
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 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 // 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}; std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
@ -785,7 +786,6 @@ struct KernelCore::Impl {
Common::ThreadWorker service_threads_manager; Common::ThreadWorker service_threads_manager;
std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; 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{}; std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
bool is_multicore{}; 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) { 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 { const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
return impl->cores[id]; return *impl->cores[id];
} }
size_t KernelCore::CurrentPhysicalCoreIndex() const { size_t KernelCore::CurrentPhysicalCoreIndex() const {
@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const {
} }
Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
return impl->cores[CurrentPhysicalCoreIndex()]; return *impl->cores[CurrentPhysicalCoreIndex()];
} }
const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
return impl->cores[CurrentPhysicalCoreIndex()]; return *impl->cores[CurrentPhysicalCoreIndex()];
} }
Kernel::KScheduler* KernelCore::CurrentScheduler() { Kernel::KScheduler* KernelCore::CurrentScheduler() {
@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
return impl->schedulers[core_id].get(); 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() { Kernel::TimeManager& KernelCore::TimeManager() {
return impl->time_manager; return impl->time_manager;
} }
@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
return *impl->global_object_list_container; return *impl->global_object_list_container;
} }
void KernelCore::InterruptAllPhysicalCores() {
for (auto& physical_core : impl->cores) {
physical_core.Interrupt();
}
}
void KernelCore::InvalidateAllInstructionCaches() { void KernelCore::InvalidateAllInstructionCaches() {
for (auto& physical_core : impl->cores) { for (auto& physical_core : impl->cores) {
physical_core.ArmInterface().ClearInstructionCache(); physical_core->ArmInterface().ClearInstructionCache();
} }
} }
void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
for (auto& physical_core : impl->cores) { for (auto& physical_core : impl->cores) {
if (!physical_core.IsInitialized()) { if (!physical_core->IsInitialized()) {
continue; continue;
} }
physical_core.ArmInterface().InvalidateCacheRange(addr, size); physical_core->ArmInterface().InvalidateCacheRange(addr, size);
} }
} }

View file

@ -9,14 +9,12 @@
#include <string> #include <string>
#include <unordered_map> #include <unordered_map>
#include <vector> #include <vector>
#include "core/arm/cpu_interrupt_handler.h"
#include "core/hardware_properties.h" #include "core/hardware_properties.h"
#include "core/hle/kernel/k_auto_object.h" #include "core/hle/kernel/k_auto_object.h"
#include "core/hle/kernel/k_slab_heap.h" #include "core/hle/kernel/k_slab_heap.h"
#include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_common.h"
namespace Core { namespace Core {
class CPUInterruptHandler;
class ExclusiveMonitor; class ExclusiveMonitor;
class System; class System;
} // namespace Core } // namespace Core
@ -183,12 +181,6 @@ public:
const KAutoObjectWithListContainer& ObjectListContainer() const; 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 InvalidateAllInstructionCaches();
void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);

View file

@ -1,7 +1,6 @@
// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later // 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_32.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/core.h" #include "core/core.h"
@ -11,16 +10,14 @@
namespace Kernel { namespace Kernel {
PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_)
Core::CPUInterrupts& interrupts_) : core_index{core_index_}, system{system_}, scheduler{scheduler_} {
: core_index{core_index_}, system{system_}, scheduler{scheduler_},
interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} {
#ifdef ARCHITECTURE_x86_64 #ifdef ARCHITECTURE_x86_64
// TODO(bunnei): Initialization relies on a core being available. We may later replace this with // 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. // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( 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 #else
#error Platform not supported yet. #error Platform not supported yet.
#endif #endif
@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
if (!is_64_bit) { if (!is_64_bit) {
// We already initialized a 64-bit core, replace with a 32-bit one. // We already initialized a 64-bit core, replace with a 32-bit one.
arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( 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 #else
#error Platform not supported yet. #error Platform not supported yet.
@ -47,24 +44,26 @@ void PhysicalCore::Run() {
} }
void PhysicalCore::Idle() { void PhysicalCore::Idle() {
interrupts[core_index].AwaitInterrupt(); std::unique_lock lk{guard};
on_interrupt.wait(lk, [this] { return is_interrupted; });
} }
bool PhysicalCore::IsInterrupted() const { bool PhysicalCore::IsInterrupted() const {
return interrupts[core_index].IsInterrupted(); return is_interrupted;
} }
void PhysicalCore::Interrupt() { void PhysicalCore::Interrupt() {
guard->lock(); std::unique_lock lk{guard};
interrupts[core_index].SetInterrupt(true); is_interrupted = true;
arm_interface->SignalInterrupt(); arm_interface->SignalInterrupt();
guard->unlock(); on_interrupt.notify_all();
} }
void PhysicalCore::ClearInterrupt() { void PhysicalCore::ClearInterrupt() {
guard->lock(); std::unique_lock lk{guard};
interrupts[core_index].SetInterrupt(false); is_interrupted = false;
guard->unlock(); arm_interface->ClearInterrupt();
on_interrupt.notify_all();
} }
} // namespace Kernel } // namespace Kernel

View file

@ -14,7 +14,6 @@ class KScheduler;
} // namespace Kernel } // namespace Kernel
namespace Core { namespace Core {
class CPUInterruptHandler;
class ExclusiveMonitor; class ExclusiveMonitor;
class System; class System;
} // namespace Core } // namespace Core
@ -23,15 +22,11 @@ namespace Kernel {
class PhysicalCore { class PhysicalCore {
public: public:
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
Core::CPUInterrupts& interrupts_);
~PhysicalCore(); ~PhysicalCore();
PhysicalCore(const PhysicalCore&) = delete; YUZU_NON_COPYABLE(PhysicalCore);
PhysicalCore& operator=(const PhysicalCore&) = delete; YUZU_NON_MOVEABLE(PhysicalCore);
PhysicalCore(PhysicalCore&&) = default;
PhysicalCore& operator=(PhysicalCore&&) = delete;
/// Initialize the core for the specified parameters. /// Initialize the core for the specified parameters.
void Initialize(bool is_64_bit); void Initialize(bool is_64_bit);
@ -86,9 +81,11 @@ private:
const std::size_t core_index; const std::size_t core_index;
Core::System& system; Core::System& system;
Kernel::KScheduler& scheduler; 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; std::unique_ptr<Core::ARM_Interface> arm_interface;
bool is_interrupted;
}; };
} // namespace Kernel } // namespace Kernel