summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp67
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h30
-rw-r--r--src/core/arm/exclusive_monitor.cpp7
-rw-r--r--src/core/arm/exclusive_monitor.h23
-rw-r--r--src/core/core.cpp3
-rw-r--r--src/core/core.h12
-rw-r--r--src/core/core_cpu.cpp19
-rw-r--r--src/core/core_cpu.h10
9 files changed, 160 insertions, 13 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 0a5d58eea..27a5de7fd 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -1,5 +1,7 @@
1add_library(core STATIC 1add_library(core STATIC
2 arm/arm_interface.h 2 arm/arm_interface.h
3 arm/exclusive_monitor.cpp
4 arm/exclusive_monitor.h
3 arm/unicorn/arm_unicorn.cpp 5 arm/unicorn/arm_unicorn.cpp
4 arm/unicorn/arm_unicorn.h 6 arm/unicorn/arm_unicorn.h
5 core.cpp 7 core.cpp
diff --git a/src/core/arm/dynarmic/arm_dynarmic.cpp b/src/core/arm/dynarmic/arm_dynarmic.cpp
index 5d7efc9b6..83c09db2b 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic.cpp
@@ -102,18 +102,28 @@ public:
102 u64 tpidr_el0 = 0; 102 u64 tpidr_el0 = 0;
103}; 103};
104 104
105std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) { 105std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
106 const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data(); 106 const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
107 107
108 Dynarmic::A64::UserConfig config; 108 Dynarmic::A64::UserConfig config;
109
110 // Callbacks
109 config.callbacks = cb.get(); 111 config.callbacks = cb.get();
112
113 // Memory
114 config.page_table = reinterpret_cast<void**>(page_table);
115 config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
116 config.silently_mirror_page_table = false;
117
118 // Multi-process state
119 config.processor_id = core_index;
120 config.global_monitor = &exclusive_monitor->monitor;
121
122 // System registers
110 config.tpidrro_el0 = &cb->tpidrro_el0; 123 config.tpidrro_el0 = &cb->tpidrro_el0;
111 config.tpidr_el0 = &cb->tpidr_el0; 124 config.tpidr_el0 = &cb->tpidr_el0;
112 config.dczid_el0 = 4; 125 config.dczid_el0 = 4;
113 config.ctr_el0 = 0x8444c004; 126 config.ctr_el0 = 0x8444c004;
114 config.page_table = reinterpret_cast<void**>(page_table);
115 config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
116 config.silently_mirror_page_table = false;
117 127
118 return std::make_unique<Dynarmic::A64::Jit>(config); 128 return std::make_unique<Dynarmic::A64::Jit>(config);
119} 129}
@@ -128,8 +138,11 @@ void ARM_Dynarmic::Step() {
128 cb->InterpreterFallback(jit->GetPC(), 1); 138 cb->InterpreterFallback(jit->GetPC(), 1);
129} 139}
130 140
131ARM_Dynarmic::ARM_Dynarmic() 141ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
132 : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) { 142 : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
143 jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
144 exclusive_monitor)},
145 core_index{core_index} {
133 ARM_Interface::ThreadContext ctx; 146 ARM_Interface::ThreadContext ctx;
134 inner_unicorn.SaveContext(ctx); 147 inner_unicorn.SaveContext(ctx);
135 LoadContext(ctx); 148 LoadContext(ctx);
@@ -237,6 +250,46 @@ void ARM_Dynarmic::ClearExclusiveState() {
237} 250}
238 251
239void ARM_Dynarmic::PageTableChanged() { 252void ARM_Dynarmic::PageTableChanged() {
240 jit = MakeJit(cb); 253 jit = MakeJit();
241 current_page_table = Memory::GetCurrentPageTable(); 254 current_page_table = Memory::GetCurrentPageTable();
242} 255}
256
257DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {}
258DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
259
260void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) {
261 // Size doesn't actually matter.
262 monitor.Mark(core_index, addr, 16);
263}
264
265void DynarmicExclusiveMonitor::ClearExclusive() {
266 monitor.Clear();
267}
268
269bool DynarmicExclusiveMonitor::ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) {
270 return monitor.DoExclusiveOperation(core_index, vaddr, 1,
271 [&] { Memory::Write8(vaddr, value); });
272}
273
274bool DynarmicExclusiveMonitor::ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) {
275 return monitor.DoExclusiveOperation(core_index, vaddr, 2,
276 [&] { Memory::Write16(vaddr, value); });
277}
278
279bool DynarmicExclusiveMonitor::ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) {
280 return monitor.DoExclusiveOperation(core_index, vaddr, 4,
281 [&] { Memory::Write32(vaddr, value); });
282}
283
284bool DynarmicExclusiveMonitor::ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) {
285 return monitor.DoExclusiveOperation(core_index, vaddr, 8,
286 [&] { Memory::Write64(vaddr, value); });
287}
288
289bool DynarmicExclusiveMonitor::ExclusiveWrite128(size_t core_index, u64 vaddr,
290 std::array<std::uint64_t, 2> value) {
291 return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
292 Memory::Write64(vaddr, value[0]);
293 Memory::Write64(vaddr, value[1]);
294 });
295}
diff --git a/src/core/arm/dynarmic/arm_dynarmic.h b/src/core/arm/dynarmic/arm_dynarmic.h
index a9891ac4f..0fa8b417c 100644
--- a/src/core/arm/dynarmic/arm_dynarmic.h
+++ b/src/core/arm/dynarmic/arm_dynarmic.h
@@ -6,15 +6,18 @@
6 6
7#include <memory> 7#include <memory>
8#include <dynarmic/A64/a64.h> 8#include <dynarmic/A64/a64.h>
9#include <dynarmic/A64/exclusive_monitor.h>
9#include "common/common_types.h" 10#include "common/common_types.h"
10#include "core/arm/arm_interface.h" 11#include "core/arm/arm_interface.h"
12#include "core/arm/exclusive_monitor.h"
11#include "core/arm/unicorn/arm_unicorn.h" 13#include "core/arm/unicorn/arm_unicorn.h"
12 14
13class ARM_Dynarmic_Callbacks; 15class ARM_Dynarmic_Callbacks;
16class DynarmicExclusiveMonitor;
14 17
15class ARM_Dynarmic final : public ARM_Interface { 18class ARM_Dynarmic final : public ARM_Interface {
16public: 19public:
17 ARM_Dynarmic(); 20 ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index);
18 ~ARM_Dynarmic(); 21 ~ARM_Dynarmic();
19 22
20 void MapBackingMemory(VAddr address, size_t size, u8* memory, 23 void MapBackingMemory(VAddr address, size_t size, u8* memory,
@@ -47,10 +50,35 @@ public:
47 void PageTableChanged() override; 50 void PageTableChanged() override;
48 51
49private: 52private:
53 std::unique_ptr<Dynarmic::A64::Jit> MakeJit();
54
50 friend class ARM_Dynarmic_Callbacks; 55 friend class ARM_Dynarmic_Callbacks;
51 std::unique_ptr<ARM_Dynarmic_Callbacks> cb; 56 std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
52 std::unique_ptr<Dynarmic::A64::Jit> jit; 57 std::unique_ptr<Dynarmic::A64::Jit> jit;
53 ARM_Unicorn inner_unicorn; 58 ARM_Unicorn inner_unicorn;
54 59
60 size_t core_index;
61 std::shared_ptr<DynarmicExclusiveMonitor> exclusive_monitor;
62
55 Memory::PageTable* current_page_table = nullptr; 63 Memory::PageTable* current_page_table = nullptr;
56}; 64};
65
66class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
67public:
68 explicit DynarmicExclusiveMonitor(size_t core_count);
69 ~DynarmicExclusiveMonitor();
70
71 void SetExclusive(size_t core_index, u64 addr) override;
72 void ClearExclusive() override;
73
74 bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) override;
75 bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) override;
76 bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) override;
77 bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) override;
78 bool ExclusiveWrite128(size_t core_index, u64 vaddr,
79 std::array<std::uint64_t, 2> value) override;
80
81private:
82 friend class ARM_Dynarmic;
83 Dynarmic::A64::ExclusiveMonitor monitor;
84};
diff --git a/src/core/arm/exclusive_monitor.cpp b/src/core/arm/exclusive_monitor.cpp
new file mode 100644
index 000000000..cb8c81d80
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.cpp
@@ -0,0 +1,7 @@
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 "core/arm/exclusive_monitor.h"
6
7ExclusiveMonitor::~ExclusiveMonitor() = default;
diff --git a/src/core/arm/exclusive_monitor.h b/src/core/arm/exclusive_monitor.h
new file mode 100644
index 000000000..acfcdb94c
--- /dev/null
+++ b/src/core/arm/exclusive_monitor.h
@@ -0,0 +1,23 @@
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 "common/common_types.h"
9
10class ExclusiveMonitor {
11public:
12 virtual ~ExclusiveMonitor();
13
14 virtual void SetExclusive(size_t core_index, u64 addr) = 0;
15 virtual void ClearExclusive() = 0;
16
17 virtual bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) = 0;
18 virtual bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) = 0;
19 virtual bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) = 0;
20 virtual bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) = 0;
21 virtual bool ExclusiveWrite128(size_t core_index, u64 vaddr,
22 std::array<std::uint64_t, 2> value) = 0;
23};
diff --git a/src/core/core.cpp b/src/core/core.cpp
index 9bd9f4bd9..b7f4b4532 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -171,8 +171,9 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
171 current_process = Kernel::Process::Create("main"); 171 current_process = Kernel::Process::Create("main");
172 172
173 cpu_barrier = std::make_shared<CpuBarrier>(); 173 cpu_barrier = std::make_shared<CpuBarrier>();
174 cpu_exclusive_monitor = Cpu::MakeExclusiveMonitor(cpu_cores.size());
174 for (size_t index = 0; index < cpu_cores.size(); ++index) { 175 for (size_t index = 0; index < cpu_cores.size(); ++index) {
175 cpu_cores[index] = std::make_shared<Cpu>(cpu_barrier, index); 176 cpu_cores[index] = std::make_shared<Cpu>(cpu_exclusive_monitor, cpu_barrier, index);
176 } 177 }
177 178
178 gpu_core = std::make_unique<Tegra::GPU>(); 179 gpu_core = std::make_unique<Tegra::GPU>();
diff --git a/src/core/core.h b/src/core/core.h
index c6f69f001..c123fe401 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -9,6 +9,7 @@
9#include <string> 9#include <string>
10#include <thread> 10#include <thread>
11#include "common/common_types.h" 11#include "common/common_types.h"
12#include "core/arm/exclusive_monitor.h"
12#include "core/core_cpu.h" 13#include "core/core_cpu.h"
13#include "core/hle/kernel/kernel.h" 14#include "core/hle/kernel/kernel.h"
14#include "core/hle/kernel/scheduler.h" 15#include "core/hle/kernel/scheduler.h"
@@ -114,6 +115,11 @@ public:
114 return CurrentCpuCore().ArmInterface(); 115 return CurrentCpuCore().ArmInterface();
115 } 116 }
116 117
118 /// Gets the index of the currently running CPU core
119 size_t CurrentCoreIndex() {
120 return CurrentCpuCore().CoreIndex();
121 }
122
117 /// Gets an ARM interface to the CPU core with the specified index 123 /// Gets an ARM interface to the CPU core with the specified index
118 ARM_Interface& ArmInterface(size_t core_index); 124 ARM_Interface& ArmInterface(size_t core_index);
119 125
@@ -130,6 +136,11 @@ public:
130 return *CurrentCpuCore().Scheduler(); 136 return *CurrentCpuCore().Scheduler();
131 } 137 }
132 138
139 /// Gets the exclusive monitor
140 ExclusiveMonitor& Monitor() {
141 return *cpu_exclusive_monitor;
142 }
143
133 /// Gets the scheduler for the CPU core with the specified index 144 /// Gets the scheduler for the CPU core with the specified index
134 const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index); 145 const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
135 146
@@ -186,6 +197,7 @@ private:
186 std::unique_ptr<Tegra::GPU> gpu_core; 197 std::unique_ptr<Tegra::GPU> gpu_core;
187 std::shared_ptr<Tegra::DebugContext> debug_context; 198 std::shared_ptr<Tegra::DebugContext> debug_context;
188 Kernel::SharedPtr<Kernel::Process> current_process; 199 Kernel::SharedPtr<Kernel::Process> current_process;
200 std::shared_ptr<ExclusiveMonitor> cpu_exclusive_monitor;
189 std::shared_ptr<CpuBarrier> cpu_barrier; 201 std::shared_ptr<CpuBarrier> cpu_barrier;
190 std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores; 202 std::array<std::shared_ptr<Cpu>, NUM_CPU_CORES> cpu_cores;
191 std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads; 203 std::array<std::unique_ptr<std::thread>, NUM_CPU_CORES - 1> cpu_core_threads;
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index f22d6a9d0..54e15a701 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -48,14 +48,15 @@ bool CpuBarrier::Rendezvous() {
48 return false; 48 return false;
49} 49}
50 50
51Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index) 51Cpu::Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
52 std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
52 : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} { 53 : cpu_barrier{std::move(cpu_barrier)}, core_index{core_index} {
53 54
54 if (Settings::values.use_cpu_jit) { 55 if (Settings::values.use_cpu_jit) {
55#ifdef ARCHITECTURE_x86_64 56#ifdef ARCHITECTURE_x86_64
56 arm_interface = std::make_shared<ARM_Dynarmic>(); 57 arm_interface = std::make_shared<ARM_Dynarmic>(exclusive_monitor, core_index);
57#else 58#else
58 cpu_core = std::make_shared<ARM_Unicorn>(); 59 arm_interface = std::make_shared<ARM_Unicorn>();
59 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); 60 LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available");
60#endif 61#endif
61 } else { 62 } else {
@@ -65,6 +66,18 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
65 scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get()); 66 scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
66} 67}
67 68
69std::shared_ptr<ExclusiveMonitor> Cpu::MakeExclusiveMonitor(size_t num_cores) {
70 if (Settings::values.use_cpu_jit) {
71#ifdef ARCHITECTURE_x86_64
72 return std::make_shared<DynarmicExclusiveMonitor>(num_cores);
73#else
74 return nullptr; // TODO(merry): Passthrough exclusive monitor
75#endif
76 } else {
77 return nullptr; // TODO(merry): Passthrough exclusive monitor
78 }
79}
80
68void Cpu::RunLoop(bool tight_loop) { 81void Cpu::RunLoop(bool tight_loop) {
69 // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step 82 // Wait for all other CPU cores to complete the previous slice, such that they run in lock-step
70 if (!cpu_barrier->Rendezvous()) { 83 if (!cpu_barrier->Rendezvous()) {
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index 243f0b5e7..976952903 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -10,6 +10,7 @@
10#include <mutex> 10#include <mutex>
11#include <string> 11#include <string>
12#include "common/common_types.h" 12#include "common/common_types.h"
13#include "core/arm/exclusive_monitor.h"
13 14
14class ARM_Interface; 15class ARM_Interface;
15 16
@@ -40,7 +41,8 @@ private:
40 41
41class Cpu { 42class Cpu {
42public: 43public:
43 Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index); 44 Cpu(std::shared_ptr<ExclusiveMonitor> exclusive_monitor,
45 std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index);
44 46
45 void RunLoop(bool tight_loop = true); 47 void RunLoop(bool tight_loop = true);
46 48
@@ -64,6 +66,12 @@ public:
64 return core_index == 0; 66 return core_index == 0;
65 } 67 }
66 68
69 size_t CoreIndex() const {
70 return core_index;
71 }
72
73 static std::shared_ptr<ExclusiveMonitor> MakeExclusiveMonitor(size_t num_cores);
74
67private: 75private:
68 void Reschedule(); 76 void Reschedule();
69 77