arm_dynarmic_64.cpp 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359
  1. // Copyright 2018 yuzu emulator team
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #include <cinttypes>
  5. #include <memory>
  6. #include <dynarmic/A64/a64.h>
  7. #include <dynarmic/A64/config.h>
  8. #include "common/logging/log.h"
  9. #include "common/page_table.h"
  10. #include "core/arm/cpu_interrupt_handler.h"
  11. #include "core/arm/dynarmic/arm_dynarmic_64.h"
  12. #include "core/core.h"
  13. #include "core/core_manager.h"
  14. #include "core/core_timing.h"
  15. #include "core/core_timing_util.h"
  16. #include "core/gdbstub/gdbstub.h"
  17. #include "core/hardware_properties.h"
  18. #include "core/hle/kernel/process.h"
  19. #include "core/hle/kernel/scheduler.h"
  20. #include "core/hle/kernel/svc.h"
  21. #include "core/memory.h"
  22. #include "core/settings.h"
  23. namespace Core {
  24. using Vector = Dynarmic::A64::Vector;
  25. class DynarmicCallbacks64 : public Dynarmic::A64::UserCallbacks {
  26. public:
  27. explicit DynarmicCallbacks64(ARM_Dynarmic_64& parent) : parent(parent) {}
  28. u8 MemoryRead8(u64 vaddr) override {
  29. return parent.system.Memory().Read8(vaddr);
  30. }
  31. u16 MemoryRead16(u64 vaddr) override {
  32. return parent.system.Memory().Read16(vaddr);
  33. }
  34. u32 MemoryRead32(u64 vaddr) override {
  35. return parent.system.Memory().Read32(vaddr);
  36. }
  37. u64 MemoryRead64(u64 vaddr) override {
  38. return parent.system.Memory().Read64(vaddr);
  39. }
  40. Vector MemoryRead128(u64 vaddr) override {
  41. auto& memory = parent.system.Memory();
  42. return {memory.Read64(vaddr), memory.Read64(vaddr + 8)};
  43. }
  44. void MemoryWrite8(u64 vaddr, u8 value) override {
  45. parent.system.Memory().Write8(vaddr, value);
  46. }
  47. void MemoryWrite16(u64 vaddr, u16 value) override {
  48. parent.system.Memory().Write16(vaddr, value);
  49. }
  50. void MemoryWrite32(u64 vaddr, u32 value) override {
  51. parent.system.Memory().Write32(vaddr, value);
  52. }
  53. void MemoryWrite64(u64 vaddr, u64 value) override {
  54. parent.system.Memory().Write64(vaddr, value);
  55. }
  56. void MemoryWrite128(u64 vaddr, Vector value) override {
  57. auto& memory = parent.system.Memory();
  58. memory.Write64(vaddr, value[0]);
  59. memory.Write64(vaddr + 8, value[1]);
  60. }
  61. bool MemoryWriteExclusive8(u64 vaddr, std::uint8_t value, std::uint8_t expected) override {
  62. return parent.system.Memory().WriteExclusive8(vaddr, value, expected);
  63. }
  64. bool MemoryWriteExclusive16(u64 vaddr, std::uint16_t value, std::uint16_t expected) override {
  65. return parent.system.Memory().WriteExclusive16(vaddr, value, expected);
  66. }
  67. bool MemoryWriteExclusive32(u64 vaddr, std::uint32_t value, std::uint32_t expected) override {
  68. return parent.system.Memory().WriteExclusive32(vaddr, value, expected);
  69. }
  70. bool MemoryWriteExclusive64(u64 vaddr, std::uint64_t value, std::uint64_t expected) override {
  71. return parent.system.Memory().WriteExclusive64(vaddr, value, expected);
  72. }
  73. bool MemoryWriteExclusive128(u64 vaddr, Vector value, Vector expected) override {
  74. return parent.system.Memory().WriteExclusive128(vaddr, value, expected);
  75. }
  76. void InterpreterFallback(u64 pc, std::size_t num_instructions) override {
  77. LOG_INFO(Core_ARM, "Unicorn fallback @ 0x{:X} for {} instructions (instr = {:08X})", pc,
  78. num_instructions, MemoryReadCode(pc));
  79. ARM_Interface::ThreadContext64 ctx;
  80. parent.SaveContext(ctx);
  81. parent.inner_unicorn.LoadContext(ctx);
  82. parent.inner_unicorn.ExecuteInstructions(num_instructions);
  83. parent.inner_unicorn.SaveContext(ctx);
  84. parent.LoadContext(ctx);
  85. num_interpreted_instructions += num_instructions;
  86. }
  87. void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
  88. switch (exception) {
  89. case Dynarmic::A64::Exception::WaitForInterrupt:
  90. case Dynarmic::A64::Exception::WaitForEvent:
  91. case Dynarmic::A64::Exception::SendEvent:
  92. case Dynarmic::A64::Exception::SendEventLocal:
  93. case Dynarmic::A64::Exception::Yield:
  94. return;
  95. case Dynarmic::A64::Exception::Breakpoint:
  96. if (GDBStub::IsServerEnabled()) {
  97. parent.jit->HaltExecution();
  98. parent.SetPC(pc);
  99. Kernel::Thread* const thread = parent.system.CurrentScheduler().GetCurrentThread();
  100. parent.SaveContext(thread->GetContext64());
  101. GDBStub::Break();
  102. GDBStub::SendTrap(thread, 5);
  103. return;
  104. }
  105. [[fallthrough]];
  106. default:
  107. ASSERT_MSG(false, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
  108. static_cast<std::size_t>(exception), pc, MemoryReadCode(pc));
  109. }
  110. }
  111. void CallSVC(u32 swi) override {
  112. Kernel::Svc::Call(parent.system, swi);
  113. }
  114. void AddTicks(u64 ticks) override {
  115. /// We are using host timing, NOP
  116. }
  117. u64 GetTicksRemaining() override {
  118. if (!parent.interrupt_handler.IsInterrupted()) {
  119. return 1000ULL;
  120. }
  121. return 0ULL;
  122. }
  123. u64 GetCNTPCT() override {
  124. return parent.system.CoreTiming().GetClockTicks();
  125. }
  126. ARM_Dynarmic_64& parent;
  127. std::size_t num_interpreted_instructions = 0;
  128. u64 tpidrro_el0 = 0;
  129. u64 tpidr_el0 = 0;
  130. };
  131. std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable& page_table,
  132. std::size_t address_space_bits) const {
  133. Dynarmic::A64::UserConfig config;
  134. // Callbacks
  135. config.callbacks = cb.get();
  136. // Memory
  137. config.page_table = reinterpret_cast<void**>(page_table.pointers.data());
  138. config.page_table_address_space_bits = address_space_bits;
  139. config.silently_mirror_page_table = false;
  140. config.absolute_offset_page_table = true;
  141. config.detect_misaligned_access_via_page_table = 16 | 32 | 64 | 128;
  142. config.only_detect_misalignment_via_page_table_on_page_boundary = true;
  143. // Multi-process state
  144. config.processor_id = core_index;
  145. config.global_monitor = &exclusive_monitor.monitor;
  146. // System registers
  147. config.tpidrro_el0 = &cb->tpidrro_el0;
  148. config.tpidr_el0 = &cb->tpidr_el0;
  149. config.dczid_el0 = 4;
  150. config.ctr_el0 = 0x8444c004;
  151. config.cntfrq_el0 = Hardware::CNTFREQ;
  152. // Unpredictable instructions
  153. config.define_unpredictable_behaviour = true;
  154. // Optimizations
  155. if (Settings::values.disable_cpu_opt) {
  156. config.enable_optimizations = false;
  157. config.enable_fast_dispatch = false;
  158. }
  159. return std::make_shared<Dynarmic::A64::Jit>(config);
  160. }
  161. void ARM_Dynarmic_64::Run() {
  162. jit->Run();
  163. }
  164. void ARM_Dynarmic_64::Step() {
  165. cb->InterpreterFallback(jit->GetPC(), 1);
  166. }
  167. ARM_Dynarmic_64::ARM_Dynarmic_64(System& system, CPUInterruptHandler& interrupt_handler,
  168. ExclusiveMonitor& exclusive_monitor, std::size_t core_index)
  169. : ARM_Interface{system, interrupt_handler}, cb(std::make_unique<DynarmicCallbacks64>(*this)),
  170. inner_unicorn{system, interrupt_handler, ARM_Unicorn::Arch::AArch64}, core_index{core_index},
  171. exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor)} {}
  172. ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
  173. void ARM_Dynarmic_64::SetPC(u64 pc) {
  174. jit->SetPC(pc);
  175. }
  176. u64 ARM_Dynarmic_64::GetPC() const {
  177. return jit->GetPC();
  178. }
  179. u64 ARM_Dynarmic_64::GetReg(int index) const {
  180. return jit->GetRegister(index);
  181. }
  182. void ARM_Dynarmic_64::SetReg(int index, u64 value) {
  183. jit->SetRegister(index, value);
  184. }
  185. u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
  186. return jit->GetVector(index);
  187. }
  188. void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
  189. jit->SetVector(index, value);
  190. }
  191. u32 ARM_Dynarmic_64::GetPSTATE() const {
  192. return jit->GetPstate();
  193. }
  194. void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
  195. jit->SetPstate(pstate);
  196. }
  197. u64 ARM_Dynarmic_64::GetTlsAddress() const {
  198. return cb->tpidrro_el0;
  199. }
  200. void ARM_Dynarmic_64::SetTlsAddress(VAddr address) {
  201. cb->tpidrro_el0 = address;
  202. }
  203. u64 ARM_Dynarmic_64::GetTPIDR_EL0() const {
  204. return cb->tpidr_el0;
  205. }
  206. void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
  207. cb->tpidr_el0 = value;
  208. }
  209. void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
  210. ctx.cpu_registers = jit->GetRegisters();
  211. ctx.sp = jit->GetSP();
  212. ctx.pc = jit->GetPC();
  213. ctx.pstate = jit->GetPstate();
  214. ctx.vector_registers = jit->GetVectors();
  215. ctx.fpcr = jit->GetFpcr();
  216. ctx.fpsr = jit->GetFpsr();
  217. ctx.tpidr = cb->tpidr_el0;
  218. }
  219. void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
  220. jit->SetRegisters(ctx.cpu_registers);
  221. jit->SetSP(ctx.sp);
  222. jit->SetPC(ctx.pc);
  223. jit->SetPstate(ctx.pstate);
  224. jit->SetVectors(ctx.vector_registers);
  225. jit->SetFpcr(ctx.fpcr);
  226. jit->SetFpsr(ctx.fpsr);
  227. SetTPIDR_EL0(ctx.tpidr);
  228. }
  229. void ARM_Dynarmic_64::PrepareReschedule() {
  230. jit->HaltExecution();
  231. }
  232. void ARM_Dynarmic_64::ClearInstructionCache() {
  233. jit->ClearCache();
  234. }
  235. void ARM_Dynarmic_64::ClearExclusiveState() {
  236. jit->ClearExclusiveState();
  237. }
  238. void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
  239. std::size_t new_address_space_size_in_bits) {
  240. auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
  241. auto iter = jit_cache.find(key);
  242. if (iter != jit_cache.end()) {
  243. jit = iter->second;
  244. return;
  245. }
  246. jit = MakeJit(page_table, new_address_space_size_in_bits);
  247. jit_cache.emplace(key, jit);
  248. }
  249. DynarmicExclusiveMonitor::DynarmicExclusiveMonitor(Memory::Memory& memory, std::size_t core_count)
  250. : monitor(core_count), memory{memory} {}
  251. DynarmicExclusiveMonitor::~DynarmicExclusiveMonitor() = default;
  252. void DynarmicExclusiveMonitor::SetExclusive8(std::size_t core_index, VAddr addr) {
  253. monitor.Mark<u8>(core_index, addr, 1, [&]() -> u8 { return memory.Read8(addr); });
  254. }
  255. void DynarmicExclusiveMonitor::SetExclusive16(std::size_t core_index, VAddr addr) {
  256. monitor.Mark<u16>(core_index, addr, 2, [&]() -> u16 { return memory.Read16(addr); });
  257. }
  258. void DynarmicExclusiveMonitor::SetExclusive32(std::size_t core_index, VAddr addr) {
  259. monitor.Mark<u32>(core_index, addr, 4, [&]() -> u32 { return memory.Read32(addr); });
  260. }
  261. void DynarmicExclusiveMonitor::SetExclusive64(std::size_t core_index, VAddr addr) {
  262. monitor.Mark<u64>(core_index, addr, 8, [&]() -> u64 { return memory.Read64(addr); });
  263. }
  264. void DynarmicExclusiveMonitor::SetExclusive128(std::size_t core_index, VAddr addr) {
  265. monitor.Mark<u128>(core_index, addr, 16, [&]() -> u128 {
  266. u128 result;
  267. result[0] = memory.Read64(addr);
  268. result[1] = memory.Read64(addr + 8);
  269. return result;
  270. });
  271. }
  272. void DynarmicExclusiveMonitor::ClearExclusive() {
  273. monitor.Clear();
  274. }
  275. bool DynarmicExclusiveMonitor::ExclusiveWrite8(std::size_t core_index, VAddr vaddr, u8 value) {
  276. return monitor.DoExclusiveOperation<u8>(core_index, vaddr, 1, [&](u8 expected) -> bool {
  277. return memory.WriteExclusive8(vaddr, value, expected);
  278. });
  279. }
  280. bool DynarmicExclusiveMonitor::ExclusiveWrite16(std::size_t core_index, VAddr vaddr, u16 value) {
  281. return monitor.DoExclusiveOperation<u16>(core_index, vaddr, 2, [&](u16 expected) -> bool {
  282. return memory.WriteExclusive16(vaddr, value, expected);
  283. });
  284. }
  285. bool DynarmicExclusiveMonitor::ExclusiveWrite32(std::size_t core_index, VAddr vaddr, u32 value) {
  286. return monitor.DoExclusiveOperation<u32>(core_index, vaddr, 4, [&](u32 expected) -> bool {
  287. return memory.WriteExclusive32(vaddr, value, expected);
  288. });
  289. }
  290. bool DynarmicExclusiveMonitor::ExclusiveWrite64(std::size_t core_index, VAddr vaddr, u64 value) {
  291. return monitor.DoExclusiveOperation<u64>(core_index, vaddr, 8, [&](u64 expected) -> bool {
  292. return memory.WriteExclusive64(vaddr, value, expected);
  293. });
  294. }
  295. bool DynarmicExclusiveMonitor::ExclusiveWrite128(std::size_t core_index, VAddr vaddr, u128 value) {
  296. return monitor.DoExclusiveOperation<u128>(core_index, vaddr, 16, [&](u128 expected) -> bool {
  297. return memory.WriteExclusive128(vaddr, value, expected);
  298. });
  299. }
  300. } // namespace Core