summaryrefslogtreecommitdiffstats
path: root/src/core/arm/dynarmic
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/arm/dynarmic')
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.cpp67
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic.h30
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:
u64 tpidr_el0 = 0;
};
-std::unique_ptr<Dynarmic::A64::Jit> MakeJit(const std::unique_ptr<ARM_Dynarmic_Callbacks>& cb) {
+std::unique_ptr<Dynarmic::A64::Jit> ARM_Dynarmic::MakeJit() {
const auto page_table = Core::CurrentProcess()->vm_manager.page_table.pointers.data();
Dynarmic::A64::UserConfig config;
+
+ // Callbacks
config.callbacks = cb.get();
+
+ // Memory
+ config.page_table = reinterpret_cast<void**>(page_table);
+ config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
+ config.silently_mirror_page_table = false;
+
+ // Multi-process state
+ config.processor_id = core_index;
+ config.global_monitor = &exclusive_monitor->monitor;
+
+ // System registers
config.tpidrro_el0 = &cb->tpidrro_el0;
config.tpidr_el0 = &cb->tpidr_el0;
config.dczid_el0 = 4;
config.ctr_el0 = 0x8444c004;
- config.page_table = reinterpret_cast<void**>(page_table);
- config.page_table_address_space_bits = Memory::ADDRESS_SPACE_BITS;
- config.silently_mirror_page_table = false;
return std::make_unique<Dynarmic::A64::Jit>(config);
}
@@ -128,8 +138,11 @@ void ARM_Dynarmic::Step() {
cb->InterpreterFallback(jit->GetPC(), 1);
}
-ARM_Dynarmic::ARM_Dynarmic()
- : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)), jit(MakeJit(cb)) {
+ARM_Dynarmic::ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index)
+ : cb(std::make_unique<ARM_Dynarmic_Callbacks>(*this)),
+ jit(MakeJit()), exclusive_monitor{std::dynamic_pointer_cast<DynarmicExclusiveMonitor>(
+ exclusive_monitor)},
+ core_index{core_index} {
ARM_Interface::ThreadContext ctx;
inner_unicorn.SaveContext(ctx);
LoadContext(ctx);
@@ -237,6 +250,46 @@ void ARM_Dynarmic::ClearExclusiveState() {
}
void ARM_Dynarmic::PageTableChanged() {
- jit = MakeJit(cb);
+ jit = MakeJit();
current_page_table = Memory::GetCurrentPageTable();
}
+
+DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(size_t core_count) : monitor(core_count) {}
+DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
+
+void DynarmicExclusiveMonitor::SetExclusive(size_t core_index, u64 addr) {
+ // Size doesn't actually matter.
+ monitor.Mark(core_index, addr, 16);
+}
+
+void DynarmicExclusiveMonitor::ClearExclusive() {
+ monitor.Clear();
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 1,
+ [&] { Memory::Write8(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 2,
+ [&] { Memory::Write16(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 4,
+ [&] { Memory::Write32(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 8,
+ [&] { Memory::Write64(vaddr, value); });
+}
+
+bool DynarmicExclusiveMonitor::ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) {
+ return monitor.DoExclusiveOperation(core_index, vaddr, 16, [&] {
+ Memory::Write64(vaddr, value[0]);
+ Memory::Write64(vaddr, value[1]);
+ });
+}
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 @@
#include <memory>
#include <dynarmic/A64/a64.h>
+#include <dynarmic/A64/exclusive_monitor.h>
#include "common/common_types.h"
#include "core/arm/arm_interface.h"
+#include "core/arm/exclusive_monitor.h"
#include "core/arm/unicorn/arm_unicorn.h"
class ARM_Dynarmic_Callbacks;
+class DynarmicExclusiveMonitor;
class ARM_Dynarmic final : public ARM_Interface {
public:
- ARM_Dynarmic();
+ ARM_Dynarmic(std::shared_ptr<ExclusiveMonitor> exclusive_monitor, size_t core_index);
~ARM_Dynarmic();
void MapBackingMemory(VAddr address, size_t size, u8* memory,
@@ -47,10 +50,35 @@ public:
void PageTableChanged() override;
private:
+ std::unique_ptr<Dynarmic::A64::Jit> MakeJit();
+
friend class ARM_Dynarmic_Callbacks;
std::unique_ptr<ARM_Dynarmic_Callbacks> cb;
std::unique_ptr<Dynarmic::A64::Jit> jit;
ARM_Unicorn inner_unicorn;
+ size_t core_index;
+ std::shared_ptr<DynarmicExclusiveMonitor> exclusive_monitor;
+
Memory::PageTable* current_page_table = nullptr;
};
+
+class DynarmicExclusiveMonitor final : public ExclusiveMonitor {
+public:
+ explicit DynarmicExclusiveMonitor(size_t core_count);
+ ~DynarmicExclusiveMonitor();
+
+ void SetExclusive(size_t core_index, u64 addr) override;
+ void ClearExclusive() override;
+
+ bool ExclusiveWrite8(size_t core_index, u64 vaddr, u8 value) override;
+ bool ExclusiveWrite16(size_t core_index, u64 vaddr, u16 value) override;
+ bool ExclusiveWrite32(size_t core_index, u64 vaddr, u32 value) override;
+ bool ExclusiveWrite64(size_t core_index, u64 vaddr, u64 value) override;
+ bool ExclusiveWrite128(size_t core_index, u64 vaddr,
+ std::array<std::uint64_t, 2> value) override;
+
+private:
+ friend class ARM_Dynarmic;
+ Dynarmic::A64::ExclusiveMonitor monitor;
+};