diff options
| author | 2020-01-30 18:13:59 -0500 | |
|---|---|---|
| committer | 2020-01-30 18:13:59 -0500 | |
| commit | 985d0f35e55f0752c6e147d0140b367708499cb4 (patch) | |
| tree | 119249aee3acc2cc2ee6a5d391288b52c126765b | |
| parent | Merge pull request #3151 from FearlessTobi/fix-korean (diff) | |
| parent | System: Address Feedback (diff) | |
| download | yuzu-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.txt | 10 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 2 | ||||
| -rw-r--r-- | src/core/arm/exclusive_monitor.cpp | 14 | ||||
| -rw-r--r-- | src/core/arm/exclusive_monitor.h | 9 | ||||
| -rw-r--r-- | src/core/core.cpp | 75 | ||||
| -rw-r--r-- | src/core/core.h | 10 | ||||
| -rw-r--r-- | src/core/core_cpu.cpp | 127 | ||||
| -rw-r--r-- | src/core/core_cpu.h | 120 | ||||
| -rw-r--r-- | src/core/core_manager.cpp | 70 | ||||
| -rw-r--r-- | src/core/core_manager.h | 63 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.cpp | 152 | ||||
| -rw-r--r-- | src/core/cpu_core_manager.h | 62 | ||||
| -rw-r--r-- | src/core/cpu_manager.cpp | 83 | ||||
| -rw-r--r-- | src/core/cpu_manager.h | 50 | ||||
| -rw-r--r-- | src/core/gdbstub/gdbstub.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/address_arbiter.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/kernel/kernel.h | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 52 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.h | 74 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 1 | ||||
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/wait_object.cpp | 3 |
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 | ||
| 7 | namespace Core { | 11 | namespace Core { |
| 8 | 12 | ||
| 9 | ExclusiveMonitor::~ExclusiveMonitor() = default; | 13 | ExclusiveMonitor::~ExclusiveMonitor() = default; |
| 10 | 14 | ||
| 15 | std::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 | ||
| 11 | namespace Memory { | ||
| 12 | class Memory; | ||
| 13 | } | ||
| 14 | |||
| 9 | namespace Core { | 15 | namespace Core { |
| 10 | 16 | ||
| 11 | class ExclusiveMonitor { | 17 | class 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 | ||
| 31 | std::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, | |||
| 113 | struct System::Impl { | 114 | struct 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 { | |||
| 377 | System::System() : impl{std::make_unique<Impl>(*this)} {} | 386 | System::System() : impl{std::make_unique<Impl>(*this)} {} |
| 378 | System::~System() = default; | 387 | System::~System() = default; |
| 379 | 388 | ||
| 380 | Cpu& System::CurrentCpuCore() { | 389 | CoreManager& System::CurrentCoreManager() { |
| 381 | return impl->CurrentCpuCore(); | 390 | return impl->CurrentCoreManager(); |
| 382 | } | 391 | } |
| 383 | 392 | ||
| 384 | const Cpu& System::CurrentCpuCore() const { | 393 | const CoreManager& System::CurrentCoreManager() const { |
| 385 | return impl->CurrentCpuCore(); | 394 | return impl->CurrentCoreManager(); |
| 386 | } | 395 | } |
| 387 | 396 | ||
| 388 | System::ResultStatus System::RunLoop(bool tight_loop) { | 397 | System::ResultStatus System::RunLoop(bool tight_loop) { |
| @@ -394,7 +403,7 @@ System::ResultStatus System::SingleStep() { | |||
| 394 | } | 403 | } |
| 395 | 404 | ||
| 396 | void System::InvalidateCpuInstructionCaches() { | 405 | void System::InvalidateCpuInstructionCaches() { |
| 397 | impl->cpu_core_manager.InvalidateAllInstructionCaches(); | 406 | impl->kernel.InvalidateAllInstructionCaches(); |
| 398 | } | 407 | } |
| 399 | 408 | ||
| 400 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { | 409 | System::ResultStatus System::Load(Frontend::EmuWindow& emu_window, const std::string& filepath) { |
| @@ -406,13 +415,11 @@ bool System::IsPoweredOn() const { | |||
| 406 | } | 415 | } |
| 407 | 416 | ||
| 408 | void System::PrepareReschedule() { | 417 | void System::PrepareReschedule() { |
| 409 | CurrentCpuCore().PrepareReschedule(); | 418 | impl->CurrentPhysicalCore().Stop(); |
| 410 | } | 419 | } |
| 411 | 420 | ||
| 412 | void System::PrepareReschedule(const u32 core_index) { | 421 | void 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 | ||
| 418 | PerfStatsResults System::GetAndResetPerfStats() { | 425 | PerfStatsResults System::GetAndResetPerfStats() { |
| @@ -428,31 +435,31 @@ const TelemetrySession& System::TelemetrySession() const { | |||
| 428 | } | 435 | } |
| 429 | 436 | ||
| 430 | ARM_Interface& System::CurrentArmInterface() { | 437 | ARM_Interface& System::CurrentArmInterface() { |
| 431 | return CurrentCpuCore().ArmInterface(); | 438 | return impl->CurrentPhysicalCore().ArmInterface(); |
| 432 | } | 439 | } |
| 433 | 440 | ||
| 434 | const ARM_Interface& System::CurrentArmInterface() const { | 441 | const ARM_Interface& System::CurrentArmInterface() const { |
| 435 | return CurrentCpuCore().ArmInterface(); | 442 | return impl->CurrentPhysicalCore().ArmInterface(); |
| 436 | } | 443 | } |
| 437 | 444 | ||
| 438 | std::size_t System::CurrentCoreIndex() const { | 445 | std::size_t System::CurrentCoreIndex() const { |
| 439 | return CurrentCpuCore().CoreIndex(); | 446 | return impl->cpu_manager.GetActiveCoreIndex(); |
| 440 | } | 447 | } |
| 441 | 448 | ||
| 442 | Kernel::Scheduler& System::CurrentScheduler() { | 449 | Kernel::Scheduler& System::CurrentScheduler() { |
| 443 | return CurrentCpuCore().Scheduler(); | 450 | return impl->CurrentPhysicalCore().Scheduler(); |
| 444 | } | 451 | } |
| 445 | 452 | ||
| 446 | const Kernel::Scheduler& System::CurrentScheduler() const { | 453 | const Kernel::Scheduler& System::CurrentScheduler() const { |
| 447 | return CurrentCpuCore().Scheduler(); | 454 | return impl->CurrentPhysicalCore().Scheduler(); |
| 448 | } | 455 | } |
| 449 | 456 | ||
| 450 | Kernel::Scheduler& System::Scheduler(std::size_t core_index) { | 457 | Kernel::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 | ||
| 454 | const Kernel::Scheduler& System::Scheduler(std::size_t core_index) const { | 461 | const 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 | ||
| 476 | ARM_Interface& System::ArmInterface(std::size_t core_index) { | 483 | ARM_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 | ||
| 480 | const ARM_Interface& System::ArmInterface(std::size_t core_index) const { | 487 | const 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 | ||
| 484 | Cpu& System::CpuCore(std::size_t core_index) { | 491 | CoreManager& 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 | ||
| 488 | const Cpu& System::CpuCore(std::size_t core_index) const { | 495 | const 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 | ||
| 493 | ExclusiveMonitor& System::Monitor() { | 500 | ExclusiveMonitor& System::Monitor() { |
| 494 | return impl->cpu_core_manager.GetExclusiveMonitor(); | 501 | return impl->kernel.GetExclusiveMonitor(); |
| 495 | } | 502 | } |
| 496 | 503 | ||
| 497 | const ExclusiveMonitor& System::Monitor() const { | 504 | const ExclusiveMonitor& System::Monitor() const { |
| 498 | return impl->cpu_core_manager.GetExclusiveMonitor(); | 505 | return impl->kernel.GetExclusiveMonitor(); |
| 499 | } | 506 | } |
| 500 | 507 | ||
| 501 | Memory::Memory& System::Memory() { | 508 | Memory::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; | |||
| 93 | namespace Core { | 93 | namespace Core { |
| 94 | 94 | ||
| 95 | class ARM_Interface; | 95 | class ARM_Interface; |
| 96 | class Cpu; | 96 | class CoreManager; |
| 97 | class ExclusiveMonitor; | 97 | class ExclusiveMonitor; |
| 98 | class FrameLimiter; | 98 | class FrameLimiter; |
| 99 | class PerfStats; | 99 | class 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 | |||
| 22 | namespace Core { | ||
| 23 | |||
| 24 | void CpuBarrier::NotifyEnd() { | ||
| 25 | std::unique_lock lock{mutex}; | ||
| 26 | end = true; | ||
| 27 | condition.notify_all(); | ||
| 28 | } | ||
| 29 | |||
| 30 | bool 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 | |||
| 53 | Cpu::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 | |||
| 67 | Cpu::~Cpu() = default; | ||
| 68 | |||
| 69 | std::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 | |||
| 79 | void 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 | |||
| 107 | void Cpu::SingleStep() { | ||
| 108 | return RunLoop(false); | ||
| 109 | } | ||
| 110 | |||
| 111 | void Cpu::PrepareReschedule() { | ||
| 112 | arm_interface->PrepareReschedule(); | ||
| 113 | } | ||
| 114 | |||
| 115 | void 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 | |||
| 123 | void 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 | |||
| 14 | namespace Kernel { | ||
| 15 | class GlobalScheduler; | ||
| 16 | class Scheduler; | ||
| 17 | } // namespace Kernel | ||
| 18 | |||
| 19 | namespace Core { | ||
| 20 | class System; | ||
| 21 | } | ||
| 22 | |||
| 23 | namespace Core::Timing { | ||
| 24 | class CoreTiming; | ||
| 25 | } | ||
| 26 | |||
| 27 | namespace Memory { | ||
| 28 | class Memory; | ||
| 29 | } | ||
| 30 | |||
| 31 | namespace Core { | ||
| 32 | |||
| 33 | class ARM_Interface; | ||
| 34 | class ExclusiveMonitor; | ||
| 35 | |||
| 36 | constexpr unsigned NUM_CPU_CORES{4}; | ||
| 37 | |||
| 38 | class CpuBarrier { | ||
| 39 | public: | ||
| 40 | bool IsAlive() const { | ||
| 41 | return !end; | ||
| 42 | } | ||
| 43 | |||
| 44 | void NotifyEnd(); | ||
| 45 | |||
| 46 | bool Rendezvous(); | ||
| 47 | |||
| 48 | private: | ||
| 49 | unsigned cores_waiting{NUM_CPU_CORES}; | ||
| 50 | std::mutex mutex; | ||
| 51 | std::condition_variable condition; | ||
| 52 | std::atomic<bool> end{}; | ||
| 53 | }; | ||
| 54 | |||
| 55 | class Cpu { | ||
| 56 | public: | ||
| 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 | |||
| 107 | private: | ||
| 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 | |||
| 24 | namespace Core { | ||
| 25 | |||
| 26 | CoreManager::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 | |||
| 31 | CoreManager::~CoreManager() = default; | ||
| 32 | |||
| 33 | void 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 | |||
| 53 | void CoreManager::SingleStep() { | ||
| 54 | return RunLoop(false); | ||
| 55 | } | ||
| 56 | |||
| 57 | void CoreManager::PrepareReschedule() { | ||
| 58 | physical_core.Stop(); | ||
| 59 | } | ||
| 60 | |||
| 61 | void 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 | |||
| 12 | namespace Kernel { | ||
| 13 | class GlobalScheduler; | ||
| 14 | class PhysicalCore; | ||
| 15 | } // namespace Kernel | ||
| 16 | |||
| 17 | namespace Core { | ||
| 18 | class System; | ||
| 19 | } | ||
| 20 | |||
| 21 | namespace Core::Timing { | ||
| 22 | class CoreTiming; | ||
| 23 | } | ||
| 24 | |||
| 25 | namespace Memory { | ||
| 26 | class Memory; | ||
| 27 | } | ||
| 28 | |||
| 29 | namespace Core { | ||
| 30 | |||
| 31 | constexpr unsigned NUM_CPU_CORES{4}; | ||
| 32 | |||
| 33 | class CoreManager { | ||
| 34 | public: | ||
| 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 | |||
| 52 | private: | ||
| 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 | |||
| 14 | namespace Core { | ||
| 15 | namespace { | ||
| 16 | void RunCpuCore(const System& system, Cpu& cpu_state) { | ||
| 17 | while (system.IsPoweredOn()) { | ||
| 18 | cpu_state.RunLoop(true); | ||
| 19 | } | ||
| 20 | } | ||
| 21 | } // Anonymous namespace | ||
| 22 | |||
| 23 | CpuCoreManager::CpuCoreManager(System& system) : system{system} {} | ||
| 24 | CpuCoreManager::~CpuCoreManager() = default; | ||
| 25 | |||
| 26 | void 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 | |||
| 35 | void 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 | |||
| 50 | void 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 | |||
| 69 | Cpu& CpuCoreManager::GetCore(std::size_t index) { | ||
| 70 | return *cores.at(index); | ||
| 71 | } | ||
| 72 | |||
| 73 | const Cpu& CpuCoreManager::GetCore(std::size_t index) const { | ||
| 74 | return *cores.at(index); | ||
| 75 | } | ||
| 76 | |||
| 77 | ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() { | ||
| 78 | return *exclusive_monitor; | ||
| 79 | } | ||
| 80 | |||
| 81 | const ExclusiveMonitor& CpuCoreManager::GetExclusiveMonitor() const { | ||
| 82 | return *exclusive_monitor; | ||
| 83 | } | ||
| 84 | |||
| 85 | Cpu& 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 | |||
| 97 | const 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 | |||
| 109 | void 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 | |||
| 146 | void 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 | |||
| 12 | namespace Core { | ||
| 13 | |||
| 14 | class Cpu; | ||
| 15 | class CpuBarrier; | ||
| 16 | class ExclusiveMonitor; | ||
| 17 | class System; | ||
| 18 | |||
| 19 | class CpuCoreManager { | ||
| 20 | public: | ||
| 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 | |||
| 47 | private: | ||
| 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 | |||
| 14 | namespace Core { | ||
| 15 | |||
| 16 | CpuManager::CpuManager(System& system) : system{system} {} | ||
| 17 | CpuManager::~CpuManager() = default; | ||
| 18 | |||
| 19 | void 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 | |||
| 25 | void CpuManager::Shutdown() { | ||
| 26 | for (auto& cpu_core : core_managers) { | ||
| 27 | cpu_core.reset(); | ||
| 28 | } | ||
| 29 | } | ||
| 30 | |||
| 31 | CoreManager& CpuManager::GetCoreManager(std::size_t index) { | ||
| 32 | return *core_managers.at(index); | ||
| 33 | } | ||
| 34 | |||
| 35 | const CoreManager& CpuManager::GetCoreManager(std::size_t index) const { | ||
| 36 | return *core_managers.at(index); | ||
| 37 | } | ||
| 38 | |||
| 39 | CoreManager& CpuManager::GetCurrentCoreManager() { | ||
| 40 | // Otherwise, use single-threaded mode active_core variable | ||
| 41 | return *core_managers[active_core]; | ||
| 42 | } | ||
| 43 | |||
| 44 | const CoreManager& CpuManager::GetCurrentCoreManager() const { | ||
| 45 | // Otherwise, use single-threaded mode active_core variable | ||
| 46 | return *core_managers[active_core]; | ||
| 47 | } | ||
| 48 | |||
| 49 | void 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 | |||
| 10 | namespace Core { | ||
| 11 | |||
| 12 | class CoreManager; | ||
| 13 | class System; | ||
| 14 | |||
| 15 | class CpuManager { | ||
| 16 | public: | ||
| 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 | |||
| 41 | private: | ||
| 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 | ||
| 265 | Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) { | ||
| 266 | return impl->cores[id]; | ||
| 267 | } | ||
| 268 | |||
| 269 | const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const { | ||
| 270 | return impl->cores[id]; | ||
| 271 | } | ||
| 272 | |||
| 273 | Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { | ||
| 274 | return *impl->exclusive_monitor; | ||
| 275 | } | ||
| 276 | |||
| 277 | const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { | ||
| 278 | return *impl->exclusive_monitor; | ||
| 279 | } | ||
| 280 | |||
| 281 | void KernelCore::InvalidateAllInstructionCaches() { | ||
| 282 | for (std::size_t i = 0; i < impl->global_scheduler.CpuCoresCount(); i++) { | ||
| 283 | PhysicalCore(i).ArmInterface().ClearInstructionCache(); | ||
| 284 | } | ||
| 285 | } | ||
| 286 | |||
| 287 | void KernelCore::PrepareReschedule(std::size_t id) { | ||
| 288 | if (id < impl->global_scheduler.CpuCoresCount()) { | ||
| 289 | impl->cores[id].Stop(); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 243 | void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) { | 293 | void 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 | ||
| 13 | namespace Core { | 13 | namespace Core { |
| 14 | class ExclusiveMonitor; | ||
| 14 | class System; | 15 | class System; |
| 15 | } | 16 | } // namespace Core |
| 16 | 17 | ||
| 17 | namespace Core::Timing { | 18 | namespace Core::Timing { |
| 18 | class CoreTiming; | 19 | class CoreTiming; |
| @@ -25,6 +26,7 @@ class AddressArbiter; | |||
| 25 | class ClientPort; | 26 | class ClientPort; |
| 26 | class GlobalScheduler; | 27 | class GlobalScheduler; |
| 27 | class HandleTable; | 28 | class HandleTable; |
| 29 | class PhysicalCore; | ||
| 28 | class Process; | 30 | class Process; |
| 29 | class ResourceLimit; | 31 | class ResourceLimit; |
| 30 | class Thread; | 32 | class 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 | |||
| 18 | namespace Kernel { | ||
| 19 | |||
| 20 | PhysicalCore::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 | |||
| 33 | PhysicalCore::~PhysicalCore() = default; | ||
| 34 | |||
| 35 | void PhysicalCore::Run() { | ||
| 36 | arm_interface->Run(); | ||
| 37 | arm_interface->ClearExclusiveState(); | ||
| 38 | } | ||
| 39 | |||
| 40 | void PhysicalCore::Step() { | ||
| 41 | arm_interface->Step(); | ||
| 42 | } | ||
| 43 | |||
| 44 | void PhysicalCore::Stop() { | ||
| 45 | arm_interface->PrepareReschedule(); | ||
| 46 | } | ||
| 47 | |||
| 48 | void 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 | |||
| 10 | namespace Kernel { | ||
| 11 | class Scheduler; | ||
| 12 | } // namespace Kernel | ||
| 13 | |||
| 14 | namespace Core { | ||
| 15 | class ARM_Interface; | ||
| 16 | class ExclusiveMonitor; | ||
| 17 | class System; | ||
| 18 | } // namespace Core | ||
| 19 | |||
| 20 | namespace Kernel { | ||
| 21 | |||
| 22 | class PhysicalCore { | ||
| 23 | public: | ||
| 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 | |||
| 67 | private: | ||
| 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 | ||