summaryrefslogtreecommitdiff
path: root/src/core/arm
diff options
context:
space:
mode:
authorGravatar Fernando Sahmkow2020-02-24 22:04:12 -0400
committerGravatar Fernando Sahmkow2020-06-27 11:35:06 -0400
commite31425df3877636c098ec7426ebd2067920715cb (patch)
tree5c0fc518a4ebb8413c491b43a9fdd99450c7bd80 /src/core/arm
parentMerge pull request #3396 from FernandoS27/prometheus-1 (diff)
downloadyuzu-e31425df3877636c098ec7426ebd2067920715cb.tar.gz
yuzu-e31425df3877636c098ec7426ebd2067920715cb.tar.xz
yuzu-e31425df3877636c098ec7426ebd2067920715cb.zip
General: Recover Prometheus project from harddrive failure
This commit: Implements CPU Interrupts, Replaces Cycle Timing for Host Timing, Reworks the Kernel's Scheduler, Introduce Idle State and Suspended State, Recreates the bootmanager, Initializes Multicore system.
Diffstat (limited to 'src/core/arm')
-rw-r--r--src/core/arm/arm_interface.h5
-rw-r--r--src/core/arm/cpu_interrupt_handler.cpp29
-rw-r--r--src/core/arm/cpu_interrupt_handler.h39
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp6
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h4
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp28
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h4
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp14
-rw-r--r--src/core/arm/unicorn/arm_unicorn.h3
9 files changed, 103 insertions, 29 deletions
diff --git a/src/core/arm/arm_interface.h b/src/core/arm/arm_interface.h
index cb2e640e2..87a1c29cc 100644
--- a/src/core/arm/arm_interface.h
+++ b/src/core/arm/arm_interface.h
@@ -18,11 +18,13 @@ enum class VMAPermission : u8;
18 18
19namespace Core { 19namespace Core {
20class System; 20class System;
21class CPUInterruptHandler;
21 22
22/// Generic ARMv8 CPU interface 23/// Generic ARMv8 CPU interface
23class ARM_Interface : NonCopyable { 24class ARM_Interface : NonCopyable {
24public: 25public:
25 explicit ARM_Interface(System& system_) : system{system_} {} 26 explicit ARM_Interface(System& system_, CPUInterruptHandler& interrupt_handler)
27 : system{system_}, interrupt_handler{interrupt_handler} {}
26 virtual ~ARM_Interface() = default; 28 virtual ~ARM_Interface() = default;
27 29
28 struct ThreadContext32 { 30 struct ThreadContext32 {
@@ -175,6 +177,7 @@ public:
175protected: 177protected:
176 /// System context that this ARM interface is running under. 178 /// System context that this ARM interface is running under.
177 System& system; 179 System& system;
180 CPUInterruptHandler& interrupt_handler;
178}; 181};
179 182
180} // namespace Core 183} // namespace Core
diff --git a/src/core/arm/cpu_interrupt_handler.cpp b/src/core/arm/cpu_interrupt_handler.cpp
new file mode 100644
index 000000000..2f1a1a269
--- /dev/null
+++ b/src/core/arm/cpu_interrupt_handler.cpp
@@ -0,0 +1,29 @@
1// Copyright 2020 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 "common/thread.h"
8#include "core/arm/cpu_interrupt_handler.h"
9
10namespace Core {
11
12CPUInterruptHandler::CPUInterruptHandler() : is_interrupted{} {
13 interrupt_event = std::make_unique<Common::Event>();
14}
15
16CPUInterruptHandler::~CPUInterruptHandler() = default;
17
18void CPUInterruptHandler::SetInterrupt(bool is_interrupted_) {
19 if (is_interrupted_) {
20 interrupt_event->Set();
21 }
22 this->is_interrupted = is_interrupted_;
23}
24
25void CPUInterruptHandler::AwaitInterrupt() {
26 interrupt_event->Wait();
27}
28
29} // namespace Core
diff --git a/src/core/arm/cpu_interrupt_handler.h b/src/core/arm/cpu_interrupt_handler.h
new file mode 100644
index 000000000..91c31a271
--- /dev/null
+++ b/src/core/arm/cpu_interrupt_handler.h
@@ -0,0 +1,39 @@
1// Copyright 2020 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 <memory>
8
9namespace Common {
10class Event;
11}
12
13namespace Core {
14
15class CPUInterruptHandler {
16public:
17 CPUInterruptHandler();
18 ~CPUInterruptHandler();
19
20 CPUInterruptHandler(const CPUInterruptHandler&) = delete;
21 CPUInterruptHandler& operator=(const CPUInterruptHandler&) = delete;
22
23 CPUInterruptHandler(CPUInterruptHandler&&) = default;
24 CPUInterruptHandler& operator=(CPUInterruptHandler&&) = default;
25
26 constexpr bool IsInterrupted() const {
27 return is_interrupted;
28 }
29
30 void SetInterrupt(bool is_interrupted);
31
32 void AwaitInterrupt();
33
34private:
35 bool is_interrupted{};
36 std::unique_ptr<Common::Event> interrupt_event;
37};
38
39} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 4c8663d03..0b7aa6a69 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -114,9 +114,9 @@ void ARM_Dynarmic_32::Step() {
114 jit->Step(); 114 jit->Step();
115} 115}
116 116
117ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, 117ARM_Dynarmic_32::ARM_Dynarmic_32(System& system, CPUInterruptHandler& interrupt_handler,
118 std::size_t core_index) 118 ExclusiveMonitor& exclusive_monitor, std::size_t core_index)
119 : ARM_Interface{system}, cb(std::make_unique<DynarmicCallbacks32>(*this)), 119 : ARM_Interface{system, interrupt_handler}, cb(std::make_unique<DynarmicCallbacks32>(*this)),
120 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index}, 120 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index},
121 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} 121 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
122 122
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index e5b92d7bb..1e7e17e64 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -21,6 +21,7 @@ class Memory;
21 21
22namespace Core { 22namespace Core {
23 23
24class CPUInterruptHandler;
24class DynarmicCallbacks32; 25class DynarmicCallbacks32;
25class DynarmicCP15; 26class DynarmicCP15;
26class DynarmicExclusiveMonitor; 27class DynarmicExclusiveMonitor;
@@ -28,7 +29,8 @@ class System;
28 29
29class ARM_Dynarmic_32 final : public ARM_Interface { 30class ARM_Dynarmic_32 final : public ARM_Interface {
30public: 31public:
31 ARM_Dynarmic_32(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); 32 ARM_Dynarmic_32(System& system, CPUInterruptHandler& interrupt_handler,
33 ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
32 ~ARM_Dynarmic_32() override; 34 ~ARM_Dynarmic_32() override;
33 35
34 void SetPC(u64 pc) override; 36 void SetPC(u64 pc) override;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 5f5e36d94..5e316ffd4 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -9,6 +9,7 @@
9#include "common/logging/log.h" 9#include "common/logging/log.h"
10#include "common/microprofile.h" 10#include "common/microprofile.h"
11#include "common/page_table.h" 11#include "common/page_table.h"
12#include "core/arm/cpu_interrupt_handler.h"
12#include "core/arm/dynarmic/arm_dynarmic_64.h" 13#include "core/arm/dynarmic/arm_dynarmic_64.h"
13#include "core/core.h" 14#include "core/core.h"
14#include "core/core_manager.h" 15#include "core/core_manager.h"
@@ -108,23 +109,16 @@ public:
108 } 109 }
109 110
110 void AddTicks(u64 ticks) override { 111 void AddTicks(u64 ticks) override {
111 // Divide the number of ticks by the amount of CPU cores. TODO(Subv): This yields only a 112 /// We are using host timing, NOP
112 // rough approximation of the amount of executed ticks in the system, it may be thrown off
113 // if not all cores are doing a similar amount of work. Instead of doing this, we should
114 // device a way so that timing is consistent across all cores without increasing the ticks 4
115 // times.
116 u64 amortized_ticks = (ticks - num_interpreted_instructions) / Core::NUM_CPU_CORES;
117 // Always execute at least one tick.
118 amortized_ticks = std::max<u64>(amortized_ticks, 1);
119
120 parent.system.CoreTiming().AddTicks(amortized_ticks);
121 num_interpreted_instructions = 0;
122 } 113 }
123 u64 GetTicksRemaining() override { 114 u64 GetTicksRemaining() override {
124 return std::max(parent.system.CoreTiming().GetDowncount(), s64{0}); 115 if (!parent.interrupt_handler.IsInterrupted()) {
116 return 1000ULL;
117 }
118 return 0ULL;
125 } 119 }
126 u64 GetCNTPCT() override { 120 u64 GetCNTPCT() override {
127 return Timing::CpuCyclesToClockCycles(parent.system.CoreTiming().GetTicks()); 121 return parent.system.CoreTiming().GetClockTicks();
128 } 122 }
129 123
130 ARM_Dynarmic_64& parent; 124 ARM_Dynarmic_64& parent;
@@ -183,10 +177,10 @@ void ARM_Dynarmic_64::Step() {
183 cb->InterpreterFallback(jit->GetPC(), 1); 177 cb->InterpreterFallback(jit->GetPC(), 1);
184} 178}
185 179
186ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, 180ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterruptHandler& interrupt_handler,
187 std::size_t core_index) 181 ExclusiveMonitor& exclusive_monitor, std::size_t core_index)
188 : ARM_Interface{system}, cb(std::make_unique<DynarmicCallbacks64>(*this)), 182 : ARM_Interface{system, interrupt_handler}, cb(std::make_unique<DynarmicCallbacks64>(*this)),
189 inner_unicorn{system, ARM_Unicorn::Arch::AArch64}, core_index{core_index}, 183 inner_unicorn{system, interrupt_handler, ARM_Unicorn::Arch::AArch64}, core_index{core_index},
190 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {} 184 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
191 185
192ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; 186ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 647cecaf0..9e94b58c2 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -22,12 +22,14 @@ class Memory;
22namespace Core { 22namespace Core {
23 23
24class DynarmicCallbacks64; 24class DynarmicCallbacks64;
25class CPUInterruptHandler;
25class DynarmicExclusiveMonitor; 26class DynarmicExclusiveMonitor;
26class System; 27class System;
27 28
28class ARM_Dynarmic_64 final : public ARM_Interface { 29class ARM_Dynarmic_64 final : public ARM_Interface {
29public: 30public:
30 ARM_Dynarmic_64(System& system, ExclusiveMonitor& exclusive_monitor, std::size_t core_index); 31 ARM_Dynarmic_64(System& system, CPUInterruptHandler& interrupt_handler,
32 ExclusiveMonitor& exclusive_monitor, std::size_t core_index);
31 ~ARM_Dynarmic_64() override; 33 ~ARM_Dynarmic_64() override;
32 34
33 void SetPC(u64 pc) override; 35 void SetPC(u64 pc) override;
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index e40e9626a..0393fe641 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -6,6 +6,7 @@
6#include <unicorn/arm64.h> 6#include <unicorn/arm64.h>
7#include "common/assert.h" 7#include "common/assert.h"
8#include "common/microprofile.h" 8#include "common/microprofile.h"
9#include "core/arm/cpu_interrupt_handler.h"
9#include "core/arm/unicorn/arm_unicorn.h" 10#include "core/arm/unicorn/arm_unicorn.h"
10#include "core/core.h" 11#include "core/core.h"
11#include "core/core_timing.h" 12#include "core/core_timing.h"
@@ -62,7 +63,8 @@ static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int si
62 return false; 63 return false;
63} 64}
64 65
65ARM_Unicorn::ARM_Unicorn(System& system, Arch architecture) : ARM_Interface{system} { 66ARM_Unicorn::ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, Arch architecture)
67 : ARM_Interface{system, interrupt_handler} {
66 const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64; 68 const auto arch = architecture == Arch::AArch32 ? UC_ARCH_ARM : UC_ARCH_ARM64;
67 CHECKED(uc_open(arch, UC_MODE_ARM, &uc)); 69 CHECKED(uc_open(arch, UC_MODE_ARM, &uc));
68 70
@@ -160,8 +162,12 @@ void ARM_Unicorn::Run() {
160 if (GDBStub::IsServerEnabled()) { 162 if (GDBStub::IsServerEnabled()) {
161 ExecuteInstructions(std::max(4000000U, 0U)); 163 ExecuteInstructions(std::max(4000000U, 0U));
162 } else { 164 } else {
163 ExecuteInstructions( 165 while (true) {
164 std::max(std::size_t(system.CoreTiming().GetDowncount()), std::size_t{0})); 166 if (interrupt_handler.IsInterrupted()) {
167 return;
168 }
169 ExecuteInstructions(10);
170 }
165 } 171 }
166} 172}
167 173
@@ -183,8 +189,6 @@ void ARM_Unicorn::ExecuteInstructions(std::size_t num_instructions) {
183 UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, page_buffer.data())); 189 UC_PROT_READ | UC_PROT_WRITE | UC_PROT_EXEC, page_buffer.data()));
184 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions)); 190 CHECKED(uc_emu_start(uc, GetPC(), 1ULL << 63, 0, num_instructions));
185 CHECKED(uc_mem_unmap(uc, map_addr, page_buffer.size())); 191 CHECKED(uc_mem_unmap(uc, map_addr, page_buffer.size()));
186
187 system.CoreTiming().AddTicks(num_instructions);
188 if (GDBStub::IsServerEnabled()) { 192 if (GDBStub::IsServerEnabled()) {
189 if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) { 193 if (last_bkpt_hit && last_bkpt.type == GDBStub::BreakpointType::Execute) {
190 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address); 194 uc_reg_write(uc, UC_ARM64_REG_PC, &last_bkpt.address);
diff --git a/src/core/arm/unicorn/arm_unicorn.h b/src/core/arm/unicorn/arm_unicorn.h
index 725c65085..0a4c087cd 100644
--- a/src/core/arm/unicorn/arm_unicorn.h
+++ b/src/core/arm/unicorn/arm_unicorn.h
@@ -11,6 +11,7 @@
11 11
12namespace Core { 12namespace Core {
13 13
14class CPUInterruptHandler;
14class System; 15class System;
15 16
16class ARM_Unicorn final : public ARM_Interface { 17class ARM_Unicorn final : public ARM_Interface {
@@ -20,7 +21,7 @@ public:
20 AArch64, // 64-bit ARM 21 AArch64, // 64-bit ARM
21 }; 22 };
22 23
23 explicit ARM_Unicorn(System& system, Arch architecture); 24 explicit ARM_Unicorn(System& system, CPUInterruptHandler& interrupt_handler, Arch architecture);
24 ~ARM_Unicorn() override; 25 ~ARM_Unicorn() override;
25 26
26 void SetPC(u64 pc) override; 27 void SetPC(u64 pc) override;