summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2022-04-16 00:24:53 -0700
committerGravatar GitHub2022-04-16 00:24:53 -0700
commita29a8c6f7840182f6fd661052e09a6b52a47e386 (patch)
treee4cb81c78ead11f2e2ce08d4e047392589ba3bd8
parentMerge pull request #8205 from liamwhite/n64-misc (diff)
parentdynarmic: Fix race when switching page tables (diff)
downloadyuzu-a29a8c6f7840182f6fd661052e09a6b52a47e386.tar.gz
yuzu-a29a8c6f7840182f6fd661052e09a6b52a47e386.tar.xz
yuzu-a29a8c6f7840182f6fd661052e09a6b52a47e386.zip
Merge pull request #8188 from merryhime/jit-race-page-table-changed
dynarmic: Fix race when switching page tables
Diffstat (limited to '')
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.cpp48
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_32.h7
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.cpp80
-rw-r--r--src/core/arm/dynarmic/arm_dynarmic_64.h6
4 files changed, 84 insertions, 57 deletions
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 6f3d53dad..5de4384db 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -88,7 +88,7 @@ public:
88 88
89 void CallSVC(u32 swi) override { 89 void CallSVC(u32 swi) override {
90 parent.svc_swi = swi; 90 parent.svc_swi = swi;
91 parent.jit->HaltExecution(svc_call); 91 parent.jit.load()->HaltExecution(svc_call);
92 } 92 }
93 93
94 void AddTicks(u64 ticks) override { 94 void AddTicks(u64 ticks) override {
@@ -151,6 +151,13 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
151 config.code_cache_size = 512_MiB; 151 config.code_cache_size = 512_MiB;
152 config.far_code_offset = 400_MiB; 152 config.far_code_offset = 400_MiB;
153 153
154 // null_jit
155 if (!page_table) {
156 // Don't waste too much memory on null_jit
157 config.code_cache_size = 8_MiB;
158 config.far_code_offset = 4_MiB;
159 }
160
154 // Safe optimizations 161 // Safe optimizations
155 if (Settings::values.cpu_debug_mode) { 162 if (Settings::values.cpu_debug_mode) {
156 if (!Settings::values.cpuopt_page_tables) { 163 if (!Settings::values.cpuopt_page_tables) {
@@ -228,7 +235,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable*
228 235
229void ARM_Dynarmic_32::Run() { 236void ARM_Dynarmic_32::Run() {
230 while (true) { 237 while (true) {
231 const auto hr = jit->Run(); 238 const auto hr = jit.load()->Run();
232 if (Has(hr, svc_call)) { 239 if (Has(hr, svc_call)) {
233 Kernel::Svc::Call(system, svc_swi); 240 Kernel::Svc::Call(system, svc_swi);
234 } 241 }
@@ -239,7 +246,7 @@ void ARM_Dynarmic_32::Run() {
239} 246}
240 247
241void ARM_Dynarmic_32::Step() { 248void ARM_Dynarmic_32::Step() {
242 jit->Step(); 249 jit.load()->Step();
243} 250}
244 251
245ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_, 252ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handlers_,
@@ -249,24 +256,24 @@ ARM_Dynarmic_32::ARM_Dynarmic_32(System& system_, CPUInterrupts& interrupt_handl
249 cb(std::make_unique<DynarmicCallbacks32>(*this)), 256 cb(std::make_unique<DynarmicCallbacks32>(*this)),
250 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_}, 257 cp15(std::make_shared<DynarmicCP15>(*this)), core_index{core_index_},
251 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 258 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
252 jit(MakeJit(nullptr)) {} 259 null_jit{MakeJit(nullptr)}, jit{null_jit.get()} {}
253 260
254ARM_Dynarmic_32::~ARM_Dynarmic_32() = default; 261ARM_Dynarmic_32::~ARM_Dynarmic_32() = default;
255 262
256void ARM_Dynarmic_32::SetPC(u64 pc) { 263void ARM_Dynarmic_32::SetPC(u64 pc) {
257 jit->Regs()[15] = static_cast<u32>(pc); 264 jit.load()->Regs()[15] = static_cast<u32>(pc);
258} 265}
259 266
260u64 ARM_Dynarmic_32::GetPC() const { 267u64 ARM_Dynarmic_32::GetPC() const {
261 return jit->Regs()[15]; 268 return jit.load()->Regs()[15];
262} 269}
263 270
264u64 ARM_Dynarmic_32::GetReg(int index) const { 271u64 ARM_Dynarmic_32::GetReg(int index) const {
265 return jit->Regs()[index]; 272 return jit.load()->Regs()[index];
266} 273}
267 274
268void ARM_Dynarmic_32::SetReg(int index, u64 value) { 275void ARM_Dynarmic_32::SetReg(int index, u64 value) {
269 jit->Regs()[index] = static_cast<u32>(value); 276 jit.load()->Regs()[index] = static_cast<u32>(value);
270} 277}
271 278
272u128 ARM_Dynarmic_32::GetVectorReg(int index) const { 279u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
@@ -276,11 +283,11 @@ u128 ARM_Dynarmic_32::GetVectorReg(int index) const {
276void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {} 283void ARM_Dynarmic_32::SetVectorReg(int index, u128 value) {}
277 284
278u32 ARM_Dynarmic_32::GetPSTATE() const { 285u32 ARM_Dynarmic_32::GetPSTATE() const {
279 return jit->Cpsr(); 286 return jit.load()->Cpsr();
280} 287}
281 288
282void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) { 289void ARM_Dynarmic_32::SetPSTATE(u32 cpsr) {
283 jit->SetCpsr(cpsr); 290 jit.load()->SetCpsr(cpsr);
284} 291}
285 292
286u64 ARM_Dynarmic_32::GetTlsAddress() const { 293u64 ARM_Dynarmic_32::GetTlsAddress() const {
@@ -301,7 +308,7 @@ void ARM_Dynarmic_32::SetTPIDR_EL0(u64 value) {
301 308
302void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) { 309void ARM_Dynarmic_32::SaveContext(ThreadContext32& ctx) {
303 Dynarmic::A32::Context context; 310 Dynarmic::A32::Context context;
304 jit->SaveContext(context); 311 jit.load()->SaveContext(context);
305 ctx.cpu_registers = context.Regs(); 312 ctx.cpu_registers = context.Regs();
306 ctx.extension_registers = context.ExtRegs(); 313 ctx.extension_registers = context.ExtRegs();
307 ctx.cpsr = context.Cpsr(); 314 ctx.cpsr = context.Cpsr();
@@ -314,27 +321,27 @@ void ARM_Dynarmic_32::LoadContext(const ThreadContext32& ctx) {
314 context.ExtRegs() = ctx.extension_registers; 321 context.ExtRegs() = ctx.extension_registers;
315 context.SetCpsr(ctx.cpsr); 322 context.SetCpsr(ctx.cpsr);
316 context.SetFpscr(ctx.fpscr); 323 context.SetFpscr(ctx.fpscr);
317 jit->LoadContext(context); 324 jit.load()->LoadContext(context);
318} 325}
319 326
320void ARM_Dynarmic_32::PrepareReschedule() { 327void ARM_Dynarmic_32::PrepareReschedule() {
321 jit->HaltExecution(break_loop); 328 jit.load()->HaltExecution(break_loop);
322} 329}
323 330
324void ARM_Dynarmic_32::SignalInterrupt() { 331void ARM_Dynarmic_32::SignalInterrupt() {
325 jit->HaltExecution(break_loop); 332 jit.load()->HaltExecution(break_loop);
326} 333}
327 334
328void ARM_Dynarmic_32::ClearInstructionCache() { 335void ARM_Dynarmic_32::ClearInstructionCache() {
329 jit->ClearCache(); 336 jit.load()->ClearCache();
330} 337}
331 338
332void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) { 339void ARM_Dynarmic_32::InvalidateCacheRange(VAddr addr, std::size_t size) {
333 jit->InvalidateCacheRange(static_cast<u32>(addr), size); 340 jit.load()->InvalidateCacheRange(static_cast<u32>(addr), size);
334} 341}
335 342
336void ARM_Dynarmic_32::ClearExclusiveState() { 343void ARM_Dynarmic_32::ClearExclusiveState() {
337 jit->ClearExclusiveState(); 344 jit.load()->ClearExclusiveState();
338} 345}
339 346
340void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table, 347void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
@@ -345,13 +352,14 @@ void ARM_Dynarmic_32::PageTableChanged(Common::PageTable& page_table,
345 auto key = std::make_pair(&page_table, new_address_space_size_in_bits); 352 auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
346 auto iter = jit_cache.find(key); 353 auto iter = jit_cache.find(key);
347 if (iter != jit_cache.end()) { 354 if (iter != jit_cache.end()) {
348 jit = iter->second; 355 jit.store(iter->second.get());
349 LoadContext(ctx); 356 LoadContext(ctx);
350 return; 357 return;
351 } 358 }
352 jit = MakeJit(&page_table); 359 std::shared_ptr new_jit = MakeJit(&page_table);
360 jit.store(new_jit.get());
353 LoadContext(ctx); 361 LoadContext(ctx);
354 jit_cache.emplace(key, jit); 362 jit_cache.emplace(key, std::move(new_jit));
355} 363}
356 364
357} // namespace Core 365} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.h b/src/core/arm/dynarmic/arm_dynarmic_32.h
index 3f68a4ff1..684937353 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_32.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <memory> 8#include <memory>
8#include <unordered_map> 9#include <unordered_map>
9 10
@@ -80,7 +81,11 @@ private:
80 std::shared_ptr<DynarmicCP15> cp15; 81 std::shared_ptr<DynarmicCP15> cp15;
81 std::size_t core_index; 82 std::size_t core_index;
82 DynarmicExclusiveMonitor& exclusive_monitor; 83 DynarmicExclusiveMonitor& exclusive_monitor;
83 std::shared_ptr<Dynarmic::A32::Jit> jit; 84
85 std::shared_ptr<Dynarmic::A32::Jit> null_jit;
86
87 // A raw pointer here is fine; we never delete Jit instances.
88 std::atomic<Dynarmic::A32::Jit*> jit;
84 89
85 // SVC callback 90 // SVC callback
86 u32 svc_swi{}; 91 u32 svc_swi{};
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
index 1fcb2b891..ae0b158c2 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp
@@ -109,7 +109,7 @@ public:
109 break; 109 break;
110 } 110 }
111 111
112 parent.jit->HaltExecution(Dynarmic::HaltReason::CacheInvalidation); 112 parent.jit.load()->HaltExecution(Dynarmic::HaltReason::CacheInvalidation);
113 } 113 }
114 114
115 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override { 115 void ExceptionRaised(u64 pc, Dynarmic::A64::Exception exception) override {
@@ -130,7 +130,7 @@ public:
130 130
131 void CallSVC(u32 swi) override { 131 void CallSVC(u32 swi) override {
132 parent.svc_swi = swi; 132 parent.svc_swi = swi;
133 parent.jit->HaltExecution(svc_call); 133 parent.jit.load()->HaltExecution(svc_call);
134 } 134 }
135 135
136 void AddTicks(u64 ticks) override { 136 void AddTicks(u64 ticks) override {
@@ -212,6 +212,13 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
212 config.code_cache_size = 512_MiB; 212 config.code_cache_size = 512_MiB;
213 config.far_code_offset = 400_MiB; 213 config.far_code_offset = 400_MiB;
214 214
215 // null_jit
216 if (!page_table) {
217 // Don't waste too much memory on null_jit
218 config.code_cache_size = 8_MiB;
219 config.far_code_offset = 4_MiB;
220 }
221
215 // Safe optimizations 222 // Safe optimizations
216 if (Settings::values.cpu_debug_mode) { 223 if (Settings::values.cpu_debug_mode) {
217 if (!Settings::values.cpuopt_page_tables) { 224 if (!Settings::values.cpuopt_page_tables) {
@@ -289,7 +296,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable*
289 296
290void ARM_Dynarmic_64::Run() { 297void ARM_Dynarmic_64::Run() {
291 while (true) { 298 while (true) {
292 const auto hr = jit->Run(); 299 const auto hr = jit.load()->Run();
293 if (Has(hr, svc_call)) { 300 if (Has(hr, svc_call)) {
294 Kernel::Svc::Call(system, svc_swi); 301 Kernel::Svc::Call(system, svc_swi);
295 } 302 }
@@ -300,7 +307,7 @@ void ARM_Dynarmic_64::Run() {
300} 307}
301 308
302void ARM_Dynarmic_64::Step() { 309void ARM_Dynarmic_64::Step() {
303 jit->Step(); 310 jit.load()->Step();
304} 311}
305 312
306ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_, 313ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handlers_,
@@ -309,40 +316,40 @@ ARM_Dynarmic_64::ARM_Dynarmic_64(System& system_, CPUInterrupts& interrupt_handl
309 : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_}, 316 : ARM_Interface{system_, interrupt_handlers_, uses_wall_clock_},
310 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_}, 317 cb(std::make_unique<DynarmicCallbacks64>(*this)), core_index{core_index_},
311 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)}, 318 exclusive_monitor{dynamic_cast<DynarmicExclusiveMonitor&>(exclusive_monitor_)},
312 jit(MakeJit(nullptr, 48)) {} 319 null_jit{MakeJit(nullptr, 48)}, jit{null_jit.get()} {}
313 320
314ARM_Dynarmic_64::~ARM_Dynarmic_64() = default; 321ARM_Dynarmic_64::~ARM_Dynarmic_64() = default;
315 322
316void ARM_Dynarmic_64::SetPC(u64 pc) { 323void ARM_Dynarmic_64::SetPC(u64 pc) {
317 jit->SetPC(pc); 324 jit.load()->SetPC(pc);
318} 325}
319 326
320u64 ARM_Dynarmic_64::GetPC() const { 327u64 ARM_Dynarmic_64::GetPC() const {
321 return jit->GetPC(); 328 return jit.load()->GetPC();
322} 329}
323 330
324u64 ARM_Dynarmic_64::GetReg(int index) const { 331u64 ARM_Dynarmic_64::GetReg(int index) const {
325 return jit->GetRegister(index); 332 return jit.load()->GetRegister(index);
326} 333}
327 334
328void ARM_Dynarmic_64::SetReg(int index, u64 value) { 335void ARM_Dynarmic_64::SetReg(int index, u64 value) {
329 jit->SetRegister(index, value); 336 jit.load()->SetRegister(index, value);
330} 337}
331 338
332u128 ARM_Dynarmic_64::GetVectorReg(int index) const { 339u128 ARM_Dynarmic_64::GetVectorReg(int index) const {
333 return jit->GetVector(index); 340 return jit.load()->GetVector(index);
334} 341}
335 342
336void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) { 343void ARM_Dynarmic_64::SetVectorReg(int index, u128 value) {
337 jit->SetVector(index, value); 344 jit.load()->SetVector(index, value);
338} 345}
339 346
340u32 ARM_Dynarmic_64::GetPSTATE() const { 347u32 ARM_Dynarmic_64::GetPSTATE() const {
341 return jit->GetPstate(); 348 return jit.load()->GetPstate();
342} 349}
343 350
344void ARM_Dynarmic_64::SetPSTATE(u32 pstate) { 351void ARM_Dynarmic_64::SetPSTATE(u32 pstate) {
345 jit->SetPstate(pstate); 352 jit.load()->SetPstate(pstate);
346} 353}
347 354
348u64 ARM_Dynarmic_64::GetTlsAddress() const { 355u64 ARM_Dynarmic_64::GetTlsAddress() const {
@@ -362,45 +369,47 @@ void ARM_Dynarmic_64::SetTPIDR_EL0(u64 value) {
362} 369}
363 370
364void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) { 371void ARM_Dynarmic_64::SaveContext(ThreadContext64& ctx) {
365 ctx.cpu_registers = jit->GetRegisters(); 372 Dynarmic::A64::Jit* j = jit.load();
366 ctx.sp = jit->GetSP(); 373 ctx.cpu_registers = j->GetRegisters();
367 ctx.pc = jit->GetPC(); 374 ctx.sp = j->GetSP();
368 ctx.pstate = jit->GetPstate(); 375 ctx.pc = j->GetPC();
369 ctx.vector_registers = jit->GetVectors(); 376 ctx.pstate = j->GetPstate();
370 ctx.fpcr = jit->GetFpcr(); 377 ctx.vector_registers = j->GetVectors();
371 ctx.fpsr = jit->GetFpsr(); 378 ctx.fpcr = j->GetFpcr();
379 ctx.fpsr = j->GetFpsr();
372 ctx.tpidr = cb->tpidr_el0; 380 ctx.tpidr = cb->tpidr_el0;
373} 381}
374 382
375void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) { 383void ARM_Dynarmic_64::LoadContext(const ThreadContext64& ctx) {
376 jit->SetRegisters(ctx.cpu_registers); 384 Dynarmic::A64::Jit* j = jit.load();
377 jit->SetSP(ctx.sp); 385 j->SetRegisters(ctx.cpu_registers);
378 jit->SetPC(ctx.pc); 386 j->SetSP(ctx.sp);
379 jit->SetPstate(ctx.pstate); 387 j->SetPC(ctx.pc);
380 jit->SetVectors(ctx.vector_registers); 388 j->SetPstate(ctx.pstate);
381 jit->SetFpcr(ctx.fpcr); 389 j->SetVectors(ctx.vector_registers);
382 jit->SetFpsr(ctx.fpsr); 390 j->SetFpcr(ctx.fpcr);
391 j->SetFpsr(ctx.fpsr);
383 SetTPIDR_EL0(ctx.tpidr); 392 SetTPIDR_EL0(ctx.tpidr);
384} 393}
385 394
386void ARM_Dynarmic_64::PrepareReschedule() { 395void ARM_Dynarmic_64::PrepareReschedule() {
387 jit->HaltExecution(break_loop); 396 jit.load()->HaltExecution(break_loop);
388} 397}
389 398
390void ARM_Dynarmic_64::SignalInterrupt() { 399void ARM_Dynarmic_64::SignalInterrupt() {
391 jit->HaltExecution(break_loop); 400 jit.load()->HaltExecution(break_loop);
392} 401}
393 402
394void ARM_Dynarmic_64::ClearInstructionCache() { 403void ARM_Dynarmic_64::ClearInstructionCache() {
395 jit->ClearCache(); 404 jit.load()->ClearCache();
396} 405}
397 406
398void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) { 407void ARM_Dynarmic_64::InvalidateCacheRange(VAddr addr, std::size_t size) {
399 jit->InvalidateCacheRange(addr, size); 408 jit.load()->InvalidateCacheRange(addr, size);
400} 409}
401 410
402void ARM_Dynarmic_64::ClearExclusiveState() { 411void ARM_Dynarmic_64::ClearExclusiveState() {
403 jit->ClearExclusiveState(); 412 jit.load()->ClearExclusiveState();
404} 413}
405 414
406void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table, 415void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
@@ -411,13 +420,14 @@ void ARM_Dynarmic_64::PageTableChanged(Common::PageTable& page_table,
411 auto key = std::make_pair(&page_table, new_address_space_size_in_bits); 420 auto key = std::make_pair(&page_table, new_address_space_size_in_bits);
412 auto iter = jit_cache.find(key); 421 auto iter = jit_cache.find(key);
413 if (iter != jit_cache.end()) { 422 if (iter != jit_cache.end()) {
414 jit = iter->second; 423 jit.store(iter->second.get());
415 LoadContext(ctx); 424 LoadContext(ctx);
416 return; 425 return;
417 } 426 }
418 jit = MakeJit(&page_table, new_address_space_size_in_bits); 427 std::shared_ptr new_jit = MakeJit(&page_table, new_address_space_size_in_bits);
428 jit.store(new_jit.get());
419 LoadContext(ctx); 429 LoadContext(ctx);
420 jit_cache.emplace(key, jit); 430 jit_cache.emplace(key, std::move(new_jit));
421} 431}
422 432
423} // namespace Core 433} // namespace Core
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.h b/src/core/arm/dynarmic/arm_dynarmic_64.h
index 58bc7fbec..86018f196 100644
--- a/src/core/arm/dynarmic/arm_dynarmic_64.h
+++ b/src/core/arm/dynarmic/arm_dynarmic_64.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <atomic>
7#include <memory> 8#include <memory>
8#include <unordered_map> 9#include <unordered_map>
9 10
@@ -74,7 +75,10 @@ private:
74 std::size_t core_index; 75 std::size_t core_index;
75 DynarmicExclusiveMonitor& exclusive_monitor; 76 DynarmicExclusiveMonitor& exclusive_monitor;
76 77
77 std::shared_ptr<Dynarmic::A64::Jit> jit; 78 std::shared_ptr<Dynarmic::A64::Jit> null_jit;
79
80 // A raw pointer here is fine; we never delete Jit instances.
81 std::atomic<Dynarmic::A64::Jit*> jit;
78 82
79 // SVC callback 83 // SVC callback
80 u32 svc_swi{}; 84 u32 svc_swi{};