summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2020-01-30 18:13:59 -0500
committerGravatar GitHub2020-01-30 18:13:59 -0500
commit985d0f35e55f0752c6e147d0140b367708499cb4 (patch)
tree119249aee3acc2cc2ee6a5d391288b52c126765b
parentMerge pull request #3151 from FearlessTobi/fix-korean (diff)
parentSystem: Address Feedback (diff)
downloadyuzu-985d0f35e55f0752c6e147d0140b367708499cb4.tar.gz
yuzu-985d0f35e55f0752c6e147d0140b367708499cb4.tar.xz
yuzu-985d0f35e55f0752c6e147d0140b367708499cb4.zip
Merge pull request #3353 from FernandoS27/aries
System: Refactor CPU Core management and move ARMInterface and Schedulers to Kernel
-rw-r--r--src/core/CMakeLists.txt10
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp2
-rw-r--r--src/core/arm/exclusive_monitor.cpp14
-rw-r--r--src/core/arm/exclusive_monitor.h9
-rw-r--r--src/core/core.cpp75
-rw-r--r--src/core/core.h10
-rw-r--r--src/core/core_cpu.cpp127
-rw-r--r--src/core/core_cpu.h120
-rw-r--r--src/core/core_manager.cpp70
-rw-r--r--src/core/core_manager.h63
-rw-r--r--src/core/cpu_core_manager.cpp152
-rw-r--r--src/core/cpu_core_manager.h62
-rw-r--r--src/core/cpu_manager.cpp83
-rw-r--r--src/core/cpu_manager.h50
-rw-r--r--src/core/gdbstub/gdbstub.cpp2
-rw-r--r--src/core/hle/kernel/address_arbiter.cpp1
-rw-r--r--src/core/hle/kernel/kernel.cpp52
-rw-r--r--src/core/hle/kernel/kernel.h19
-rw-r--r--src/core/hle/kernel/physical_core.cpp52
-rw-r--r--src/core/hle/kernel/physical_core.h74
-rw-r--r--src/core/hle/kernel/scheduler.cpp1
-rw-r--r--src/core/hle/kernel/svc.cpp2
-rw-r--r--src/core/hle/kernel/thread.cpp3
-rw-r--r--src/core/hle/kernel/wait_object.cpp3
24 files changed, 541 insertions, 515 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 1a3647a67..d342cafe0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -15,14 +15,14 @@ add_library(core STATIC
15 constants.h 15 constants.h
16 core.cpp 16 core.cpp
17 core.h 17 core.h
18 core_cpu.cpp 18 core_manager.cpp
19 core_cpu.h 19 core_manager.h
20 core_timing.cpp 20 core_timing.cpp
21 core_timing.h 21 core_timing.h
22 core_timing_util.cpp 22 core_timing_util.cpp
23 core_timing_util.h 23 core_timing_util.h
24 cpu_core_manager.cpp 24 cpu_manager.cpp
25 cpu_core_manager.h 25 cpu_manager.h
26 crypto/aes_util.cpp 26 crypto/aes_util.cpp
27 crypto/aes_util.h 27 crypto/aes_util.h
28 crypto/encryption_layer.cpp 28 crypto/encryption_layer.cpp
@@ -158,6 +158,8 @@ add_library(core STATIC
158 hle/kernel/mutex.h 158 hle/kernel/mutex.h
159 hle/kernel/object.cpp 159 hle/kernel/object.cpp
160 hle/kernel/object.h 160 hle/kernel/object.h
161 hle/kernel/physical_core.cpp
162 hle/kernel/physical_core.h
161 hle/kernel/process.cpp 163 hle/kernel/process.cpp
162 hle/kernel/process.h 164 hle/kernel/process.h
163 hle/kernel/process_capability.cpp 165 hle/kernel/process_capability.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index e825c0526..f468e57e4 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -10,7 +10,7 @@
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "core/arm/dynarmic/arm_dynarmic.h" 11#include "core/arm/dynarmic/arm_dynarmic.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/core_cpu.h" 13#include "core/core_manager.h"
14#include "core/core_timing.h" 14#include "core/core_timing.h"
15#include "core/core_timing_util.h" 15#include "core/core_timing_util.h"
16#include "core/gdbstub/gdbstub.h" 16#include "core/gdbstub/gdbstub.h"
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
index abd59ff4b..94570e520 100644
--- a/src/core/arm/exclusive_monitor.cpp
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -2,10 +2,24 @@
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#ifdef ARCHITECTURE_x86_64
6#include "core/arm/dynarmic/arm_dynarmic.h"
7#endif
5#include "core/arm/exclusive_monitor.h" 8#include "core/arm/exclusive_monitor.h"
9#include "core/memory.h"
6 10
7namespace Core { 11namespace Core {
8 12
9ExclusiveMonitor::~ExclusiveMonitor() = default; 13ExclusiveMonitor::~ExclusiveMonitor() = default;
10 14
15std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
16 std::size_t num_cores) {
17#ifdef ARCHITECTURE_x86_64
18 return std::make_unique<Core::DynarmicExclusiveMonitor>(memory, num_cores);
19#else
20 // TODO(merry): Passthrough exclusive monitor
21 return nullptr;
22#endif
23}
24
11} // namespace Core 25} // namespace Core
diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h
index f59aca667..4ef418b90 100644
--- a/src/core/arm/exclusive_monitor.h
+++ b/src/core/arm/exclusive_monitor.h
@@ -4,8 +4,14 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
8
7#include "common/common_types.h" 9#include "common/common_types.h"
8 10
11namespace Memory {
12class Memory;
13}
14
9namespace Core { 15namespace Core {
10 16
11class ExclusiveMonitor { 17class ExclusiveMonitor {
@@ -22,4 +28,7 @@ public:
22 virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0; 28 virtual bool ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) = 0;
23}; 29};
24 30
31std::unique_ptr<Core::ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
32 std::size_t num_cores);
33
25} // namespace Core 34} // namespace Core
diff --git a/src/core/core.cpp b/src/core/core.cpp
index d697b80ef..c53d122be 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -11,9 +11,9 @@
11#include "common/string_util.h" 11#include "common/string_util.h"
12#include "core/arm/exclusive_monitor.h" 12#include "core/arm/exclusive_monitor.h"
13#include "core/core.h" 13#include "core/core.h"
14#include "core/core_cpu.h" 14#include "core/core_manager.h"
15#include "core/core_timing.h" 15#include "core/core_timing.h"
16#include "core/cpu_core_manager.h" 16#include "core/cpu_manager.h"
17#include "core/file_sys/bis_factory.h" 17#include "core/file_sys/bis_factory.h"
18#include "core/file_sys/card_image.h" 18#include "core/file_sys/card_image.h"
19#include "core/file_sys/mode.h" 19#include "core/file_sys/mode.h"
@@ -28,6 +28,7 @@
28#include "core/hardware_interrupt_manager.h" 28#include "core/hardware_interrupt_manager.h"
29#include "core/hle/kernel/client_port.h" 29#include "core/hle/kernel/client_port.h"
30#include "core/hle/kernel/kernel.h" 30#include "core/hle/kernel/kernel.h"
31#include "core/hle/kernel/physical_core.h"
31#include "core/hle/kernel/process.h" 32#include "core/hle/kernel/process.h"
32#include "core/hle/kernel/scheduler.h" 33#include "core/hle/kernel/scheduler.h"
33#include "core/hle/kernel/thread.h" 34#include "core/hle/kernel/thread.h"
@@ -113,16 +114,25 @@ FileSys::VirtualFile GetGameFileFromPath(const FileSys::VirtualFilesystem& vfs,
113struct System::Impl { 114struct System::Impl {
114 explicit Impl(System& system) 115 explicit Impl(System& system)
115 : kernel{system}, fs_controller{system}, memory{system}, 116 : kernel{system}, fs_controller{system}, memory{system},
116 cpu_core_manager{system}, reporter{system}, applet_manager{system} {} 117 cpu_manager{system}, reporter{system}, applet_manager{system} {}
117 118
118 Cpu& CurrentCpuCore() { 119 CoreManager& CurrentCoreManager() {
119 return cpu_core_manager.GetCurrentCore(); 120 return cpu_manager.GetCurrentCoreManager();
121 }
122
123 Kernel::PhysicalCore& CurrentPhysicalCore() {
124 const auto index = cpu_manager.GetActiveCoreIndex();
125 return kernel.PhysicalCore(index);
126 }
127
128 Kernel::PhysicalCore& GetPhysicalCore(std::size_t index) {
129 return kernel.PhysicalCore(index);
120 } 130 }
121 131
122 ResultStatus RunLoop(bool tight_loop) { 132 ResultStatus RunLoop(bool tight_loop) {
123 status = ResultStatus::Success; 133 status = ResultStatus::Success;
124 134
125 cpu_core_manager.RunLoop(tight_loop); 135 cpu_manager.RunLoop(tight_loop);
126 136
127 return status; 137 return status;
128 } 138 }
@@ -131,8 +141,8 @@ struct System::Impl {
131 LOG_DEBUG(HW_Memory, "initialized OK"); 141 LOG_DEBUG(HW_Memory, "initialized OK");
132 142
133 core_timing.Initialize(); 143 core_timing.Initialize();
134 cpu_core_manager.Initialize();
135 kernel.Initialize(); 144 kernel.Initialize();
145 cpu_manager.Initialize();
136 146
137 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>( 147 const auto current_time = std::chrono::duration_cast<std::chrono::seconds>(
138 std::chrono::system_clock::now().time_since_epoch()); 148 std::chrono::system_clock::now().time_since_epoch());
@@ -205,7 +215,6 @@ struct System::Impl {
205 // Main process has been loaded and been made current. 215 // Main process has been loaded and been made current.
206 // Begin GPU and CPU execution. 216 // Begin GPU and CPU execution.
207 gpu_core->Start(); 217 gpu_core->Start();
208 cpu_core_manager.StartThreads();
209 218
210 // Initialize cheat engine 219 // Initialize cheat engine
211 if (cheat_engine) { 220 if (cheat_engine) {
@@ -272,7 +281,7 @@ struct System::Impl {
272 gpu_core.reset(); 281 gpu_core.reset();
273 282
274 // Close all CPU/threading state 283 // Close all CPU/threading state
275 cpu_core_manager.Shutdown(); 284 cpu_manager.Shutdown();
276 285
277 // Shutdown kernel and core timing 286 // Shutdown kernel and core timing
278 kernel.Shutdown(); 287 kernel.Shutdown();
@@ -342,7 +351,7 @@ struct System::Impl {
342 std::unique_ptr<Tegra::GPU> gpu_core; 351 std::unique_ptr<Tegra::GPU> gpu_core;
343 std::unique_ptr<Hardware::InterruptManager> interrupt_manager; 352 std::unique_ptr<Hardware::InterruptManager> interrupt_manager;
344 Memory::Memory memory; 353 Memory::Memory memory;
345 CpuCoreManager cpu_core_manager; 354 CpuManager cpu_manager;
346 bool is_powered_on = false; 355 bool is_powered_on = false;
347 bool exit_lock = false; 356 bool exit_lock = false;
348 357
@@ -377,12 +386,12 @@ struct System::Impl {
377System::System() : impl{std::make_unique<Impl>(*this)} {} 386System::System() : impl{std::make_unique<Impl>(*this)} {}
378System::~System() = default; 387System::~System() = default;
379 388
380Cpu& System::CurrentCpuCore() { 389CoreManager& System::CurrentCoreManager() {
381 return impl->CurrentCpuCore(); 390 return impl->CurrentCoreManager();
382} 391}
383 392
384const Cpu& System::CurrentCpuCore() const { 393const CoreManager& System::CurrentCoreManager() const {
385 return impl->CurrentCpuCore(); 394 return impl->CurrentCoreManager();
386} 395}
387 396
388System::ResultStatus System::RunLoop(bool tight_loop) { 397System::ResultStatus System::RunLoop(bool tight_loop) {
@@ -394,7 +403,7 @@ System::ResultStatus System::SingleStep() {
394} 403}
395 404
396void System::InvalidateCpuInstructionCaches() { 405void System::InvalidateCpuInstructionCaches() {
397 impl->cpu_core_manager.InvalidateAllInstructionCaches(); 406 impl->kernel.InvalidateAllInstructionCaches();
398} 407}
399 408
400System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { 409System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) {
@@ -406,13 +415,11 @@ bool System::IsPoweredOn() const {
406} 415}
407 416
408void System::PrepareReschedule() { 417void System::PrepareReschedule() {
409 CurrentCpuCore().PrepareReschedule(); 418 impl->CurrentPhysicalCore().Stop();
410} 419}
411 420
412void System::PrepareReschedule(const u32 core_index) { 421void System::PrepareReschedule(const u32 core_index) {
413 if (core_index < GlobalScheduler().CpuCoresCount()) { 422 impl->kernel.PrepareReschedule(core_index);
414 CpuCore(core_index).PrepareReschedule();
415 }
416} 423}
417 424
418PerfStatsResults System::GetAndResetPerfStats() { 425PerfStatsResults System::GetAndResetPerfStats() {
@@ -428,31 +435,31 @@ const TelemetrySession& System::TelemetrySession() const {
428} 435}
429 436
430ARM_Interface& System::CurrentArmInterface() { 437ARM_Interface& System::CurrentArmInterface() {
431 return CurrentCpuCore().ArmInterface(); 438 return impl->CurrentPhysicalCore().ArmInterface();
432} 439}
433 440
434const ARM_Interface& System::CurrentArmInterface() const { 441const ARM_Interface& System::CurrentArmInterface() const {
435 return CurrentCpuCore().ArmInterface(); 442 return impl->CurrentPhysicalCore().ArmInterface();
436} 443}
437 444
438std::size_t System::CurrentCoreIndex() const { 445std::size_t System::CurrentCoreIndex() const {
439 return CurrentCpuCore().CoreIndex(); 446 return impl->cpu_manager.GetActiveCoreIndex();
440} 447}
441 448
442Kernel::Scheduler& System::CurrentScheduler() { 449Kernel::Scheduler& System::CurrentScheduler() {
443 return CurrentCpuCore().Scheduler(); 450 return impl->CurrentPhysicalCore().Scheduler();
444} 451}
445 452
446const Kernel::Scheduler& System::CurrentScheduler() const { 453const Kernel::Scheduler& System::CurrentScheduler() const {
447 return CurrentCpuCore().Scheduler(); 454 return impl->CurrentPhysicalCore().Scheduler();
448} 455}
449 456
450Kernel::Scheduler& System::Scheduler(std::size_t core_index) { 457Kernel::Scheduler& System::Scheduler(std::size_t core_index) {
451 return CpuCore(core_index).Scheduler(); 458 return impl->GetPhysicalCore(core_index).Scheduler();
452} 459}
453 460
454const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { 461const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const {
455 return CpuCore(core_index).Scheduler(); 462 return impl->GetPhysicalCore(core_index).Scheduler();
456} 463}
457 464
458/// Gets the global scheduler 465/// Gets the global scheduler
@@ -474,28 +481,28 @@ const Kernel::Process* System::CurrentProcess() const {
474} 481}
475 482
476ARM_Interface& System::ArmInterface(std::size_t core_index) { 483ARM_Interface& System::ArmInterface(std::size_t core_index) {
477 return CpuCore(core_index).ArmInterface(); 484 return impl->GetPhysicalCore(core_index).ArmInterface();
478} 485}
479 486
480const ARM_Interface& System::ArmInterface(std::size_t core_index) const { 487const ARM_Interface& System::ArmInterface(std::size_t core_index) const {
481 return CpuCore(core_index).ArmInterface(); 488 return impl->GetPhysicalCore(core_index).ArmInterface();
482} 489}
483 490
484Cpu& System::CpuCore(std::size_t core_index) { 491CoreManager& System::GetCoreManager(std::size_t core_index) {
485 return impl->cpu_core_manager.GetCore(core_index); 492 return impl->cpu_manager.GetCoreManager(core_index);
486} 493}
487 494
488const Cpu& System::CpuCore(std::size_t core_index) const { 495const CoreManager& System::GetCoreManager(std::size_t core_index) const {
489 ASSERT(core_index < NUM_CPU_CORES); 496 ASSERT(core_index < NUM_CPU_CORES);
490 return impl->cpu_core_manager.GetCore(core_index); 497 return impl->cpu_manager.GetCoreManager(core_index);
491} 498}
492 499
493ExclusiveMonitor& System::Monitor() { 500ExclusiveMonitor& System::Monitor() {
494 return impl->cpu_core_manager.GetExclusiveMonitor(); 501 return impl->kernel.GetExclusiveMonitor();
495} 502}
496 503
497const ExclusiveMonitor& System::Monitor() const { 504const ExclusiveMonitor& System::Monitor() const {
498 return impl->cpu_core_manager.GetExclusiveMonitor(); 505 return impl->kernel.GetExclusiveMonitor();
499} 506}
500 507
501Memory::Memory& System::Memory() { 508Memory::Memory& System::Memory() {
diff --git a/src/core/core.h b/src/core/core.h
index e240c5c58..e69d68fcf 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -93,7 +93,7 @@ class Memory;
93namespace Core { 93namespace Core {
94 94
95class ARM_Interface; 95class ARM_Interface;
96class Cpu; 96class CoreManager;
97class ExclusiveMonitor; 97class ExclusiveMonitor;
98class FrameLimiter; 98class FrameLimiter;
99class PerfStats; 99class PerfStats;
@@ -218,10 +218,10 @@ public:
218 const ARM_Interface& ArmInterface(std::size_t core_index) const; 218 const ARM_Interface& ArmInterface(std::size_t core_index) const;
219 219
220 /// Gets a CPU interface to the CPU core with the specified index 220 /// Gets a CPU interface to the CPU core with the specified index
221 Cpu& CpuCore(std::size_t core_index); 221 CoreManager& GetCoreManager(std::size_t core_index);
222 222
223 /// Gets a CPU interface to the CPU core with the specified index 223 /// Gets a CPU interface to the CPU core with the specified index
224 const Cpu& CpuCore(std::size_t core_index) const; 224 const CoreManager& GetCoreManager(std::size_t core_index) const;
225 225
226 /// Gets a reference to the exclusive monitor 226 /// Gets a reference to the exclusive monitor
227 ExclusiveMonitor& Monitor(); 227 ExclusiveMonitor& Monitor();
@@ -364,10 +364,10 @@ private:
364 System(); 364 System();
365 365
366 /// Returns the currently running CPU core 366 /// Returns the currently running CPU core
367 Cpu& CurrentCpuCore(); 367 CoreManager& CurrentCoreManager();
368 368
369 /// Returns the currently running CPU core 369 /// Returns the currently running CPU core
370 const Cpu& CurrentCpuCore() const; 370 const CoreManager& CurrentCoreManager() const;
371 371
372 /** 372 /**
373 * Initialize the emulated system. 373 * Initialize the emulated system.
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
deleted file mode 100644
index 630cd4feb..000000000
--- a/src/core/core_cpu.cpp
+++ /dev/null
@@ -1,127 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <condition_variable>
6#include <mutex>
7
8#include "common/logging/log.h"
9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic.h"
11#endif
12#include "core/arm/exclusive_monitor.h"
13#include "core/arm/unicorn/arm_unicorn.h"
14#include "core/core.h"
15#include "core/core_cpu.h"
16#include "core/core_timing.h"
17#include "core/hle/kernel/scheduler.h"
18#include "core/hle/kernel/thread.h"
19#include "core/hle/lock.h"
20#include "core/settings.h"
21
22namespace Core {
23
24void CpuBarrier::NotifyEnd() {
25 std::unique_lock lock{mutex};
26 end = true;
27 condition.notify_all();
28}
29
30bool CpuBarrier::Rendezvous() {
31 if (!Settings::values.use_multi_core) {
32 // Meaningless when running in single-core mode
33 return true;
34 }
35
36 if (!end) {
37 std::unique_lock lock{mutex};
38
39 --cores_waiting;
40 if (!cores_waiting) {
41 cores_waiting = NUM_CPU_CORES;
42 condition.notify_all();
43 return true;
44 }
45
46 condition.wait(lock);
47 return true;
48 }
49
50 return false;
51}
52
53Cpu::Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
54 std::size_t core_index)
55 : cpu_barrier{cpu_barrier}, global_scheduler{system.GlobalScheduler()},
56 core_timing{system.CoreTiming()}, core_index{core_index} {
57#ifdef ARCHITECTURE_x86_64
58 arm_interface = std::make_unique<ARM_Dynarmic>(system, exclusive_monitor, core_index);
59#else
60 arm_interface = std::make_unique<ARM_Unicorn>(system);
61 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
62#endif
63
64 scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index);
65}
66
67Cpu::~Cpu() = default;
68
69std::unique_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(
70 [[maybe_unused]] Memory::Memory& memory, [[maybe_unused]] std::size_t num_cores) {
71#ifdef ARCHITECTURE_x86_64
72 return std::make_unique<DynarmicExclusiveMonitor>(memory, num_cores);
73#else
74 // TODO(merry): Passthrough exclusive monitor
75 return nullptr;
76#endif
77}
78
79void Cpu::RunLoop(bool tight_loop) {
80 // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
81 if (!cpu_barrier.Rendezvous()) {
82 // If rendezvous failed, session has been killed
83 return;
84 }
85
86 Reschedule();
87
88 // If we don't have a currently active thread then don't execute instructions,
89 // instead advance to the next event and try to yield to the next thread
90 if (Kernel::GetCurrentThread() == nullptr) {
91 LOG_TRACE(Core, "Core-{} idling", core_index);
92 core_timing.Idle();
93 } else {
94 if (tight_loop) {
95 arm_interface->Run();
96 } else {
97 arm_interface->Step();
98 }
99 // We are stopping a run, exclusive state must be cleared
100 arm_interface->ClearExclusiveState();
101 }
102 core_timing.Advance();
103
104 Reschedule();
105}
106
107void Cpu::SingleStep() {
108 return RunLoop(false);
109}
110
111void Cpu::PrepareReschedule() {
112 arm_interface->PrepareReschedule();
113}
114
115void Cpu::Reschedule() {
116 // Lock the global kernel mutex when we manipulate the HLE state
117 std::lock_guard lock(HLE::g_hle_lock);
118
119 global_scheduler.SelectThread(core_index);
120 scheduler->TryDoContextSwitch();
121}
122
123void Cpu::Shutdown() {
124 scheduler->Shutdown();
125}
126
127} // namespace Core
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
deleted file mode 100644
index 78f5021a2..000000000
--- a/src/core/core_cpu.h
+++ /dev/null
@@ -1,120 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <atomic>
8#include <condition_variable>
9#include <cstddef>
10#include <memory>
11#include <mutex>
12#include "common/common_types.h"
13
14namespace Kernel {
15class GlobalScheduler;
16class Scheduler;
17} // namespace Kernel
18
19namespace Core {
20class System;
21}
22
23namespace Core::Timing {
24class CoreTiming;
25}
26
27namespace Memory {
28class Memory;
29}
30
31namespace Core {
32
33class ARM_Interface;
34class ExclusiveMonitor;
35
36constexpr unsigned NUM_CPU_CORES{4};
37
38class CpuBarrier {
39public:
40 bool IsAlive() const {
41 return !end;
42 }
43
44 void NotifyEnd();
45
46 bool Rendezvous();
47
48private:
49 unsigned cores_waiting{NUM_CPU_CORES};
50 std::mutex mutex;
51 std::condition_variable condition;
52 std::atomic<bool> end{};
53};
54
55class Cpu {
56public:
57 Cpu(System& system, ExclusiveMonitor& exclusive_monitor, CpuBarrier& cpu_barrier,
58 std::size_t core_index);
59 ~Cpu();
60
61 void RunLoop(bool tight_loop = true);
62
63 void SingleStep();
64
65 void PrepareReschedule();
66
67 ARM_Interface& ArmInterface() {
68 return *arm_interface;
69 }
70
71 const ARM_Interface& ArmInterface() const {
72 return *arm_interface;
73 }
74
75 Kernel::Scheduler& Scheduler() {
76 return *scheduler;
77 }
78
79 const Kernel::Scheduler& Scheduler() const {
80 return *scheduler;
81 }
82
83 bool IsMainCore() const {
84 return core_index == 0;
85 }
86
87 std::size_t CoreIndex() const {
88 return core_index;
89 }
90
91 void Shutdown();
92
93 /**
94 * Creates an exclusive monitor to handle exclusive reads/writes.
95 *
96 * @param memory The current memory subsystem that the monitor may wish
97 * to keep track of.
98 *
99 * @param num_cores The number of cores to assume about the CPU.
100 *
101 * @returns The constructed exclusive monitor instance, or nullptr if the current
102 * CPU backend is unable to use an exclusive monitor.
103 */
104 static std::unique_ptr<ExclusiveMonitor> MakeExclusiveMonitor(Memory::Memory& memory,
105 std::size_t num_cores);
106
107private:
108 void Reschedule();
109
110 std::unique_ptr<ARM_Interface> arm_interface;
111 CpuBarrier& cpu_barrier;
112 Kernel::GlobalScheduler& global_scheduler;
113 std::unique_ptr<Kernel::Scheduler> scheduler;
114 Timing::CoreTiming& core_timing;
115
116 std::atomic<bool> reschedule_pending = false;
117 std::size_t core_index;
118};
119
120} // namespace Core
diff --git a/src/core/core_manager.cpp b/src/core/core_manager.cpp
new file mode 100644
index 000000000..8eacf92dd
--- /dev/null
+++ b/src/core/core_manager.cpp
@@ -0,0 +1,70 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <condition_variable>
6#include <mutex>
7
8#include "common/logging/log.h"
9#ifdef ARCHITECTURE_x86_64
10#include "core/arm/dynarmic/arm_dynarmic.h"
11#endif
12#include "core/arm/exclusive_monitor.h"
13#include "core/arm/unicorn/arm_unicorn.h"
14#include "core/core.h"
15#include "core/core_manager.h"
16#include "core/core_timing.h"
17#include "core/hle/kernel/kernel.h"
18#include "core/hle/kernel/physical_core.h"
19#include "core/hle/kernel/scheduler.h"
20#include "core/hle/kernel/thread.h"
21#include "core/hle/lock.h"
22#include "core/settings.h"
23
24namespace Core {
25
26CoreManager::CoreManager(System& system, std::size_t core_index)
27 : global_scheduler{system.GlobalScheduler()}, physical_core{system.Kernel().PhysicalCore(
28 core_index)},
29 core_timing{system.CoreTiming()}, core_index{core_index} {}
30
31CoreManager::~CoreManager() = default;
32
33void CoreManager::RunLoop(bool tight_loop) {
34 Reschedule();
35
36 // If we don't have a currently active thread then don't execute instructions,
37 // instead advance to the next event and try to yield to the next thread
38 if (Kernel::GetCurrentThread() == nullptr) {
39 LOG_TRACE(Core, "Core-{} idling", core_index);
40 core_timing.Idle();
41 } else {
42 if (tight_loop) {
43 physical_core.Run();
44 } else {
45 physical_core.Step();
46 }
47 }
48 core_timing.Advance();
49
50 Reschedule();
51}
52
53void CoreManager::SingleStep() {
54 return RunLoop(false);
55}
56
57void CoreManager::PrepareReschedule() {
58 physical_core.Stop();
59}
60
61void CoreManager::Reschedule() {
62 // Lock the global kernel mutex when we manipulate the HLE state
63 std::lock_guard lock(HLE::g_hle_lock);
64
65 global_scheduler.SelectThread(core_index);
66
67 physical_core.Scheduler().TryDoContextSwitch();
68}
69
70} // namespace Core
diff --git a/src/core/core_manager.h b/src/core/core_manager.h
new file mode 100644
index 000000000..b14e723d7
--- /dev/null
+++ b/src/core/core_manager.h
@@ -0,0 +1,63 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <atomic>
8#include <cstddef>
9#include <memory>
10#include "common/common_types.h"
11
12namespace Kernel {
13class GlobalScheduler;
14class PhysicalCore;
15} // namespace Kernel
16
17namespace Core {
18class System;
19}
20
21namespace Core::Timing {
22class CoreTiming;
23}
24
25namespace Memory {
26class Memory;
27}
28
29namespace Core {
30
31constexpr unsigned NUM_CPU_CORES{4};
32
33class CoreManager {
34public:
35 CoreManager(System& system, std::size_t core_index);
36 ~CoreManager();
37
38 void RunLoop(bool tight_loop = true);
39
40 void SingleStep();
41
42 void PrepareReschedule();
43
44 bool IsMainCore() const {
45 return core_index == 0;
46 }
47
48 std::size_t CoreIndex() const {
49 return core_index;
50 }
51
52private:
53 void Reschedule();
54
55 Kernel::GlobalScheduler& global_scheduler;
56 Kernel::PhysicalCore& physical_core;
57 Timing::CoreTiming& core_timing;
58
59 std::atomic<bool> reschedule_pending = false;
60 std::size_t core_index;
61};
62
63} // namespace Core
diff --git a/src/core/cpu_core_manager.cpp b/src/core/cpu_core_manager.cpp
deleted file mode 100644
index f04a34133..000000000
--- a/src/core/cpu_core_manager.cpp
+++ /dev/null
@@ -1,152 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "core/arm/exclusive_monitor.h"
7#include "core/core.h"
8#include "core/core_cpu.h"
9#include "core/core_timing.h"
10#include "core/cpu_core_manager.h"
11#include "core/gdbstub/gdbstub.h"
12#include "core/settings.h"
13
14namespace Core {
15namespace {
16void RunCpuCore(const System& system, Cpu& cpu_state) {
17 while (system.IsPoweredOn()) {
18 cpu_state.RunLoop(true);
19 }
20}
21} // Anonymous namespace
22
23CpuCoreManager::CpuCoreManager(System& system) : system{system} {}
24CpuCoreManager::~CpuCoreManager() = default;
25
26void CpuCoreManager::Initialize() {
27 barrier = std::make_unique<CpuBarrier>();
28 exclusive_monitor = Cpu::MakeExclusiveMonitor(system.Memory(), cores.size());
29
30 for (std::size_t index = 0; index < cores.size(); ++index) {
31 cores[index] = std::make_unique<Cpu>(system, *exclusive_monitor, *barrier, index);
32 }
33}
34
35void CpuCoreManager::StartThreads() {
36 // Create threads for CPU cores 1-3, and build thread_to_cpu map
37 // CPU core 0 is run on the main thread
38 thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
39 if (!Settings::values.use_multi_core) {
40 return;
41 }
42
43 for (std::size_t index = 0; index < core_threads.size(); ++index) {
44 core_threads[index] = std::make_unique<std::thread>(RunCpuCore, std::cref(system),
45 std::ref(*cores[index + 1]));
46 thread_to_cpu[core_threads[index]->get_id()] = cores[index + 1].get();
47 }
48}
49
50void CpuCoreManager::Shutdown() {
51 barrier->NotifyEnd();
52 if (Settings::values.use_multi_core) {
53 for (auto& thread : core_threads) {
54 thread->join();
55 thread.reset();
56 }
57 }
58
59 thread_to_cpu.clear();
60 for (auto& cpu_core : cores) {
61 cpu_core->Shutdown();
62 cpu_core.reset();
63 }
64
65 exclusive_monitor.reset();
66 barrier.reset();
67}
68
69Cpu& CpuCoreManager::GetCore(std::size_t index) {
70 return *cores.at(index);
71}
72
73const Cpu& CpuCoreManager::GetCore(std::size_t index) const {
74 return *cores.at(index);
75}
76
77ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() {
78 return *exclusive_monitor;
79}
80
81const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const {
82 return *exclusive_monitor;
83}
84
85Cpu& CpuCoreManager::GetCurrentCore() {
86 if (Settings::values.use_multi_core) {
87 const auto& search = thread_to_cpu.find(std::this_thread::get_id());
88 ASSERT(search != thread_to_cpu.end());
89 ASSERT(search->second);
90 return *search->second;
91 }
92
93 // Otherwise, use single-threaded mode active_core variable
94 return *cores[active_core];
95}
96
97const Cpu& CpuCoreManager::GetCurrentCore() const {
98 if (Settings::values.use_multi_core) {
99 const auto& search = thread_to_cpu.find(std::this_thread::get_id());
100 ASSERT(search != thread_to_cpu.end());
101 ASSERT(search->second);
102 return *search->second;
103 }
104
105 // Otherwise, use single-threaded mode active_core variable
106 return *cores[active_core];
107}
108
109void CpuCoreManager::RunLoop(bool tight_loop) {
110 // Update thread_to_cpu in case Core 0 is run from a different host thread
111 thread_to_cpu[std::this_thread::get_id()] = cores[0].get();
112
113 if (GDBStub::IsServerEnabled()) {
114 GDBStub::HandlePacket();
115
116 // If the loop is halted and we want to step, use a tiny (1) number of instructions to
117 // execute. Otherwise, get out of the loop function.
118 if (GDBStub::GetCpuHaltFlag()) {
119 if (GDBStub::GetCpuStepFlag()) {
120 tight_loop = false;
121 } else {
122 return;
123 }
124 }
125 }
126
127 auto& core_timing = system.CoreTiming();
128 core_timing.ResetRun();
129 bool keep_running{};
130 do {
131 keep_running = false;
132 for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
133 core_timing.SwitchContext(active_core);
134 if (core_timing.CanCurrentContextRun()) {
135 cores[active_core]->RunLoop(tight_loop);
136 }
137 keep_running |= core_timing.CanCurrentContextRun();
138 }
139 } while (keep_running);
140
141 if (GDBStub::IsServerEnabled()) {
142 GDBStub::SetCpuStepFlag(false);
143 }
144}
145
146void CpuCoreManager::InvalidateAllInstructionCaches() {
147 for (auto& cpu : cores) {
148 cpu->ArmInterface().ClearInstructionCache();
149 }
150}
151
152} // namespace Core
diff --git a/src/core/cpu_core_manager.h b/src/core/cpu_core_manager.h
deleted file mode 100644
index 2cbbf8216..000000000
--- a/src/core/cpu_core_manager.h
+++ /dev/null
@@ -1,62 +0,0 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <map>
9#include <memory>
10#include <thread>
11
12namespace Core {
13
14class Cpu;
15class CpuBarrier;
16class ExclusiveMonitor;
17class System;
18
19class CpuCoreManager {
20public:
21 explicit CpuCoreManager(System& system);
22 CpuCoreManager(const CpuCoreManager&) = delete;
23 CpuCoreManager(CpuCoreManager&&) = delete;
24
25 ~CpuCoreManager();
26
27 CpuCoreManager& operator=(const CpuCoreManager&) = delete;
28 CpuCoreManager& operator=(CpuCoreManager&&) = delete;
29
30 void Initialize();
31 void StartThreads();
32 void Shutdown();
33
34 Cpu& GetCore(std::size_t index);
35 const Cpu& GetCore(std::size_t index) const;
36
37 Cpu& GetCurrentCore();
38 const Cpu& GetCurrentCore() const;
39
40 ExclusiveMonitor& GetExclusiveMonitor();
41 const ExclusiveMonitor& GetExclusiveMonitor() const;
42
43 void RunLoop(bool tight_loop);
44
45 void InvalidateAllInstructionCaches();
46
47private:
48 static constexpr std::size_t NUM_CPU_CORES = 4;
49
50 std::unique_ptr<ExclusiveMonitor> exclusive_monitor;
51 std::unique_ptr<CpuBarrier> barrier;
52 std::array<std::unique_ptr<Cpu>, NUM_CPU_CORES> cores;
53 std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> core_threads;
54 std::size_t active_core{}; ///< Active core, only used in single thread mode
55
56 /// Map of guest threads to CPU cores
57 std::map<std::thread::id, Cpu*> thread_to_cpu;
58
59 System& system;
60};
61
62} // namespace Core
diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp
new file mode 100644
index 000000000..752534868
--- /dev/null
+++ b/src/core/cpu_manager.cpp
@@ -0,0 +1,83 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "core/arm/exclusive_monitor.h"
7#include "core/core.h"
8#include "core/core_manager.h"
9#include "core/core_timing.h"
10#include "core/cpu_manager.h"
11#include "core/gdbstub/gdbstub.h"
12#include "core/settings.h"
13
14namespace Core {
15
16CpuManager::CpuManager(System& system) : system{system} {}
17CpuManager::~CpuManager() = default;
18
19void CpuManager::Initialize() {
20 for (std::size_t index = 0; index < core_managers.size(); ++index) {
21 core_managers[index] = std::make_unique<CoreManager>(system, index);
22 }
23}
24
25void CpuManager::Shutdown() {
26 for (auto& cpu_core : core_managers) {
27 cpu_core.reset();
28 }
29}
30
31CoreManager& CpuManager::GetCoreManager(std::size_t index) {
32 return *core_managers.at(index);
33}
34
35const CoreManager& CpuManager::GetCoreManager(std::size_t index) const {
36 return *core_managers.at(index);
37}
38
39CoreManager& CpuManager::GetCurrentCoreManager() {
40 // Otherwise, use single-threaded mode active_core variable
41 return *core_managers[active_core];
42}
43
44const CoreManager& CpuManager::GetCurrentCoreManager() const {
45 // Otherwise, use single-threaded mode active_core variable
46 return *core_managers[active_core];
47}
48
49void CpuManager::RunLoop(bool tight_loop) {
50 if (GDBStub::IsServerEnabled()) {
51 GDBStub::HandlePacket();
52
53 // If the loop is halted and we want to step, use a tiny (1) number of instructions to
54 // execute. Otherwise, get out of the loop function.
55 if (GDBStub::GetCpuHaltFlag()) {
56 if (GDBStub::GetCpuStepFlag()) {
57 tight_loop = false;
58 } else {
59 return;
60 }
61 }
62 }
63
64 auto& core_timing = system.CoreTiming();
65 core_timing.ResetRun();
66 bool keep_running{};
67 do {
68 keep_running = false;
69 for (active_core = 0; active_core < NUM_CPU_CORES; ++active_core) {
70 core_timing.SwitchContext(active_core);
71 if (core_timing.CanCurrentContextRun()) {
72 core_managers[active_core]->RunLoop(tight_loop);
73 }
74 keep_running |= core_timing.CanCurrentContextRun();
75 }
76 } while (keep_running);
77
78 if (GDBStub::IsServerEnabled()) {
79 GDBStub::SetCpuStepFlag(false);
80 }
81}
82
83} // namespace Core
diff --git a/src/core/cpu_manager.h b/src/core/cpu_manager.h
new file mode 100644
index 000000000..feb619e1b
--- /dev/null
+++ b/src/core/cpu_manager.h
@@ -0,0 +1,50 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9
10namespace Core {
11
12class CoreManager;
13class System;
14
15class CpuManager {
16public:
17 explicit CpuManager(System& system);
18 CpuManager(const CpuManager&) = delete;
19 CpuManager(CpuManager&&) = delete;
20
21 ~CpuManager();
22
23 CpuManager& operator=(const CpuManager&) = delete;
24 CpuManager& operator=(CpuManager&&) = delete;
25
26 void Initialize();
27 void Shutdown();
28
29 CoreManager& GetCoreManager(std::size_t index);
30 const CoreManager& GetCoreManager(std::size_t index) const;
31
32 CoreManager& GetCurrentCoreManager();
33 const CoreManager& GetCurrentCoreManager() const;
34
35 std::size_t GetActiveCoreIndex() const {
36 return active_core;
37 }
38
39 void RunLoop(bool tight_loop);
40
41private:
42 static constexpr std::size_t NUM_CPU_CORES = 4;
43
44 std::array<std::unique_ptr<CoreManager>, NUM_CPU_CORES> core_managers;
45 std::size_t active_core{}; ///< Active core, only used in single thread mode
46
47 System& system;
48};
49
50} // namespace Core
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 37cb28848..67e95999d 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -35,7 +35,7 @@
35#include "common/swap.h" 35#include "common/swap.h"
36#include "core/arm/arm_interface.h" 36#include "core/arm/arm_interface.h"
37#include "core/core.h" 37#include "core/core.h"
38#include "core/core_cpu.h" 38#include "core/core_manager.h"
39#include "core/gdbstub/gdbstub.h" 39#include "core/gdbstub/gdbstub.h"
40#include "core/hle/kernel/process.h" 40#include "core/hle/kernel/process.h"
41#include "core/hle/kernel/scheduler.h" 41#include "core/hle/kernel/scheduler.h"
diff --git a/src/core/hle/kernel/address_arbiter.cpp b/src/core/hle/kernel/address_arbiter.cpp
index db189c8e3..2ea3dcb61 100644
--- a/src/core/hle/kernel/address_arbiter.cpp
+++ b/src/core/hle/kernel/address_arbiter.cpp
@@ -8,7 +8,6 @@
8#include "common/assert.h" 8#include "common/assert.h"
9#include "common/common_types.h" 9#include "common/common_types.h"
10#include "core/core.h" 10#include "core/core.h"
11#include "core/core_cpu.h"
12#include "core/hle/kernel/address_arbiter.h" 11#include "core/hle/kernel/address_arbiter.h"
13#include "core/hle/kernel/errors.h" 12#include "core/hle/kernel/errors.h"
14#include "core/hle/kernel/scheduler.h" 13#include "core/hle/kernel/scheduler.h"
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 1d0783bd3..0cf3c8f70 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -3,13 +3,15 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <atomic> 5#include <atomic>
6#include <functional>
6#include <memory> 7#include <memory>
7#include <mutex> 8#include <mutex>
8#include <utility> 9#include <utility>
9 10
10#include "common/assert.h" 11#include "common/assert.h"
11#include "common/logging/log.h" 12#include "common/logging/log.h"
12 13#include "core/arm/arm_interface.h"
14#include "core/arm/exclusive_monitor.h"
13#include "core/core.h" 15#include "core/core.h"
14#include "core/core_timing.h" 16#include "core/core_timing.h"
15#include "core/core_timing_util.h" 17#include "core/core_timing_util.h"
@@ -17,6 +19,7 @@
17#include "core/hle/kernel/errors.h" 19#include "core/hle/kernel/errors.h"
18#include "core/hle/kernel/handle_table.h" 20#include "core/hle/kernel/handle_table.h"
19#include "core/hle/kernel/kernel.h" 21#include "core/hle/kernel/kernel.h"
22#include "core/hle/kernel/physical_core.h"
20#include "core/hle/kernel/process.h" 23#include "core/hle/kernel/process.h"
21#include "core/hle/kernel/resource_limit.h" 24#include "core/hle/kernel/resource_limit.h"
22#include "core/hle/kernel/scheduler.h" 25#include "core/hle/kernel/scheduler.h"
@@ -98,6 +101,7 @@ struct KernelCore::Impl {
98 void Initialize(KernelCore& kernel) { 101 void Initialize(KernelCore& kernel) {
99 Shutdown(); 102 Shutdown();
100 103
104 InitializePhysicalCores(kernel);
101 InitializeSystemResourceLimit(kernel); 105 InitializeSystemResourceLimit(kernel);
102 InitializeThreads(); 106 InitializeThreads();
103 InitializePreemption(); 107 InitializePreemption();
@@ -121,6 +125,21 @@ struct KernelCore::Impl {
121 global_scheduler.Shutdown(); 125 global_scheduler.Shutdown();
122 126
123 named_ports.clear(); 127 named_ports.clear();
128
129 for (auto& core : cores) {
130 core.Shutdown();
131 }
132 cores.clear();
133
134 exclusive_monitor.reset(nullptr);
135 }
136
137 void InitializePhysicalCores(KernelCore& kernel) {
138 exclusive_monitor =
139 Core::MakeExclusiveMonitor(system.Memory(), global_scheduler.CpuCoresCount());
140 for (std::size_t i = 0; i < global_scheduler.CpuCoresCount(); i++) {
141 cores.emplace_back(system, kernel, i, *exclusive_monitor);
142 }
124 } 143 }
125 144
126 // Creates the default system resource limit 145 // Creates the default system resource limit
@@ -186,6 +205,9 @@ struct KernelCore::Impl {
186 /// the ConnectToPort SVC. 205 /// the ConnectToPort SVC.
187 NamedPortTable named_ports; 206 NamedPortTable named_ports;
188 207
208 std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
209 std::vector<Kernel::PhysicalCore> cores;
210
189 // System context 211 // System context
190 Core::System& system; 212 Core::System& system;
191}; 213};
@@ -240,6 +262,34 @@ const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
240 return impl->global_scheduler; 262 return impl->global_scheduler;
241} 263}
242 264
265Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
266 return impl->cores[id];
267}
268
269const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
270 return impl->cores[id];
271}
272
273Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
274 return *impl->exclusive_monitor;
275}
276
277const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
278 return *impl->exclusive_monitor;
279}
280
281void KernelCore::InvalidateAllInstructionCaches() {
282 for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) {
283 PhysicalCore(i).ArmInterface().ClearInstructionCache();
284 }
285}
286
287void KernelCore::PrepareReschedule(std::size_t id) {
288 if (id < impl->global_scheduler.CpuCoresCount()) {
289 impl->cores[id].Stop();
290 }
291}
292
243void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) { 293void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
244 impl->named_ports.emplace(std::move(name), std::move(port)); 294 impl->named_ports.emplace(std::move(name), std::move(port));
245} 295}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 3bf0068ed..fccffaf3a 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -11,8 +11,9 @@
11#include "core/hle/kernel/object.h" 11#include "core/hle/kernel/object.h"
12 12
13namespace Core { 13namespace Core {
14class ExclusiveMonitor;
14class System; 15class System;
15} 16} // namespace Core
16 17
17namespace Core::Timing { 18namespace Core::Timing {
18class CoreTiming; 19class CoreTiming;
@@ -25,6 +26,7 @@ class AddressArbiter;
25class ClientPort; 26class ClientPort;
26class GlobalScheduler; 27class GlobalScheduler;
27class HandleTable; 28class HandleTable;
29class PhysicalCore;
28class Process; 30class Process;
29class ResourceLimit; 31class ResourceLimit;
30class Thread; 32class Thread;
@@ -84,6 +86,21 @@ public:
84 /// Gets the sole instance of the global scheduler 86 /// Gets the sole instance of the global scheduler
85 const Kernel::GlobalScheduler& GlobalScheduler() const; 87 const Kernel::GlobalScheduler& GlobalScheduler() const;
86 88
89 /// Gets the an instance of the respective physical CPU core.
90 Kernel::PhysicalCore& PhysicalCore(std::size_t id);
91
92 /// Gets the an instance of the respective physical CPU core.
93 const Kernel::PhysicalCore& PhysicalCore(std::size_t id) const;
94
95 /// Stops execution of 'id' core, in order to reschedule a new thread.
96 void PrepareReschedule(std::size_t id);
97
98 Core::ExclusiveMonitor& GetExclusiveMonitor();
99
100 const Core::ExclusiveMonitor& GetExclusiveMonitor() const;
101
102 void InvalidateAllInstructionCaches();
103
87 /// Adds a port to the named port table 104 /// Adds a port to the named port table
88 void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port); 105 void AddNamedPort(std::string name, std::shared_ptr<ClientPort> port);
89 106
diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp
new file mode 100644
index 000000000..896a1a87a
--- /dev/null
+++ b/src/core/hle/kernel/physical_core.cpp
@@ -0,0 +1,52 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/logging/log.h"
6#include "core/arm/arm_interface.h"
7#ifdef ARCHITECTURE_x86_64
8#include "core/arm/dynarmic/arm_dynarmic.h"
9#endif
10#include "core/arm/exclusive_monitor.h"
11#include "core/arm/unicorn/arm_unicorn.h"
12#include "core/core.h"
13#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/physical_core.h"
15#include "core/hle/kernel/scheduler.h"
16#include "core/hle/kernel/thread.h"
17
18namespace Kernel {
19
20PhysicalCore::PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
21 Core::ExclusiveMonitor& exclusive_monitor)
22 : core_index{id}, kernel{kernel} {
23#ifdef ARCHITECTURE_x86_64
24 arm_interface = std::make_shared<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index);
25#else
26 arm_interface = std::make_shared<Core::ARM_Unicorn>(system);
27 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
28#endif
29
30 scheduler = std::make_shared<Kernel::Scheduler>(system, *arm_interface, core_index);
31}
32
33PhysicalCore::~PhysicalCore() = default;
34
35void PhysicalCore::Run() {
36 arm_interface->Run();
37 arm_interface->ClearExclusiveState();
38}
39
40void PhysicalCore::Step() {
41 arm_interface->Step();
42}
43
44void PhysicalCore::Stop() {
45 arm_interface->PrepareReschedule();
46}
47
48void PhysicalCore::Shutdown() {
49 scheduler->Shutdown();
50}
51
52} // namespace Kernel
diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h
new file mode 100644
index 000000000..fbef0801f
--- /dev/null
+++ b/src/core/hle/kernel/physical_core.h
@@ -0,0 +1,74 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <cstddef>
8#include <memory>
9
10namespace Kernel {
11class Scheduler;
12} // namespace Kernel
13
14namespace Core {
15class ARM_Interface;
16class ExclusiveMonitor;
17class System;
18} // namespace Core
19
20namespace Kernel {
21
22class PhysicalCore {
23public:
24 PhysicalCore(Core::System& system, KernelCore& kernel, std::size_t id,
25 Core::ExclusiveMonitor& exclusive_monitor);
26
27 ~PhysicalCore();
28
29 /// Execute current jit state
30 void Run();
31 /// Execute a single instruction in current jit.
32 void Step();
33 /// Stop JIT execution/exit
34 void Stop();
35
36 // Shutdown this physical core.
37 void Shutdown();
38
39 Core::ARM_Interface& ArmInterface() {
40 return *arm_interface;
41 }
42
43 const Core::ARM_Interface& ArmInterface() const {
44 return *arm_interface;
45 }
46
47 bool IsMainCore() const {
48 return core_index == 0;
49 }
50
51 bool IsSystemCore() const {
52 return core_index == 3;
53 }
54
55 std::size_t CoreIndex() const {
56 return core_index;
57 }
58
59 Kernel::Scheduler& Scheduler() {
60 return *scheduler;
61 }
62
63 const Kernel::Scheduler& Scheduler() const {
64 return *scheduler;
65 }
66
67private:
68 std::size_t core_index;
69 KernelCore& kernel;
70 std::shared_ptr<Core::ARM_Interface> arm_interface;
71 std::shared_ptr<Kernel::Scheduler> scheduler;
72};
73
74} // namespace Kernel
diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp
index d36fcd7d9..eb196a690 100644
--- a/src/core/hle/kernel/scheduler.cpp
+++ b/src/core/hle/kernel/scheduler.cpp
@@ -14,7 +14,6 @@
14#include "common/logging/log.h" 14#include "common/logging/log.h"
15#include "core/arm/arm_interface.h" 15#include "core/arm/arm_interface.h"
16#include "core/core.h" 16#include "core/core.h"
17#include "core/core_cpu.h"
18#include "core/core_timing.h" 17#include "core/core_timing.h"
19#include "core/hle/kernel/kernel.h" 18#include "core/hle/kernel/kernel.h"
20#include "core/hle/kernel/process.h" 19#include "core/hle/kernel/process.h"
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index dbcdb0b88..1d99bf7a2 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -15,7 +15,7 @@
15#include "common/string_util.h" 15#include "common/string_util.h"
16#include "core/arm/exclusive_monitor.h" 16#include "core/arm/exclusive_monitor.h"
17#include "core/core.h" 17#include "core/core.h"
18#include "core/core_cpu.h" 18#include "core/core_manager.h"
19#include "core/core_timing.h" 19#include "core/core_timing.h"
20#include "core/core_timing_util.h" 20#include "core/core_timing_util.h"
21#include "core/hle/kernel/address_arbiter.h" 21#include "core/hle/kernel/address_arbiter.h"
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index e84e5ce0d..e965b5b04 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -13,7 +13,6 @@
13#include "common/thread_queue_list.h" 13#include "common/thread_queue_list.h"
14#include "core/arm/arm_interface.h" 14#include "core/arm/arm_interface.h"
15#include "core/core.h" 15#include "core/core.h"
16#include "core/core_cpu.h"
17#include "core/core_timing.h" 16#include "core/core_timing.h"
18#include "core/core_timing_util.h" 17#include "core/core_timing_util.h"
19#include "core/hle/kernel/errors.h" 18#include "core/hle/kernel/errors.h"
@@ -356,7 +355,7 @@ void Thread::SetActivity(ThreadActivity value) {
356 // Set status if not waiting 355 // Set status if not waiting
357 if (status == ThreadStatus::Ready || status == ThreadStatus::Running) { 356 if (status == ThreadStatus::Ready || status == ThreadStatus::Running) {
358 SetStatus(ThreadStatus::Paused); 357 SetStatus(ThreadStatus::Paused);
359 Core::System::GetInstance().CpuCore(processor_id).PrepareReschedule(); 358 kernel.PrepareReschedule(processor_id);
360 } 359 }
361 } else if (status == ThreadStatus::Paused) { 360 } else if (status == ThreadStatus::Paused) {
362 // Ready to reschedule 361 // Ready to reschedule
diff --git a/src/core/hle/kernel/wait_object.cpp b/src/core/hle/kernel/wait_object.cpp
index 745f2c4e8..a0c806e8f 100644
--- a/src/core/hle/kernel/wait_object.cpp
+++ b/src/core/hle/kernel/wait_object.cpp
@@ -7,7 +7,6 @@
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/logging/log.h" 8#include "common/logging/log.h"
9#include "core/core.h" 9#include "core/core.h"
10#include "core/core_cpu.h"
11#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/object.h" 11#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/process.h" 12#include "core/hle/kernel/process.h"
@@ -96,7 +95,7 @@ void WaitObject::WakeupWaitingThread(std::shared_ptr<Thread> thread) {
96 } 95 }
97 if (resume) { 96 if (resume) {
98 thread->ResumeFromWait(); 97 thread->ResumeFromWait();
99 Core::System::GetInstance().PrepareReschedule(thread->GetProcessorID()); 98 kernel.PrepareReschedule(thread->GetProcessorID());
100 } 99 }
101} 100}
102 101