summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2022-08-07 17:48:55 -0700
committerGravatar GitHub2022-08-07 17:48:55 -0700
commit01bb5d5c4d10424145739e4dd50c0a92547ca240 (patch)
tree403f5ae1f6ea1d4555a40dbea0f2c44183292aba
parentMerge pull request #8240 from liamwhite/count-cycles (diff)
parentkernel: unlayer CPU interrupt handling (diff)
downloadyuzu-01bb5d5c4d10424145739e4dd50c0a92547ca240.tar.gz
yuzu-01bb5d5c4d10424145739e4dd50c0a92547ca240.tar.xz
yuzu-01bb5d5c4d10424145739e4dd50c0a92547ca240.zip
Merge pull request #8637 from liamwhite/bad-interrupts
kernel: unlayer CPU interrupt handling
Diffstat (limited to '')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/arm_interface.h11
-rw-r--r--src/core/arm/cpu_interrupt_handler.cpp24
-rw-r--r--src/core/arm/cpu_interrupt_handler.h39
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp13
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h5
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp12
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h6
-rw-r--r--src/core/debugger/debugger.cpp9
-rw-r--r--src/core/hle/kernel/kernel.cpp41
-rw-r--r--src/core/hle/kernel/kernel.h8
-rw-r--r--src/core/hle/kernel/physical_core.cpp29
-rw-r--r--src/core/hle/kernel/physical_core.h17
13 files changed, 64 insertions, 152 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 9dbe5bdca..052357be4 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -6,8 +6,6 @@ add_library(core STATIC
6 announce_multiplayer_session.h 6 announce_multiplayer_session.h
7 arm/arm_interface.h 7 arm/arm_interface.h
8 arm/arm_interface.cpp 8 arm/arm_interface.cpp
9 arm/cpu_interrupt_handler.cpp
10 arm/cpu_interrupt_handler.h
11 arm/dynarmic/arm_dynarmic_32.cpp 9 arm/dynarmic/arm_dynarmic_32.cpp
12 arm/dynarmic/arm_dynarmic_32.h 10 arm/dynarmic/arm_dynarmic_32.h
13 arm/dynarmic/arm_dynarmic_64.cpp 11 arm/dynarmic/arm_dynarmic_64.cpp
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index 73f259525..7d62d030e 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -27,7 +27,6 @@ namespace Core {
27class System; 27class System;
28class CPUInterruptHandler; 28class CPUInterruptHandler;
29 29
30using CPUInterrupts = std::array<CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>;
31using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>; 30using WatchpointArray = std::array<Kernel::DebugWatchpoint, Core::Hardware::NUM_WATCHPOINTS>;
32 31
33/// Generic ARMv8 CPU interface 32/// Generic ARMv8 CPU interface
@@ -36,10 +35,8 @@ public:
36 YUZU_NON_COPYABLE(ARM_Interface); 35 YUZU_NON_COPYABLE(ARM_Interface);
37 YUZU_NON_MOVEABLE(ARM_Interface); 36 YUZU_NON_MOVEABLE(ARM_Interface);
38 37
39 explicit ARM_Interface(System& system_, CPUInterrupts& interrupt_handlers_, 38 explicit ARM_Interface(System& system_, bool uses_wall_clock_)
40 bool uses_wall_clock_) 39 : system{system_}, uses_wall_clock{uses_wall_clock_} {}
41 : system{system_}, interrupt_handlers{interrupt_handlers_}, uses_wall_clock{
42 uses_wall_clock_} {}
43 virtual ~ARM_Interface() = default; 40 virtual ~ARM_Interface() = default;
44 41
45 struct ThreadContext32 { 42 struct ThreadContext32 {
@@ -181,6 +178,9 @@ public:
181 /// Signal an interrupt and ask the core to halt as soon as possible. 178 /// Signal an interrupt and ask the core to halt as soon as possible.
182 virtual void SignalInterrupt() = 0; 179 virtual void SignalInterrupt() = 0;
183 180
181 /// Clear a previous interrupt.
182 virtual void ClearInterrupt() = 0;
183
184 struct BacktraceEntry { 184 struct BacktraceEntry {
185 std::string module; 185 std::string module;
186 u64 address; 186 u64 address;
@@ -208,7 +208,6 @@ public:
208protected: 208protected:
209 /// System context that this ARM interface is running under. 209 /// System context that this ARM interface is running under.
210 System& system; 210 System& system;
211 CPUInterrupts& interrupt_handlers;
212 const WatchpointArray* watchpoints; 211 const WatchpointArray* watchpoints;
213 bool uses_wall_clock; 212 bool uses_wall_clock;
214 213
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp
deleted file mode 100644
index 77b6194d7..000000000
--- a/src/core/arm/cpu_interrupt_handler.cpp
+++ /dev/null
@@ -1,24 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#include "common/thread.h"
5#include "core/arm/cpu_interrupt_handler.h"
6
7namespace Core {
8
9CPUInterruptHandler::CPUInterruptHandler() : interrupt_event{std::make_unique<Common::Event>()} {}
10
11CPUInterruptHandler::~CPUInterruptHandler() = default;
12
13void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) {
14 if (is_interrupted_) {
15 interrupt_event->Set();
16 }
17 is_interrupted = is_interrupted_;
18}
19
20void CPUInterruptHandler::AwaitInterrupt() {
21 interrupt_event->Wait();
22}
23
24} // namespace Core
diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h
deleted file mode 100644
index 286e12e53..000000000
--- a/src/core/arm/cpu_interrupt_handler.h
+++ /dev/null
@@ -1,39 +0,0 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later
3
4#pragma once
5
6#include <atomic>
7#include <memory>
8
9namespace Common {
10class Event;
11}
12
13namespace Core {
14
15class CPUInterruptHandler {
16public:
17 CPUInterruptHandler();
18 ~CPUInterruptHandler();
19
20 CPUInterruptHandler(const CPUInterruptHandler&) = delete;
21 CPUInterruptHandler& operator=(const CPUInterruptHandler&) = delete;
22
23 CPUInterruptHandler(CPUInterruptHandler&&) = delete;
24 CPUInterruptHandler& operator=(CPUInterruptHandler&&) = delete;
25
26 bool IsInterrupted() const {
27 return is_interrupted;
28 }
29
30 void SetInterrupt(bool is_interrupted);
31
32 void AwaitInterrupt();
33
34private:
35 std::unique_ptr<Common::Event> interrupt_event;
36 std::atomic_bool is_interrupted{false};
37};
38
39} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 99fab6384..2e0e16b6e 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -11,7 +11,6 @@
11#include "common/logging/log.h" 11#include "common/logging/log.h"
12#include "common/page_table.h" 12#include "common/page_table.h"
13#include "common/settings.h" 13#include "common/settings.h"
14#include "core/arm/cpu_interrupt_handler.h"
15#include "core/arm/dynarmic/arm_dynarmic_32.h" 14#include "core/arm/dynarmic/arm_dynarmic_32.h"
16#include "core/arm/dynarmic/arm_dynarmic_cp15.h" 15#include "core/arm/dynarmic/arm_dynarmic_cp15.h"
17#include "core/arm/dynarmic/arm_exclusive_monitor.h" 16#include "core/arm/dynarmic/arm_exclusive_monitor.h"
@@ -318,11 +317,9 @@ void ARM_Dynarmic_32::RewindBreakpointInstruction() {
318 LoadContext(breakpoint_context); 317 LoadContext(breakpoint_context);
319} 318}
320 319
321ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, 320ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, bool uses_wall_clock_,
322 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 321 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
323 std::size_t core_index_) 322 : ARM_Interface{system_, uses_wall_clock_}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
324 : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
325 cb(std::make_unique<DynarmicCallbacks32>(*this)),
326 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, 323 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
327 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 324 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
328 null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {} 325 null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
@@ -401,6 +398,10 @@ void ARM_Dynarmic_32::SignalInterrupt() {
401 jit.load()->HaltExecution(break_loop); 398 jit.load()->HaltExecution(break_loop);
402} 399}
403 400
401void ARM_Dynarmic_32::ClearInterrupt() {
402 jit.load()->ClearHalt(break_loop);
403}
404
404void ARM_Dynarmic_32::ClearInstructionCache() { 405void ARM_Dynarmic_32::ClearInstructionCache() {
405 jit.load()->ClearCache(); 406 jit.load()->ClearCache();
406} 407}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 346e9abf8..d24ba2289 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -28,8 +28,8 @@ class System;
28 28
29class ARM_Dynarmic_32 final : public ARM_Interface { 29class ARM_Dynarmic_32 final : public ARM_Interface {
30public: 30public:
31 ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, 31 ARM_Dynarmic_32(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
32 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); 32 std::size_t core_index_);
33 ~ARM_Dynarmic_32() override; 33 ~ARM_Dynarmic_32() override;
34 34
35 void SetPC(u64 pc) override; 35 void SetPC(u64 pc) override;
@@ -56,6 +56,7 @@ public:
56 void LoadContext(const ThreadContext64& ctx) override {} 56 void LoadContext(const ThreadContext64& ctx) override {}
57 57
58 void SignalInterrupt() override; 58 void SignalInterrupt() override;
59 void ClearInterrupt() override;
59 void ClearExclusiveState() override; 60 void ClearExclusiveState() override;
60 61
61 void ClearInstructionCache() override; 62 void ClearInstructionCache() override;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index a91b587ce..bf971b7dc 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -10,7 +10,6 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/page_table.h" 11#include "common/page_table.h"
12#include "common/settings.h" 12#include "common/settings.h"
13#include "core/arm/cpu_interrupt_handler.h"
14#include "core/arm/dynarmic/arm_dynarmic_64.h" 13#include "core/arm/dynarmic/arm_dynarmic_64.h"
15#include "core/arm/dynarmic/arm_exclusive_monitor.h" 14#include "core/arm/dynarmic/arm_exclusive_monitor.h"
16#include "core/core.h" 15#include "core/core.h"
@@ -378,10 +377,9 @@ void ARM_Dynarmic_64::RewindBreakpointInstruction() {
378 LoadContext(breakpoint_context); 377 LoadContext(breakpoint_context);
379} 378}
380 379
381ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, 380ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, bool uses_wall_clock_,
382 bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_, 381 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_)
383 std::size_t core_index_) 382 : ARM_Interface{system_, uses_wall_clock_},
384 : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
385 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, 383 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
386 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 384 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
387 null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {} 385 null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
@@ -468,6 +466,10 @@ void ARM_Dynarmic_64::SignalInterrupt() {
468 jit.load()->HaltExecution(break_loop); 466 jit.load()->HaltExecution(break_loop);
469} 467}
470 468
469void ARM_Dynarmic_64::ClearInterrupt() {
470 jit.load()->ClearHalt(break_loop);
471}
472
471void ARM_Dynarmic_64::ClearInstructionCache() { 473void ARM_Dynarmic_64::ClearInstructionCache() {
472 jit.load()->ClearCache(); 474 jit.load()->ClearCache();
473} 475}
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index c77a83ad7..ed1a5eb96 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -20,14 +20,13 @@ class Memory;
20namespace Core { 20namespace Core {
21 21
22class DynarmicCallbacks64; 22class DynarmicCallbacks64;
23class CPUInterruptHandler;
24class DynarmicExclusiveMonitor; 23class DynarmicExclusiveMonitor;
25class System; 24class System;
26 25
27class ARM_Dynarmic_64 final : public ARM_Interface { 26class ARM_Dynarmic_64 final : public ARM_Interface {
28public: 27public:
29 ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, bool uses_wall_clock_, 28 ARM_Dynarmic_64(System& system_, bool uses_wall_clock_, ExclusiveMonitor& exclusive_monitor_,
30 ExclusiveMonitor& exclusive_monitor_, std::size_t core_index_); 29 std::size_t core_index_);
31 ~ARM_Dynarmic_64() override; 30 ~ARM_Dynarmic_64() override;
32 31
33 void SetPC(u64 pc) override; 32 void SetPC(u64 pc) override;
@@ -50,6 +49,7 @@ public:
50 void LoadContext(const ThreadContext64& ctx) override; 49 void LoadContext(const ThreadContext64& ctx) override;
51 50
52 void SignalInterrupt() override; 51 void SignalInterrupt() override;
52 void ClearInterrupt() override;
53 void ClearExclusiveState() override; 53 void ClearExclusiveState() override;
54 54
55 void ClearInstructionCache() override; 55 void ClearInstructionCache() override;
diff --git a/src/core/debugger/debugger.cpp b/src/core/debugger/debugger.cpp
index ac64d2f9d..e42bdd17d 100644
--- a/src/core/debugger/debugger.cpp
+++ b/src/core/debugger/debugger.cpp
@@ -15,6 +15,7 @@
15#include "core/debugger/debugger_interface.h" 15#include "core/debugger/debugger_interface.h"
16#include "core/debugger/gdbstub.h" 16#include "core/debugger/gdbstub.h"
17#include "core/hle/kernel/global_scheduler_context.h" 17#include "core/hle/kernel/global_scheduler_context.h"
18#include "core/hle/kernel/k_scheduler.h"
18 19
19template <typename Readable, typename Buffer, typename Callback> 20template <typename Readable, typename Buffer, typename Callback>
20static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) { 21static void AsyncReceiveInto(Readable& r, Buffer& buffer, Callback&& c) {
@@ -230,13 +231,12 @@ private:
230 } 231 }
231 232
232 void PauseEmulation() { 233 void PauseEmulation() {
234 Kernel::KScopedSchedulerLock sl{system.Kernel()};
235
233 // Put all threads to sleep on next scheduler round. 236 // Put all threads to sleep on next scheduler round.
234 for (auto* thread : ThreadList()) { 237 for (auto* thread : ThreadList()) {
235 thread->RequestSuspend(Kernel::SuspendType::Debug); 238 thread->RequestSuspend(Kernel::SuspendType::Debug);
236 } 239 }
237
238 // Signal an interrupt so that scheduler will fire.
239 system.Kernel().InterruptAllPhysicalCores();
240 } 240 }
241 241
242 void ResumeEmulation(Kernel::KThread* except = nullptr) { 242 void ResumeEmulation(Kernel::KThread* except = nullptr) {
@@ -253,7 +253,8 @@ private:
253 253
254 template <typename Callback> 254 template <typename Callback>
255 void MarkResumed(Callback&& cb) { 255 void MarkResumed(Callback&& cb) {
256 std::scoped_lock lk{connection_lock}; 256 Kernel::KScopedSchedulerLock sl{system.Kernel()};
257 std::scoped_lock cl{connection_lock};
257 stopped = false; 258 stopped = false;
258 cb(); 259 cb();
259 } 260 }
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index f4072e1c3..ce7fa8275 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -17,7 +17,6 @@
17#include "common/thread.h" 17#include "common/thread.h"
18#include "common/thread_worker.h" 18#include "common/thread_worker.h"
19#include "core/arm/arm_interface.h" 19#include "core/arm/arm_interface.h"
20#include "core/arm/cpu_interrupt_handler.h"
21#include "core/arm/exclusive_monitor.h" 20#include "core/arm/exclusive_monitor.h"
22#include "core/core.h" 21#include "core/core.h"
23#include "core/core_timing.h" 22#include "core/core_timing.h"
@@ -82,7 +81,7 @@ struct KernelCore::Impl {
82 81
83 void InitializeCores() { 82 void InitializeCores() {
84 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { 83 for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) {
85 cores[core_id].Initialize((*current_process).Is64BitProcess()); 84 cores[core_id]->Initialize((*current_process).Is64BitProcess());
86 system.Memory().SetCurrentPageTable(*current_process, core_id); 85 system.Memory().SetCurrentPageTable(*current_process, core_id);
87 } 86 }
88 } 87 }
@@ -100,7 +99,9 @@ struct KernelCore::Impl {
100 next_user_process_id = KProcess::ProcessIDMin; 99 next_user_process_id = KProcess::ProcessIDMin;
101 next_thread_id = 1; 100 next_thread_id = 1;
102 101
103 cores.clear(); 102 for (auto& core : cores) {
103 core = nullptr;
104 }
104 105
105 global_handle_table->Finalize(); 106 global_handle_table->Finalize();
106 global_handle_table.reset(); 107 global_handle_table.reset();
@@ -199,7 +200,7 @@ struct KernelCore::Impl {
199 const s32 core{static_cast<s32>(i)}; 200 const s32 core{static_cast<s32>(i)};
200 201
201 schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); 202 schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel());
202 cores.emplace_back(i, system, *schedulers[i], interrupts); 203 cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]);
203 204
204 auto* main_thread{Kernel::KThread::Create(system.Kernel())}; 205 auto* main_thread{Kernel::KThread::Create(system.Kernel())};
205 main_thread->SetName(fmt::format("MainThread:{}", core)); 206 main_thread->SetName(fmt::format("MainThread:{}", core));
@@ -761,7 +762,7 @@ struct KernelCore::Impl {
761 std::unordered_set<KAutoObject*> registered_in_use_objects; 762 std::unordered_set<KAutoObject*> registered_in_use_objects;
762 763
763 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor; 764 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
764 std::vector<Kernel::PhysicalCore> cores; 765 std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
765 766
766 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others 767 // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
767 std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES}; 768 std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
@@ -785,7 +786,6 @@ struct KernelCore::Impl {
785 Common::ThreadWorker service_threads_manager; 786 Common::ThreadWorker service_threads_manager;
786 787
787 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads; 788 std::array<KThread*, Core::Hardware::NUM_CPU_CORES> shutdown_threads;
788 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
789 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{}; 789 std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
790 790
791 bool is_multicore{}; 791 bool is_multicore{};
@@ -874,11 +874,11 @@ const Kernel::KScheduler& KernelCore::Scheduler(std::size_t id) const {
874} 874}
875 875
876Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { 876Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
877 return impl->cores[id]; 877 return *impl->cores[id];
878} 878}
879 879
880const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { 880const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
881 return impl->cores[id]; 881 return *impl->cores[id];
882} 882}
883 883
884size_t KernelCore::CurrentPhysicalCoreIndex() const { 884size_t KernelCore::CurrentPhysicalCoreIndex() const {
@@ -890,11 +890,11 @@ size_t KernelCore::CurrentPhysicalCoreIndex() const {
890} 890}
891 891
892Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() { 892Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
893 return impl->cores[CurrentPhysicalCoreIndex()]; 893 return *impl->cores[CurrentPhysicalCoreIndex()];
894} 894}
895 895
896const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const { 896const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
897 return impl->cores[CurrentPhysicalCoreIndex()]; 897 return *impl->cores[CurrentPhysicalCoreIndex()];
898} 898}
899 899
900Kernel::KScheduler* KernelCore::CurrentScheduler() { 900Kernel::KScheduler* KernelCore::CurrentScheduler() {
@@ -906,15 +906,6 @@ Kernel::KScheduler* KernelCore::CurrentScheduler() {
906 return impl->schedulers[core_id].get(); 906 return impl->schedulers[core_id].get();
907} 907}
908 908
909std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() {
910 return impl->interrupts;
911}
912
913const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
914 const {
915 return impl->interrupts;
916}
917
918Kernel::TimeManager& KernelCore::TimeManager() { 909Kernel::TimeManager& KernelCore::TimeManager() {
919 return impl->time_manager; 910 return impl->time_manager;
920} 911}
@@ -939,24 +930,18 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
939 return *impl->global_object_list_container; 930 return *impl->global_object_list_container;
940} 931}
941 932
942void KernelCore::InterruptAllPhysicalCores() {
943 for (auto& physical_core : impl->cores) {
944 physical_core.Interrupt();
945 }
946}
947
948void KernelCore::InvalidateAllInstructionCaches() { 933void KernelCore::InvalidateAllInstructionCaches() {
949 for (auto& physical_core : impl->cores) { 934 for (auto& physical_core : impl->cores) {
950 physical_core.ArmInterface().ClearInstructionCache(); 935 physical_core->ArmInterface().ClearInstructionCache();
951 } 936 }
952} 937}
953 938
954void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) { 939void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
955 for (auto& physical_core : impl->cores) { 940 for (auto& physical_core : impl->cores) {
956 if (!physical_core.IsInitialized()) { 941 if (!physical_core->IsInitialized()) {
957 continue; 942 continue;
958 } 943 }
959 physical_core.ArmInterface().InvalidateCacheRange(addr, size); 944 physical_core->ArmInterface().InvalidateCacheRange(addr, size);
960 } 945 }
961} 946}
962 947
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 6c7cf6af2..bcf016a97 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -9,14 +9,12 @@
9#include <string> 9#include <string>
10#include <unordered_map> 10#include <unordered_map>
11#include <vector> 11#include <vector>
12#include "core/arm/cpu_interrupt_handler.h"
13#include "core/hardware_properties.h" 12#include "core/hardware_properties.h"
14#include "core/hle/kernel/k_auto_object.h" 13#include "core/hle/kernel/k_auto_object.h"
15#include "core/hle/kernel/k_slab_heap.h" 14#include "core/hle/kernel/k_slab_heap.h"
16#include "core/hle/kernel/svc_common.h" 15#include "core/hle/kernel/svc_common.h"
17 16
18namespace Core { 17namespace Core {
19class CPUInterruptHandler;
20class ExclusiveMonitor; 18class ExclusiveMonitor;
21class System; 19class System;
22} // namespace Core 20} // namespace Core
@@ -183,12 +181,6 @@ public:
183 181
184 const KAutoObjectWithListContainer& ObjectListContainer() const; 182 const KAutoObjectWithListContainer& ObjectListContainer() const;
185 183
186 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts();
187
188 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Interrupts() const;
189
190 void InterruptAllPhysicalCores();
191
192 void InvalidateAllInstructionCaches(); 184 void InvalidateAllInstructionCaches();
193 185
194 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size); 186 void InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size);
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
index 6e7dacf97..d4375962f 100644
--- a/src/core/hle/kernel/physical_core.cpp
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -1,7 +1,6 @@
1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project 1// SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project
2// SPDX-License-Identifier: GPL-2.0-or-later 2// SPDX-License-Identifier: GPL-2.0-or-later
3 3
4#include "core/arm/cpu_interrupt_handler.h"
5#include "core/arm/dynarmic/arm_dynarmic_32.h" 4#include "core/arm/dynarmic/arm_dynarmic_32.h"
6#include "core/arm/dynarmic/arm_dynarmic_64.h" 5#include "core/arm/dynarmic/arm_dynarmic_64.h"
7#include "core/core.h" 6#include "core/core.h"
@@ -11,16 +10,14 @@
11 10
12namespace Kernel { 11namespace Kernel {
13 12
14PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, 13PhysicalCore::PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_)
15 Core::CPUInterrupts& interrupts_) 14 : core_index{core_index_}, system{system_}, scheduler{scheduler_} {
16 : core_index{core_index_}, system{system_}, scheduler{scheduler_},
17 interrupts{interrupts_}, guard{std::make_unique<std::mutex>()} {
18#ifdef ARCHITECTURE_x86_64 15#ifdef ARCHITECTURE_x86_64
19 // TODO(bunnei): Initialization relies on a core being available. We may later replace this with 16 // TODO(bunnei): Initialization relies on a core being available. We may later replace this with
20 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. 17 // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager.
21 auto& kernel = system.Kernel(); 18 auto& kernel = system.Kernel();
22 arm_interface = std::make_unique<Core::ARM_Dynarmic_64>( 19 arm_interface = std::make_unique<Core::ARM_Dynarmic_64>(
23 system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); 20 system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
24#else 21#else
25#error Platform not supported yet. 22#error Platform not supported yet.
26#endif 23#endif
@@ -34,7 +31,7 @@ void PhysicalCore::Initialize([[maybe_unused]] bool is_64_bit) {
34 if (!is_64_bit) { 31 if (!is_64_bit) {
35 // We already initialized a 64-bit core, replace with a 32-bit one. 32 // We already initialized a 64-bit core, replace with a 32-bit one.
36 arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( 33 arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
37 system, interrupts, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index); 34 system, kernel.IsMulticore(), kernel.GetExclusiveMonitor(), core_index);
38 } 35 }
39#else 36#else
40#error Platform not supported yet. 37#error Platform not supported yet.
@@ -47,24 +44,26 @@ void PhysicalCore::Run() {
47} 44}
48 45
49void PhysicalCore::Idle() { 46void PhysicalCore::Idle() {
50 interrupts[core_index].AwaitInterrupt(); 47 std::unique_lock lk{guard};
48 on_interrupt.wait(lk, [this] { return is_interrupted; });
51} 49}
52 50
53bool PhysicalCore::IsInterrupted() const { 51bool PhysicalCore::IsInterrupted() const {
54 return interrupts[core_index].IsInterrupted(); 52 return is_interrupted;
55} 53}
56 54
57void PhysicalCore::Interrupt() { 55void PhysicalCore::Interrupt() {
58 guard->lock(); 56 std::unique_lock lk{guard};
59 interrupts[core_index].SetInterrupt(true); 57 is_interrupted = true;
60 arm_interface->SignalInterrupt(); 58 arm_interface->SignalInterrupt();
61 guard->unlock(); 59 on_interrupt.notify_all();
62} 60}
63 61
64void PhysicalCore::ClearInterrupt() { 62void PhysicalCore::ClearInterrupt() {
65 guard->lock(); 63 std::unique_lock lk{guard};
66 interrupts[core_index].SetInterrupt(false); 64 is_interrupted = false;
67 guard->unlock(); 65 arm_interface->ClearInterrupt();
66 on_interrupt.notify_all();
68} 67}
69 68
70} // namespace Kernel 69} // namespace Kernel
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
index 898d1e5db..2fc8d4be2 100644
--- a/src/core/hle/kernel/physical_core.h
+++ b/src/core/hle/kernel/physical_core.h
@@ -14,7 +14,6 @@ class KScheduler;
14} // namespace Kernel 14} // namespace Kernel
15 15
16namespace Core { 16namespace Core {
17class CPUInterruptHandler;
18class ExclusiveMonitor; 17class ExclusiveMonitor;
19class System; 18class System;
20} // namespace Core 19} // namespace Core
@@ -23,15 +22,11 @@ namespace Kernel {
23 22
24class PhysicalCore { 23class PhysicalCore {
25public: 24public:
26 PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_, 25 PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
27 Core::CPUInterrupts& interrupts_);
28 ~PhysicalCore(); 26 ~PhysicalCore();
29 27
30 PhysicalCore(const PhysicalCore&) = delete; 28 YUZU_NON_COPYABLE(PhysicalCore);
31 PhysicalCore& operator=(const PhysicalCore&) = delete; 29 YUZU_NON_MOVEABLE(PhysicalCore);
32
33 PhysicalCore(PhysicalCore&&) = default;
34 PhysicalCore& operator=(PhysicalCore&&) = delete;
35 30
36 /// Initialize the core for the specified parameters. 31 /// Initialize the core for the specified parameters.
37 void Initialize(bool is_64_bit); 32 void Initialize(bool is_64_bit);
@@ -86,9 +81,11 @@ private:
86 const std::size_t core_index; 81 const std::size_t core_index;
87 Core::System& system; 82 Core::System& system;
88 Kernel::KScheduler& scheduler; 83 Kernel::KScheduler& scheduler;
89 Core::CPUInterrupts& interrupts; 84
90 std::unique_ptr<std::mutex> guard; 85 std::mutex guard;
86 std::condition_variable on_interrupt;
91 std::unique_ptr<Core::ARM_Interface> arm_interface; 87 std::unique_ptr<Core::ARM_Interface> arm_interface;
88 bool is_interrupted;
92}; 89};
93 90
94} // namespace Kernel 91} // namespace Kernel