summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGravatar bunnei2018-05-02 22:36:51 -0400
committerGravatar bunnei2018-05-10 19:34:46 -0400
commita434fdcb102e96ddf564dc0973d7073d49bf19fc (patch)
treede758b0cc5ebcb67146397a74474fb898c0be51a
parentcore: Create a thread for each CPU core, keep in lock-step with a barrier. (diff)
downloadyuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.gz
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.tar.xz
yuzu-a434fdcb102e96ddf564dc0973d7073d49bf19fc.zip
core: Implement multicore support.
-rw-r--r--src/core/arm/unicorn/arm_unicorn.cpp2
-rw-r--r--src/core/core.h26
-rw-r--r--src/core/core_cpu.cpp2
-rw-r--r--src/core/core_cpu.h12
-rw-r--r--src/core/gdbstub/gdbstub.cpp24
-rw-r--r--src/core/hle/kernel/svc.cpp43
-rw-r--r--src/core/hle/kernel/svc_wrap.h24
-rw-r--r--src/core/hle/kernel/thread.cpp16
-rw-r--r--src/core/hle/kernel/thread.h4
-rw-r--r--src/core/hle/kernel/vm_manager.cpp23
-rw-r--r--src/core/memory.cpp9
-rw-r--r--src/yuzu/debugger/registers.cpp4
-rw-r--r--src/yuzu/debugger/wait_tree.cpp2
13 files changed, 113 insertions, 78 deletions
diff --git a/src/core/arm/unicorn/arm_unicorn.cpp b/src/core/arm/unicorn/arm_unicorn.cpp
index 574922130..c0cc62f03 100644
--- a/src/core/arm/unicorn/arm_unicorn.cpp
+++ b/src/core/arm/unicorn/arm_unicorn.cpp
@@ -52,7 +52,7 @@ static void InterruptHook(uc_engine* uc, u32 intNo, void* user_data) {
52static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value, 52static bool UnmappedMemoryHook(uc_engine* uc, uc_mem_type type, u64 addr, int size, u64 value,
53 void* user_data) { 53 void* user_data) {
54 ARM_Interface::ThreadContext ctx{}; 54 ARM_Interface::ThreadContext ctx{};
55 Core::CPU().SaveContext(ctx); 55 Core::CurrentArmInterface().SaveContext(ctx);
56 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr, 56 ASSERT_MSG(false, "Attempted to read from unmapped memory: 0x{:X}, pc=0x{:X}, lr=0x{:X}", addr,
57 ctx.pc, ctx.cpu_registers[30]); 57 ctx.pc, ctx.cpu_registers[30]);
58 return {}; 58 return {};
diff --git a/src/core/core.h b/src/core/core.h
index 21a0b074b..3e0a7e6a7 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -108,20 +108,26 @@ public:
108 108
109 PerfStats::Results GetAndResetPerfStats(); 109 PerfStats::Results GetAndResetPerfStats();
110 110
111 /** 111 ARM_Interface& CurrentArmInterface() {
112 * Gets a reference to the emulated CPU. 112 return CurrentCpuCore().ArmInterface();
113 * @returns A reference to the emulated CPU. 113 }
114 */ 114
115 ARM_Interface& CPU() { 115 ARM_Interface& ArmInterface(size_t core_index) {
116 return CurrentCpuCore().CPU(); 116 ASSERT(core_index < NUM_CPU_CORES);
117 return cpu_cores[core_index]->ArmInterface();
117 } 118 }
118 119
119 Tegra::GPU& GPU() { 120 Tegra::GPU& GPU() {
120 return *gpu_core; 121 return *gpu_core;
121 } 122 }
122 123
123 Kernel::Scheduler& Scheduler() { 124 Kernel::Scheduler& CurrentScheduler() {
124 return CurrentCpuCore().Scheduler(); 125 return *CurrentCpuCore().Scheduler();
126 }
127
128 const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index) {
129 ASSERT(core_index < NUM_CPU_CORES);
130 return cpu_cores[core_index]->Scheduler();
125 } 131 }
126 132
127 Kernel::SharedPtr<Kernel::Process>& CurrentProcess() { 133 Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
@@ -198,8 +204,8 @@ private:
198 std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu; 204 std::map<std::thread::id, std::shared_ptr<Cpu>> thread_to_cpu;
199}; 205};
200 206
201inline ARM_Interface& CPU() { 207inline ARM_Interface& CurrentArmInterface() {
202 return System::GetInstance().CPU(); 208 return System::GetInstance().CurrentArmInterface();
203} 209}
204 210
205inline TelemetrySession& Telemetry() { 211inline TelemetrySession& Telemetry() {
diff --git a/src/core/core_cpu.cpp b/src/core/core_cpu.cpp
index 6bdfdd7df..a556f12e9 100644
--- a/src/core/core_cpu.cpp
+++ b/src/core/core_cpu.cpp
@@ -33,7 +33,7 @@ Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
33 arm_interface = std::make_shared<ARM_Unicorn>(); 33 arm_interface = std::make_shared<ARM_Unicorn>();
34 } 34 }
35 35
36 scheduler = std::make_unique<Kernel::Scheduler>(arm_interface.get()); 36 scheduler = std::make_shared<Kernel::Scheduler>(arm_interface.get());
37} 37}
38 38
39void Cpu::RunLoop(bool tight_loop) { 39void Cpu::RunLoop(bool tight_loop) {
diff --git a/src/core/core_cpu.h b/src/core/core_cpu.h
index e6ed698cc..06784c4ab 100644
--- a/src/core/core_cpu.h
+++ b/src/core/core_cpu.h
@@ -51,12 +51,16 @@ public:
51 51
52 void PrepareReschedule(); 52 void PrepareReschedule();
53 53
54 ARM_Interface& CPU() { 54 ARM_Interface& ArmInterface() {
55 return *arm_interface; 55 return *arm_interface;
56 } 56 }
57 57
58 Kernel::Scheduler& Scheduler() { 58 const ARM_Interface& ArmInterface() const {
59 return *scheduler; 59 return *arm_interface;
60 }
61
62 const std::shared_ptr<Kernel::Scheduler>& Scheduler() const {
63 return scheduler;
60 } 64 }
61 65
62 bool IsMainCore() const { 66 bool IsMainCore() const {
@@ -68,7 +72,7 @@ private:
68 72
69 std::shared_ptr<ARM_Interface> arm_interface; 73 std::shared_ptr<ARM_Interface> arm_interface;
70 std::shared_ptr<CpuBarrier> cpu_barrier; 74 std::shared_ptr<CpuBarrier> cpu_barrier;
71 std::unique_ptr<Kernel::Scheduler> scheduler; 75 std::shared_ptr<Kernel::Scheduler> scheduler;
72 76
73 bool reschedule_pending{}; 77 bool reschedule_pending{};
74 size_t core_index; 78 size_t core_index;
diff --git a/src/core/gdbstub/gdbstub.cpp b/src/core/gdbstub/gdbstub.cpp
index 46606b992..6c5a40ba8 100644
--- a/src/core/gdbstub/gdbstub.cpp
+++ b/src/core/gdbstub/gdbstub.cpp
@@ -598,11 +598,11 @@ static void ReadRegister() {
598 } 598 }
599 599
600 if (id <= SP_REGISTER) { 600 if (id <= SP_REGISTER) {
601 LongToGdbHex(reply, Core::CPU().GetReg(static_cast<int>(id))); 601 LongToGdbHex(reply, Core::CurrentArmInterface().GetReg(static_cast<int>(id)));
602 } else if (id == PC_REGISTER) { 602 } else if (id == PC_REGISTER) {
603 LongToGdbHex(reply, Core::CPU().GetPC()); 603 LongToGdbHex(reply, Core::CurrentArmInterface().GetPC());
604 } else if (id == CPSR_REGISTER) { 604 } else if (id == CPSR_REGISTER) {
605 IntToGdbHex(reply, Core::CPU().GetCPSR()); 605 IntToGdbHex(reply, Core::CurrentArmInterface().GetCPSR());
606 } else { 606 } else {
607 return SendReply("E01"); 607 return SendReply("E01");
608 } 608 }
@@ -618,16 +618,16 @@ static void ReadRegisters() {
618 u8* bufptr = buffer; 618 u8* bufptr = buffer;
619 619
620 for (int reg = 0; reg <= SP_REGISTER; reg++) { 620 for (int reg = 0; reg <= SP_REGISTER; reg++) {
621 LongToGdbHex(bufptr + reg * 16, Core::CPU().GetReg(reg)); 621 LongToGdbHex(bufptr + reg * 16, Core::CurrentArmInterface().GetReg(reg));
622 } 622 }
623 623
624 bufptr += (32 * 16); 624 bufptr += (32 * 16);
625 625
626 LongToGdbHex(bufptr, Core::CPU().GetPC()); 626 LongToGdbHex(bufptr, Core::CurrentArmInterface().GetPC());
627 627
628 bufptr += 16; 628 bufptr += 16;
629 629
630 IntToGdbHex(bufptr, Core::CPU().GetCPSR()); 630 IntToGdbHex(bufptr, Core::CurrentArmInterface().GetCPSR());
631 631
632 bufptr += 8; 632 bufptr += 8;
633 633
@@ -646,11 +646,11 @@ static void WriteRegister() {
646 } 646 }
647 647
648 if (id <= SP_REGISTER) { 648 if (id <= SP_REGISTER) {
649 Core::CPU().SetReg(id, GdbHexToLong(buffer_ptr)); 649 Core::CurrentArmInterface().SetReg(id, GdbHexToLong(buffer_ptr));
650 } else if (id == PC_REGISTER) { 650 } else if (id == PC_REGISTER) {
651 Core::CPU().SetPC(GdbHexToLong(buffer_ptr)); 651 Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr));
652 } else if (id == CPSR_REGISTER) { 652 } else if (id == CPSR_REGISTER) {
653 Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr)); 653 Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr));
654 } else { 654 } else {
655 return SendReply("E01"); 655 return SendReply("E01");
656 } 656 }
@@ -667,11 +667,11 @@ static void WriteRegisters() {
667 667
668 for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) { 668 for (int i = 0, reg = 0; reg <= CPSR_REGISTER; i++, reg++) {
669 if (reg <= SP_REGISTER) { 669 if (reg <= SP_REGISTER) {
670 Core::CPU().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16)); 670 Core::CurrentArmInterface().SetReg(reg, GdbHexToLong(buffer_ptr + i * 16));
671 } else if (reg == PC_REGISTER) { 671 } else if (reg == PC_REGISTER) {
672 Core::CPU().SetPC(GdbHexToLong(buffer_ptr + i * 16)); 672 Core::CurrentArmInterface().SetPC(GdbHexToLong(buffer_ptr + i * 16));
673 } else if (reg == CPSR_REGISTER) { 673 } else if (reg == CPSR_REGISTER) {
674 Core::CPU().SetCPSR(GdbHexToInt(buffer_ptr + i * 16)); 674 Core::CurrentArmInterface().SetCPSR(GdbHexToInt(buffer_ptr + i * 16));
675 } else { 675 } else {
676 UNIMPLEMENTED(); 676 UNIMPLEMENTED();
677 } 677 }
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 72b5c05f2..520510b61 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -485,22 +485,28 @@ static void ExitProcess() {
485 485
486 Core::CurrentProcess()->status = ProcessStatus::Exited; 486 Core::CurrentProcess()->status = ProcessStatus::Exited;
487 487
488 // Stop all the process threads that are currently waiting for objects. 488 auto stop_threads = [](const std::vector<SharedPtr<Thread>>& thread_list) {
489 auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); 489 for (auto& thread : thread_list) {
490 for (auto& thread : thread_list) { 490 if (thread->owner_process != Core::CurrentProcess())
491 if (thread->owner_process != Core::CurrentProcess()) 491 continue;
492 continue;
493 492
494 if (thread == GetCurrentThread()) 493 if (thread == GetCurrentThread())
495 continue; 494 continue;
496 495
497 // TODO(Subv): When are the other running/ready threads terminated? 496 // TODO(Subv): When are the other running/ready threads terminated?
498 ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY || 497 ASSERT_MSG(thread->status == THREADSTATUS_WAIT_SYNCH_ANY ||
499 thread->status == THREADSTATUS_WAIT_SYNCH_ALL, 498 thread->status == THREADSTATUS_WAIT_SYNCH_ALL,
500 "Exiting processes with non-waiting threads is currently unimplemented"); 499 "Exiting processes with non-waiting threads is currently unimplemented");
501 500
502 thread->Stop(); 501 thread->Stop();
503 } 502 }
503 };
504
505 auto& system = Core::System::GetInstance();
506 stop_threads(system.Scheduler(0)->GetThreadList());
507 stop_threads(system.Scheduler(1)->GetThreadList());
508 stop_threads(system.Scheduler(2)->GetThreadList());
509 stop_threads(system.Scheduler(3)->GetThreadList());
504 510
505 // Kill the current thread 511 // Kill the current thread
506 GetCurrentThread()->Stop(); 512 GetCurrentThread()->Stop();
@@ -530,14 +536,9 @@ static ResultCode CreateThread(Handle* out_handle, VAddr entry_point, u64 arg, V
530 536
531 switch (processor_id) { 537 switch (processor_id) {
532 case THREADPROCESSORID_0: 538 case THREADPROCESSORID_0:
533 break;
534 case THREADPROCESSORID_1: 539 case THREADPROCESSORID_1:
535 case THREADPROCESSORID_2: 540 case THREADPROCESSORID_2:
536 case THREADPROCESSORID_3: 541 case THREADPROCESSORID_3:
537 // TODO(bunnei): Implement support for other processor IDs
538 NGLOG_ERROR(Kernel_SVC,
539 "Newly created thread must run in another thread ({}), unimplemented.",
540 processor_id);
541 break; 542 break;
542 default: 543 default:
543 ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id); 544 ASSERT_MSG(false, "Unsupported thread processor ID: {}", processor_id);
@@ -576,7 +577,7 @@ static ResultCode StartThread(Handle thread_handle) {
576 577
577/// Called when a thread exits 578/// Called when a thread exits
578static void ExitThread() { 579static void ExitThread() {
579 NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CPU().GetPC()); 580 NGLOG_TRACE(Kernel_SVC, "called, pc=0x{:08X}", Core::CurrentArmInterface().GetPC());
580 581
581 ExitCurrentThread(); 582 ExitCurrentThread();
582 Core::System::GetInstance().PrepareReschedule(); 583 Core::System::GetInstance().PrepareReschedule();
@@ -588,7 +589,7 @@ static void SleepThread(s64 nanoseconds) {
588 589
589 // Don't attempt to yield execution if there are no available threads to run, 590 // Don't attempt to yield execution if there are no available threads to run,
590 // this way we avoid a useless reschedule to the idle thread. 591 // this way we avoid a useless reschedule to the idle thread.
591 if (nanoseconds == 0 && !Core::System::GetInstance().Scheduler().HaveReadyThreads()) 592 if (nanoseconds == 0 && !Core::System::GetInstance().CurrentScheduler().HaveReadyThreads())
592 return; 593 return;
593 594
594 // Sleep current thread and check for next thread to schedule 595 // Sleep current thread and check for next thread to schedule
@@ -634,7 +635,7 @@ static ResultCode SignalProcessWideKey(VAddr condition_variable_addr, s32 target
634 condition_variable_addr, target); 635 condition_variable_addr, target);
635 636
636 u32 processed = 0; 637 u32 processed = 0;
637 auto& thread_list = Core::System::GetInstance().Scheduler().GetThreadList(); 638 auto& thread_list = Core::System::GetInstance().CurrentScheduler().GetThreadList();
638 639
639 for (auto& thread : thread_list) { 640 for (auto& thread : thread_list) {
640 if (thread->condvar_wait_address != condition_variable_addr) 641 if (thread->condvar_wait_address != condition_variable_addr)
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index c86ad3e04..40aa88cc1 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -13,14 +13,14 @@
13 13
14namespace Kernel { 14namespace Kernel {
15 15
16#define PARAM(n) Core::CPU().GetReg(n) 16#define PARAM(n) Core::CurrentArmInterface().GetReg(n)
17 17
18/** 18/**
19 * HLE a function return from the current ARM userland process 19 * HLE a function return from the current ARM userland process
20 * @param res Result to return 20 * @param res Result to return
21 */ 21 */
22static inline void FuncReturn(u64 res) { 22static inline void FuncReturn(u64 res) {
23 Core::CPU().SetReg(0, res); 23 Core::CurrentArmInterface().SetReg(0, res);
24} 24}
25 25
26//////////////////////////////////////////////////////////////////////////////////////////////////// 26////////////////////////////////////////////////////////////////////////////////////////////////////
@@ -45,7 +45,7 @@ template <ResultCode func(u32*, u32)>
45void SvcWrap() { 45void SvcWrap() {
46 u32 param_1 = 0; 46 u32 param_1 = 0;
47 u32 retval = func(&param_1, (u32)PARAM(1)).raw; 47 u32 retval = func(&param_1, (u32)PARAM(1)).raw;
48 Core::CPU().SetReg(1, param_1); 48 Core::CurrentArmInterface().SetReg(1, param_1);
49 FuncReturn(retval); 49 FuncReturn(retval);
50} 50}
51 51
@@ -53,7 +53,7 @@ template <ResultCode func(u32*, u64)>
53void SvcWrap() { 53void SvcWrap() {
54 u32 param_1 = 0; 54 u32 param_1 = 0;
55 u32 retval = func(&param_1, PARAM(1)).raw; 55 u32 retval = func(&param_1, PARAM(1)).raw;
56 Core::CPU().SetReg(1, param_1); 56 Core::CurrentArmInterface().SetReg(1, param_1);
57 FuncReturn(retval); 57 FuncReturn(retval);
58} 58}
59 59
@@ -66,7 +66,7 @@ template <ResultCode func(u64*, u64)>
66void SvcWrap() { 66void SvcWrap() {
67 u64 param_1 = 0; 67 u64 param_1 = 0;
68 u32 retval = func(&param_1, PARAM(1)).raw; 68 u32 retval = func(&param_1, PARAM(1)).raw;
69 Core::CPU().SetReg(1, param_1); 69 Core::CurrentArmInterface().SetReg(1, param_1);
70 FuncReturn(retval); 70 FuncReturn(retval);
71} 71}
72 72
@@ -85,8 +85,8 @@ void SvcWrap() {
85 u32 param_1 = 0; 85 u32 param_1 = 0;
86 u64 param_2 = 0; 86 u64 param_2 = 0;
87 ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2); 87 ResultCode retval = func((u32)(PARAM(2) & 0xFFFFFFFF), &param_1, &param_2);
88 Core::CPU().SetReg(1, param_1); 88 Core::CurrentArmInterface().SetReg(1, param_1);
89 Core::CPU().SetReg(2, param_2); 89 Core::CurrentArmInterface().SetReg(2, param_2);
90 FuncReturn(retval.raw); 90 FuncReturn(retval.raw);
91} 91}
92 92
@@ -120,7 +120,7 @@ template <ResultCode func(u32*, u64, u64, s64)>
120void SvcWrap() { 120void SvcWrap() {
121 u32 param_1 = 0; 121 u32 param_1 = 0;
122 ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3)); 122 ResultCode retval = func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (s64)PARAM(3));
123 Core::CPU().SetReg(1, param_1); 123 Core::CurrentArmInterface().SetReg(1, param_1);
124 FuncReturn(retval.raw); 124 FuncReturn(retval.raw);
125} 125}
126 126
@@ -133,7 +133,7 @@ template <ResultCode func(u64*, u64, u64, u64)>
133void SvcWrap() { 133void SvcWrap() {
134 u64 param_1 = 0; 134 u64 param_1 = 0;
135 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw; 135 u32 retval = func(&param_1, PARAM(1), PARAM(2), PARAM(3)).raw;
136 Core::CPU().SetReg(1, param_1); 136 Core::CurrentArmInterface().SetReg(1, param_1);
137 FuncReturn(retval); 137 FuncReturn(retval);
138} 138}
139 139
@@ -143,7 +143,7 @@ void SvcWrap() {
143 u32 retval = 143 u32 retval =
144 func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF)) 144 func(&param_1, PARAM(1), PARAM(2), PARAM(3), (u32)PARAM(4), (s32)(PARAM(5) & 0xFFFFFFFF))
145 .raw; 145 .raw;
146 Core::CPU().SetReg(1, param_1); 146 Core::CurrentArmInterface().SetReg(1, param_1);
147 FuncReturn(retval); 147 FuncReturn(retval);
148} 148}
149 149
@@ -166,7 +166,7 @@ template <ResultCode func(u32*, u64, u64, u32)>
166void SvcWrap() { 166void SvcWrap() {
167 u32 param_1 = 0; 167 u32 param_1 = 0;
168 u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; 168 u32 retval = func(&param_1, PARAM(1), PARAM(2), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
169 Core::CPU().SetReg(1, param_1); 169 Core::CurrentArmInterface().SetReg(1, param_1);
170 FuncReturn(retval); 170 FuncReturn(retval);
171} 171}
172 172
@@ -175,7 +175,7 @@ void SvcWrap() {
175 u32 param_1 = 0; 175 u32 param_1 = 0;
176 u32 retval = 176 u32 retval =
177 func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw; 177 func(&param_1, PARAM(1), (u32)(PARAM(2) & 0xFFFFFFFF), (u32)(PARAM(3) & 0xFFFFFFFF)).raw;
178 Core::CPU().SetReg(1, param_1); 178 Core::CurrentArmInterface().SetReg(1, param_1);
179 FuncReturn(retval); 179 FuncReturn(retval);
180} 180}
181 181
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index 1bd5d9ebf..0a5441684 100644
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -64,7 +64,7 @@ void Thread::Stop() {
64 // Clean up thread from ready queue 64 // Clean up thread from ready queue
65 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess) 65 // This is only needed when the thread is termintated forcefully (SVC TerminateProcess)
66 if (status == THREADSTATUS_READY) { 66 if (status == THREADSTATUS_READY) {
67 Core::System::GetInstance().Scheduler().UnscheduleThread(this, current_priority); 67 scheduler->UnscheduleThread(this, current_priority);
68 } 68 }
69 69
70 status = THREADSTATUS_DEAD; 70 status = THREADSTATUS_DEAD;
@@ -92,7 +92,7 @@ void WaitCurrentThread_Sleep() {
92void ExitCurrentThread() { 92void ExitCurrentThread() {
93 Thread* thread = GetCurrentThread(); 93 Thread* thread = GetCurrentThread();
94 thread->Stop(); 94 thread->Stop();
95 Core::System::GetInstance().Scheduler().RemoveThread(thread); 95 Core::System::GetInstance().CurrentScheduler().RemoveThread(thread);
96} 96}
97 97
98/** 98/**
@@ -188,7 +188,7 @@ void Thread::ResumeFromWait() {
188 wakeup_callback = nullptr; 188 wakeup_callback = nullptr;
189 189
190 status = THREADSTATUS_READY; 190 status = THREADSTATUS_READY;
191 Core::System::GetInstance().Scheduler().ScheduleThread(this, current_priority); 191 scheduler->ScheduleThread(this, current_priority);
192 Core::System::GetInstance().PrepareReschedule(); 192 Core::System::GetInstance().PrepareReschedule();
193} 193}
194 194
@@ -259,8 +259,6 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
259 259
260 SharedPtr<Thread> thread(new Thread); 260 SharedPtr<Thread> thread(new Thread);
261 261
262 Core::System::GetInstance().Scheduler().AddThread(thread, priority);
263
264 thread->thread_id = NewThreadId(); 262 thread->thread_id = NewThreadId();
265 thread->status = THREADSTATUS_DORMANT; 263 thread->status = THREADSTATUS_DORMANT;
266 thread->entry_point = entry_point; 264 thread->entry_point = entry_point;
@@ -275,6 +273,8 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point,
275 thread->name = std::move(name); 273 thread->name = std::move(name);
276 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap(); 274 thread->callback_handle = wakeup_callback_handle_table.Create(thread).Unwrap();
277 thread->owner_process = owner_process; 275 thread->owner_process = owner_process;
276 thread->scheduler = Core::System().GetInstance().Scheduler(static_cast<size_t>(processor_id));
277 thread->scheduler->AddThread(thread, priority);
278 278
279 // Find the next available TLS index, and mark it as used 279 // Find the next available TLS index, and mark it as used
280 auto& tls_slots = owner_process->tls_slots; 280 auto& tls_slots = owner_process->tls_slots;
@@ -337,7 +337,7 @@ void Thread::SetPriority(u32 priority) {
337} 337}
338 338
339void Thread::BoostPriority(u32 priority) { 339void Thread::BoostPriority(u32 priority) {
340 Core::System::GetInstance().Scheduler().SetThreadPriority(this, priority); 340 scheduler->SetThreadPriority(this, priority);
341 current_priority = priority; 341 current_priority = priority;
342} 342}
343 343
@@ -406,7 +406,7 @@ void Thread::UpdatePriority() {
406 if (new_priority == current_priority) 406 if (new_priority == current_priority)
407 return; 407 return;
408 408
409 Core::System::GetInstance().Scheduler().SetThreadPriority(this, new_priority); 409 scheduler->SetThreadPriority(this, new_priority);
410 410
411 current_priority = new_priority; 411 current_priority = new_priority;
412 412
@@ -421,7 +421,7 @@ void Thread::UpdatePriority() {
421 * Gets the current thread 421 * Gets the current thread
422 */ 422 */
423Thread* GetCurrentThread() { 423Thread* GetCurrentThread() {
424 return Core::System::GetInstance().Scheduler().GetCurrentThread(); 424 return Core::System::GetInstance().CurrentScheduler().GetCurrentThread();
425} 425}
426 426
427void ThreadingInit() { 427void ThreadingInit() {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index e0a3c0934..0a3bb1183 100644
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <memory>
7#include <string> 8#include <string>
8#include <unordered_map> 9#include <unordered_map>
9#include <vector> 10#include <vector>
@@ -56,6 +57,7 @@ enum class ThreadWakeupReason {
56namespace Kernel { 57namespace Kernel {
57 58
58class Process; 59class Process;
60class Scheduler;
59 61
60class Thread final : public WaitObject { 62class Thread final : public WaitObject {
61public: 63public:
@@ -240,6 +242,8 @@ public:
240 // available. In case of a timeout, the object will be nullptr. 242 // available. In case of a timeout, the object will be nullptr.
241 std::function<WakeupCallback> wakeup_callback; 243 std::function<WakeupCallback> wakeup_callback;
242 244
245 std::shared_ptr<Scheduler> scheduler;
246
243private: 247private:
244 Thread(); 248 Thread();
245 ~Thread() override; 249 ~Thread() override;
diff --git a/src/core/hle/kernel/vm_manager.cpp b/src/core/hle/kernel/vm_manager.cpp
index 2f0044c11..676e5b282 100644
--- a/src/core/hle/kernel/vm_manager.cpp
+++ b/src/core/hle/kernel/vm_manager.cpp
@@ -104,8 +104,15 @@ ResultVal<VMManager::VMAHandle> VMManager::MapMemoryBlock(VAddr target,
104 VirtualMemoryArea& final_vma = vma_handle->second; 104 VirtualMemoryArea& final_vma = vma_handle->second;
105 ASSERT(final_vma.size == size); 105 ASSERT(final_vma.size == size);
106 106
107 Core::CPU().MapBackingMemory(target, size, block->data() + offset, 107 auto& system = Core::System::GetInstance();
108 VMAPermission::ReadWriteExecute); 108 system.ArmInterface(0).MapBackingMemory(target, size, block->data() + offset,
109 VMAPermission::ReadWriteExecute);
110 system.ArmInterface(1).MapBackingMemory(target, size, block->data() + offset,
111 VMAPermission::ReadWriteExecute);
112 system.ArmInterface(2).MapBackingMemory(target, size, block->data() + offset,
113 VMAPermission::ReadWriteExecute);
114 system.ArmInterface(3).MapBackingMemory(target, size, block->data() + offset,
115 VMAPermission::ReadWriteExecute);
109 116
110 final_vma.type = VMAType::AllocatedMemoryBlock; 117 final_vma.type = VMAType::AllocatedMemoryBlock;
111 final_vma.permissions = VMAPermission::ReadWrite; 118 final_vma.permissions = VMAPermission::ReadWrite;
@@ -126,7 +133,11 @@ ResultVal<VMManager::VMAHandle> VMManager::MapBackingMemory(VAddr target, u8* me
126 VirtualMemoryArea& final_vma = vma_handle->second; 133 VirtualMemoryArea& final_vma = vma_handle->second;
127 ASSERT(final_vma.size == size); 134 ASSERT(final_vma.size == size);
128 135
129 Core::CPU().MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute); 136 auto& system = Core::System::GetInstance();
137 system.ArmInterface(0).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
138 system.ArmInterface(1).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
139 system.ArmInterface(2).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
140 system.ArmInterface(3).MapBackingMemory(target, size, memory, VMAPermission::ReadWriteExecute);
130 141
131 final_vma.type = VMAType::BackingMemory; 142 final_vma.type = VMAType::BackingMemory;
132 final_vma.permissions = VMAPermission::ReadWrite; 143 final_vma.permissions = VMAPermission::ReadWrite;
@@ -184,7 +195,11 @@ ResultCode VMManager::UnmapRange(VAddr target, u64 size) {
184 195
185 ASSERT(FindVMA(target)->second.size >= size); 196 ASSERT(FindVMA(target)->second.size >= size);
186 197
187 Core::CPU().UnmapMemory(target, size); 198 auto& system = Core::System::GetInstance();
199 system.ArmInterface(0).UnmapMemory(target, size);
200 system.ArmInterface(1).UnmapMemory(target, size);
201 system.ArmInterface(2).UnmapMemory(target, size);
202 system.ArmInterface(3).UnmapMemory(target, size);
188 203
189 return RESULT_SUCCESS; 204 return RESULT_SUCCESS;
190} 205}
diff --git a/src/core/memory.cpp b/src/core/memory.cpp
index db8211463..3b81acd63 100644
--- a/src/core/memory.cpp
+++ b/src/core/memory.cpp
@@ -28,8 +28,13 @@ static PageTable* current_page_table = nullptr;
28 28
29void SetCurrentPageTable(PageTable* page_table) { 29void SetCurrentPageTable(PageTable* page_table) {
30 current_page_table = page_table; 30 current_page_table = page_table;
31 if (Core::System::GetInstance().IsPoweredOn()) { 31
32 Core::CPU().PageTableChanged(); 32 auto& system = Core::System::GetInstance();
33 if (system.IsPoweredOn()) {
34 system.ArmInterface(0).PageTableChanged();
35 system.ArmInterface(1).PageTableChanged();
36 system.ArmInterface(2).PageTableChanged();
37 system.ArmInterface(3).PageTableChanged();
33 } 38 }
34} 39}
35 40
diff --git a/src/yuzu/debugger/registers.cpp b/src/yuzu/debugger/registers.cpp
index 06e2d1647..178cc65a7 100644
--- a/src/yuzu/debugger/registers.cpp
+++ b/src/yuzu/debugger/registers.cpp
@@ -63,7 +63,7 @@ void RegistersWidget::OnDebugModeEntered() {
63 63
64 for (int i = 0; i < core_registers->childCount(); ++i) 64 for (int i = 0; i < core_registers->childCount(); ++i)
65 core_registers->child(i)->setText( 65 core_registers->child(i)->setText(
66 1, QString("0x%1").arg(Core::CPU().GetReg(i), 8, 16, QLatin1Char('0'))); 66 1, QString("0x%1").arg(Core::CurrentArmInterface().GetReg(i), 8, 16, QLatin1Char('0')));
67 67
68 UpdateCPSRValues(); 68 UpdateCPSRValues();
69} 69}
@@ -122,7 +122,7 @@ void RegistersWidget::CreateCPSRChildren() {
122} 122}
123 123
124void RegistersWidget::UpdateCPSRValues() { 124void RegistersWidget::UpdateCPSRValues() {
125 const u32 cpsr_val = Core::CPU().GetCPSR(); 125 const u32 cpsr_val = Core::CurrentArmInterface().GetCPSR();
126 126
127 cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0'))); 127 cpsr->setText(1, QString("0x%1").arg(cpsr_val, 8, 16, QLatin1Char('0')));
128 cpsr->child(0)->setText( 128 cpsr->child(0)->setText(
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index acc4c2e0b..f05c98cc3 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -51,7 +51,7 @@ std::size_t WaitTreeItem::Row() const {
51} 51}
52 52
53std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() { 53std::vector<std::unique_ptr<WaitTreeThread>> WaitTreeItem::MakeThreadItemList() {
54 const auto& threads = Core::System::GetInstance().Scheduler().GetThreadList(); 54 const auto& threads = Core::System::GetInstance().Scheduler(0)->GetThreadList();
55 std::vector<std::unique_ptr<WaitTreeThread>> item_list; 55 std::vector<std::unique_ptr<WaitTreeThread>> item_list;
56 item_list.reserve(threads.size()); 56 item_list.reserve(threads.size());
57 for (std::size_t i = 0; i < threads.size(); ++i) { 57 for (std::size_t i = 0; i < threads.size(); ++i) {