diff options
| author | 2018-07-03 14:28:46 +0100 | |
|---|---|---|
| committer | 2018-07-22 15:55:17 +0100 | |
| commit | 0b1c2e5505c6478ef10e65c0b002eeb242e15540 (patch) | |
| tree | 187eeabceb451d3cd89b3f0fd47412a7a9e57015 /src/core/arm/dynarmic | |
| parent | Merge pull request #765 from lioncash/file (diff) | |
| download | yuzu-0b1c2e5505c6478ef10e65c0b002eeb242e15540.tar.gz yuzu-0b1c2e5505c6478ef10e65c0b002eeb242e15540.tar.xz yuzu-0b1c2e5505c6478ef10e65c0b002eeb242e15540.zip | |
Implement exclusive monitor
Diffstat (limited to 'src/core/arm/dynarmic')
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.cpp | 67 | ||||
| -rw-r--r-- | src/core/arm/dynarmic/arm_dynarmic.h | 30 |
2 files changed, 89 insertions, 8 deletions
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 | ||
| 105 | std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) { | 105 | std::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 | ||
| 131 | ARM_Dynarmic::ARM_Dynarmic() | 141 | ARM_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 | ||
| 239 | void ARM_Dynarmic::PageTableChanged() { | 252 | void 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 | |||
| 257 | DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {} | ||
| 258 | DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default; | ||
| 259 | |||
| 260 | void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) { | ||
| 261 | // Size doesn't actually matter. | ||
| 262 | monitor.Mark(core_index, addr, 16); | ||
| 263 | } | ||
| 264 | |||
| 265 | void DynarmicExclusiveMonitor::ClearExclusive() { | ||
| 266 | monitor.Clear(); | ||
| 267 | } | ||
| 268 | |||
| 269 | bool 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 | |||
| 274 | bool 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 | |||
| 279 | bool 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 | |||
| 284 | bool 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 | |||
| 289 | bool 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 | ||
| 13 | class ARM_Dynarmic_Callbacks; | 15 | class ARM_Dynarmic_Callbacks; |
| 16 | class DynarmicExclusiveMonitor; | ||
| 14 | 17 | ||
| 15 | class ARM_Dynarmic final : public ARM_Interface { | 18 | class ARM_Dynarmic final : public ARM_Interface { |
| 16 | public: | 19 | public: |
| 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 | ||
| 49 | private: | 52 | private: |
| 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 | |||
| 66 | class DynarmicExclusiveMonitor final : public ExclusiveMonitor { | ||
| 67 | public: | ||
| 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 | |||
| 81 | private: | ||
| 82 | friend class ARM_Dynarmic; | ||
| 83 | Dynarmic::A64::ExclusiveMonitor monitor; | ||
| 84 | }; | ||