1 // Copyright 2014 Citra Emulator Project
2 // Licensed under GPLv2 or any later version
3 // Refer to the license.txt file included.
4 
5 #include <array>
6 #include <atomic>
7 #include <bitset>
8 #include <functional>
9 #include <memory>
10 #include <thread>
11 #include <unordered_map>
12 #include <utility>
13 
14 #include "common/assert.h"
15 #include "common/logging/log.h"
16 #include "common/microprofile.h"
17 #include "common/thread.h"
18 #include "core/arm/arm_interface.h"
19 #include "core/arm/cpu_interrupt_handler.h"
20 #include "core/arm/exclusive_monitor.h"
21 #include "core/core.h"
22 #include "core/core_timing.h"
23 #include "core/core_timing_util.h"
24 #include "core/cpu_manager.h"
25 #include "core/device_memory.h"
26 #include "core/hardware_properties.h"
27 #include "core/hle/kernel/client_port.h"
28 #include "core/hle/kernel/errors.h"
29 #include "core/hle/kernel/handle_table.h"
30 #include "core/hle/kernel/kernel.h"
31 #include "core/hle/kernel/memory/memory_layout.h"
32 #include "core/hle/kernel/memory/memory_manager.h"
33 #include "core/hle/kernel/memory/slab_heap.h"
34 #include "core/hle/kernel/physical_core.h"
35 #include "core/hle/kernel/process.h"
36 #include "core/hle/kernel/resource_limit.h"
37 #include "core/hle/kernel/scheduler.h"
38 #include "core/hle/kernel/shared_memory.h"
39 #include "core/hle/kernel/synchronization.h"
40 #include "core/hle/kernel/thread.h"
41 #include "core/hle/kernel/time_manager.h"
42 #include "core/hle/lock.h"
43 #include "core/hle/result.h"
44 #include "core/memory.h"
45 
46 MICROPROFILE_DEFINE(Kernel_SVC, "Kernel", "SVC", MP_RGB(70, 200, 70));
47 
48 namespace Kernel {
49 
50 struct KernelCore::Impl {
ImplKernel::KernelCore::Impl51     explicit Impl(Core::System& system, KernelCore& kernel)
52         : global_scheduler{kernel}, synchronization{system}, time_manager{system},
53           global_handle_table{kernel}, system{system} {}
54 
SetMulticoreKernel::KernelCore::Impl55     void SetMulticore(bool is_multicore) {
56         this->is_multicore = is_multicore;
57     }
58 
InitializeKernel::KernelCore::Impl59     void Initialize(KernelCore& kernel) {
60         Shutdown();
61         RegisterHostThread();
62 
63         InitializePhysicalCores();
64         InitializeSystemResourceLimit(kernel);
65         InitializeMemoryLayout();
66         InitializePreemption(kernel);
67         InitializeSchedulers();
68         InitializeSuspendThreads();
69     }
70 
InitializeCoresKernel::KernelCore::Impl71     void InitializeCores() {
72         for (auto& core : cores) {
73             core.Initialize(current_process->Is64BitProcess());
74         }
75     }
76 
ShutdownKernel::KernelCore::Impl77     void Shutdown() {
78         next_object_id = 0;
79         next_kernel_process_id = Process::InitialKIPIDMin;
80         next_user_process_id = Process::ProcessIDMin;
81         next_thread_id = 1;
82 
83         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
84             if (suspend_threads[i]) {
85                 suspend_threads[i].reset();
86             }
87         }
88 
89         for (std::size_t i = 0; i < cores.size(); i++) {
90             cores[i].Shutdown();
91             schedulers[i].reset();
92         }
93         cores.clear();
94 
95         process_list.clear();
96         current_process = nullptr;
97 
98         system_resource_limit = nullptr;
99 
100         global_handle_table.Clear();
101         preemption_event = nullptr;
102 
103         global_scheduler.Shutdown();
104 
105         named_ports.clear();
106 
107         for (auto& core : cores) {
108             core.Shutdown();
109         }
110         cores.clear();
111 
112         exclusive_monitor.reset();
113 
114         num_host_threads = 0;
115         std::fill(register_host_thread_keys.begin(), register_host_thread_keys.end(),
116                   std::thread::id{});
117         std::fill(register_host_thread_values.begin(), register_host_thread_values.end(), 0);
118     }
119 
InitializePhysicalCoresKernel::KernelCore::Impl120     void InitializePhysicalCores() {
121         exclusive_monitor =
122             Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
123         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
124             schedulers[i] = std::make_unique<Kernel::Scheduler>(system, i);
125             cores.emplace_back(i, system, *schedulers[i], interrupts);
126         }
127     }
128 
InitializeSchedulersKernel::KernelCore::Impl129     void InitializeSchedulers() {
130         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
131             cores[i].Scheduler().Initialize();
132         }
133     }
134 
135     // Creates the default system resource limit
InitializeSystemResourceLimitKernel::KernelCore::Impl136     void InitializeSystemResourceLimit(KernelCore& kernel) {
137         system_resource_limit = ResourceLimit::Create(kernel);
138 
139         // If setting the default system values fails, then something seriously wrong has occurred.
140         ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
141                    .IsSuccess());
142         ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
143         ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
144         ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
145         ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
146 
147         if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
148             !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
149             UNREACHABLE();
150         }
151     }
152 
InitializePreemptionKernel::KernelCore::Impl153     void InitializePreemption(KernelCore& kernel) {
154         preemption_event = Core::Timing::CreateEvent(
155             "PreemptionCallback", [this, &kernel](std::uintptr_t, std::chrono::nanoseconds) {
156                 {
157                     SchedulerLock lock(kernel);
158                     global_scheduler.PreemptThreads();
159                 }
160                 const auto time_interval = std::chrono::nanoseconds{
161                     Core::Timing::msToCycles(std::chrono::milliseconds(10))};
162                 system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
163             });
164 
165         const auto time_interval =
166             std::chrono::nanoseconds{Core::Timing::msToCycles(std::chrono::milliseconds(10))};
167         system.CoreTiming().ScheduleEvent(time_interval, preemption_event);
168     }
169 
InitializeSuspendThreadsKernel::KernelCore::Impl170     void InitializeSuspendThreads() {
171         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
172             std::string name = "Suspend Thread Id:" + std::to_string(i);
173             std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
174             void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
175             const auto type =
176                 static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
177             auto thread_res =
178                 Thread::Create(system, type, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
179                                nullptr, std::move(init_func), init_func_parameter);
180 
181             suspend_threads[i] = std::move(thread_res).Unwrap();
182         }
183     }
184 
MakeCurrentProcessKernel::KernelCore::Impl185     void MakeCurrentProcess(Process* process) {
186         current_process = process;
187         if (process == nullptr) {
188             return;
189         }
190 
191         const u32 core_id = GetCurrentHostThreadID();
192         if (core_id < Core::Hardware::NUM_CPU_CORES) {
193             system.Memory().SetCurrentPageTable(*process, core_id);
194         }
195     }
196 
RegisterCoreThreadKernel::KernelCore::Impl197     void RegisterCoreThread(std::size_t core_id) {
198         const std::thread::id this_id = std::this_thread::get_id();
199         if (!is_multicore) {
200             single_core_thread_id = this_id;
201         }
202         const auto end =
203             register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
204         const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
205         ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
206         ASSERT(it == end);
207         InsertHostThread(static_cast<u32>(core_id));
208     }
209 
RegisterHostThreadKernel::KernelCore::Impl210     void RegisterHostThread() {
211         const std::thread::id this_id = std::this_thread::get_id();
212         const auto end =
213             register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
214         const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
215         if (it == end) {
216             InsertHostThread(registered_thread_ids++);
217         }
218     }
219 
InsertHostThreadKernel::KernelCore::Impl220     void InsertHostThread(u32 value) {
221         const size_t index = num_host_threads++;
222         ASSERT_MSG(index < NUM_REGISTRABLE_HOST_THREADS, "Too many host threads");
223         register_host_thread_values[index] = value;
224         register_host_thread_keys[index] = std::this_thread::get_id();
225     }
226 
GetCurrentHostThreadIDKernel::KernelCore::Impl227     [[nodiscard]] u32 GetCurrentHostThreadID() const {
228         const std::thread::id this_id = std::this_thread::get_id();
229         if (!is_multicore && single_core_thread_id == this_id) {
230             return static_cast<u32>(system.GetCpuManager().CurrentCore());
231         }
232         const auto end =
233             register_host_thread_keys.begin() + static_cast<ptrdiff_t>(num_host_threads);
234         const auto it = std::find(register_host_thread_keys.begin(), end, this_id);
235         if (it == end) {
236             return Core::INVALID_HOST_THREAD_ID;
237         }
238         return register_host_thread_values[static_cast<size_t>(
239             std::distance(register_host_thread_keys.begin(), it))];
240     }
241 
GetCurrentEmuThreadIDKernel::KernelCore::Impl242     Core::EmuThreadHandle GetCurrentEmuThreadID() const {
243         Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
244         result.host_handle = GetCurrentHostThreadID();
245         if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
246             return result;
247         }
248         const Kernel::Scheduler& sched = cores[result.host_handle].Scheduler();
249         const Kernel::Thread* current = sched.GetCurrentThread();
250         if (current != nullptr && !current->IsPhantomMode()) {
251             result.guest_handle = current->GetGlobalHandle();
252         } else {
253             result.guest_handle = InvalidHandle;
254         }
255         return result;
256     }
257 
InitializeMemoryLayoutKernel::KernelCore::Impl258     void InitializeMemoryLayout() {
259         // Initialize memory layout
260         constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()};
261         constexpr std::size_t hid_size{0x40000};
262         constexpr std::size_t font_size{0x1100000};
263         constexpr std::size_t irs_size{0x8000};
264         constexpr std::size_t time_size{0x1000};
265         constexpr PAddr hid_addr{layout.System().StartAddress()};
266         constexpr PAddr font_pa{layout.System().StartAddress() + hid_size};
267         constexpr PAddr irs_addr{layout.System().StartAddress() + hid_size + font_size};
268         constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
269 
270         // Initialize memory manager
271         memory_manager = std::make_unique<Memory::MemoryManager>();
272         memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
273                                           layout.Application().StartAddress(),
274                                           layout.Application().EndAddress());
275         memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet,
276                                           layout.Applet().StartAddress(),
277                                           layout.Applet().EndAddress());
278         memory_manager->InitializeManager(Memory::MemoryManager::Pool::System,
279                                           layout.System().StartAddress(),
280                                           layout.System().EndAddress());
281 
282         hid_shared_mem = Kernel::SharedMemory::Create(
283             system.Kernel(), system.DeviceMemory(), nullptr,
284             {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None,
285             Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory");
286         font_shared_mem = Kernel::SharedMemory::Create(
287             system.Kernel(), system.DeviceMemory(), nullptr,
288             {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None,
289             Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory");
290         irs_shared_mem = Kernel::SharedMemory::Create(
291             system.Kernel(), system.DeviceMemory(), nullptr,
292             {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None,
293             Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory");
294         time_shared_mem = Kernel::SharedMemory::Create(
295             system.Kernel(), system.DeviceMemory(), nullptr,
296             {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None,
297             Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory");
298 
299         // Allocate slab heaps
300         user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>();
301 
302         // Initialize slab heaps
303         constexpr u64 user_slab_heap_size{0x3de000};
304         user_slab_heap_pages->Initialize(
305             system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase),
306             user_slab_heap_size);
307     }
308 
309     std::atomic<u32> next_object_id{0};
310     std::atomic<u64> next_kernel_process_id{Process::InitialKIPIDMin};
311     std::atomic<u64> next_user_process_id{Process::ProcessIDMin};
312     std::atomic<u64> next_thread_id{1};
313 
314     // Lists all processes that exist in the current session.
315     std::vector<std::shared_ptr<Process>> process_list;
316     Process* current_process = nullptr;
317     Kernel::GlobalScheduler global_scheduler;
318     Kernel::Synchronization synchronization;
319     Kernel::TimeManager time_manager;
320 
321     std::shared_ptr<ResourceLimit> system_resource_limit;
322 
323     std::shared_ptr<Core::Timing::EventType> preemption_event;
324 
325     // This is the kernel's handle table or supervisor handle table which
326     // stores all the objects in place.
327     HandleTable global_handle_table;
328 
329     /// Map of named ports managed by the kernel, which can be retrieved using
330     /// the ConnectToPort SVC.
331     NamedPortTable named_ports;
332 
333     std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
334     std::vector<Kernel::PhysicalCore> cores;
335 
336     // 0-3 IDs represent core threads, >3 represent others
337     std::atomic<u32> registered_thread_ids{Core::Hardware::NUM_CPU_CORES};
338 
339     // Number of host threads is a relatively high number to avoid overflowing
340     static constexpr size_t NUM_REGISTRABLE_HOST_THREADS = 64;
341     std::atomic<size_t> num_host_threads{0};
342     std::array<std::atomic<std::thread::id>, NUM_REGISTRABLE_HOST_THREADS>
343         register_host_thread_keys{};
344     std::array<std::atomic<u32>, NUM_REGISTRABLE_HOST_THREADS> register_host_thread_values{};
345 
346     // Kernel memory management
347     std::unique_ptr<Memory::MemoryManager> memory_manager;
348     std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages;
349 
350     // Shared memory for services
351     std::shared_ptr<Kernel::SharedMemory> hid_shared_mem;
352     std::shared_ptr<Kernel::SharedMemory> font_shared_mem;
353     std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
354     std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
355 
356     std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
357     std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
358     std::array<std::unique_ptr<Kernel::Scheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
359 
360     bool is_multicore{};
361     std::thread::id single_core_thread_id{};
362 
363     std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
364 
365     // System context
366     Core::System& system;
367 };
368 
KernelCore(Core::System & system)369 KernelCore::KernelCore(Core::System& system) : impl{std::make_unique<Impl>(system, *this)} {}
~KernelCore()370 KernelCore::~KernelCore() {
371     Shutdown();
372 }
373 
SetMulticore(bool is_multicore)374 void KernelCore::SetMulticore(bool is_multicore) {
375     impl->SetMulticore(is_multicore);
376 }
377 
Initialize()378 void KernelCore::Initialize() {
379     impl->Initialize(*this);
380 }
381 
InitializeCores()382 void KernelCore::InitializeCores() {
383     impl->InitializeCores();
384 }
385 
Shutdown()386 void KernelCore::Shutdown() {
387     impl->Shutdown();
388 }
389 
GetSystemResourceLimit() const390 std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
391     return impl->system_resource_limit;
392 }
393 
RetrieveThreadFromGlobalHandleTable(Handle handle) const394 std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
395     return impl->global_handle_table.Get<Thread>(handle);
396 }
397 
AppendNewProcess(std::shared_ptr<Process> process)398 void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
399     impl->process_list.push_back(std::move(process));
400 }
401 
MakeCurrentProcess(Process * process)402 void KernelCore::MakeCurrentProcess(Process* process) {
403     impl->MakeCurrentProcess(process);
404 }
405 
CurrentProcess()406 Process* KernelCore::CurrentProcess() {
407     return impl->current_process;
408 }
409 
CurrentProcess() const410 const Process* KernelCore::CurrentProcess() const {
411     return impl->current_process;
412 }
413 
GetProcessList() const414 const std::vector<std::shared_ptr<Process>>& KernelCore::GetProcessList() const {
415     return impl->process_list;
416 }
417 
GlobalScheduler()418 Kernel::GlobalScheduler& KernelCore::GlobalScheduler() {
419     return impl->global_scheduler;
420 }
421 
GlobalScheduler() const422 const Kernel::GlobalScheduler& KernelCore::GlobalScheduler() const {
423     return impl->global_scheduler;
424 }
425 
Scheduler(std::size_t id)426 Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) {
427     return *impl->schedulers[id];
428 }
429 
Scheduler(std::size_t id) const430 const Kernel::Scheduler& KernelCore::Scheduler(std::size_t id) const {
431     return *impl->schedulers[id];
432 }
433 
PhysicalCore(std::size_t id)434 Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) {
435     return impl->cores[id];
436 }
437 
PhysicalCore(std::size_t id) const438 const Kernel::PhysicalCore& KernelCore::PhysicalCore(std::size_t id) const {
439     return impl->cores[id];
440 }
441 
CurrentPhysicalCore()442 Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() {
443     u32 core_id = impl->GetCurrentHostThreadID();
444     ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
445     return impl->cores[core_id];
446 }
447 
CurrentPhysicalCore() const448 const Kernel::PhysicalCore& KernelCore::CurrentPhysicalCore() const {
449     u32 core_id = impl->GetCurrentHostThreadID();
450     ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
451     return impl->cores[core_id];
452 }
453 
CurrentScheduler()454 Kernel::Scheduler& KernelCore::CurrentScheduler() {
455     u32 core_id = impl->GetCurrentHostThreadID();
456     ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
457     return *impl->schedulers[core_id];
458 }
459 
CurrentScheduler() const460 const Kernel::Scheduler& KernelCore::CurrentScheduler() const {
461     u32 core_id = impl->GetCurrentHostThreadID();
462     ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
463     return *impl->schedulers[core_id];
464 }
465 
Interrupts()466 std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts() {
467     return impl->interrupts;
468 }
469 
Interrupts() const470 const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& KernelCore::Interrupts()
471     const {
472     return impl->interrupts;
473 }
474 
Synchronization()475 Kernel::Synchronization& KernelCore::Synchronization() {
476     return impl->synchronization;
477 }
478 
Synchronization() const479 const Kernel::Synchronization& KernelCore::Synchronization() const {
480     return impl->synchronization;
481 }
482 
TimeManager()483 Kernel::TimeManager& KernelCore::TimeManager() {
484     return impl->time_manager;
485 }
486 
TimeManager() const487 const Kernel::TimeManager& KernelCore::TimeManager() const {
488     return impl->time_manager;
489 }
490 
GetExclusiveMonitor()491 Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
492     return *impl->exclusive_monitor;
493 }
494 
GetExclusiveMonitor() const495 const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
496     return *impl->exclusive_monitor;
497 }
498 
InvalidateAllInstructionCaches()499 void KernelCore::InvalidateAllInstructionCaches() {
500     for (auto& physical_core : impl->cores) {
501         physical_core.ArmInterface().ClearInstructionCache();
502     }
503 }
504 
InvalidateCpuInstructionCacheRange(VAddr addr,std::size_t size)505 void KernelCore::InvalidateCpuInstructionCacheRange(VAddr addr, std::size_t size) {
506     for (auto& physical_core : impl->cores) {
507         if (!physical_core.IsInitialized()) {
508             continue;
509         }
510         physical_core.ArmInterface().InvalidateCacheRange(addr, size);
511     }
512 }
513 
PrepareReschedule(std::size_t id)514 void KernelCore::PrepareReschedule(std::size_t id) {
515     // TODO: Reimplement, this
516 }
517 
AddNamedPort(std::string name,std::shared_ptr<ClientPort> port)518 void KernelCore::AddNamedPort(std::string name, std::shared_ptr<ClientPort> port) {
519     impl->named_ports.emplace(std::move(name), std::move(port));
520 }
521 
FindNamedPort(const std::string & name)522 KernelCore::NamedPortTable::iterator KernelCore::FindNamedPort(const std::string& name) {
523     return impl->named_ports.find(name);
524 }
525 
FindNamedPort(const std::string & name) const526 KernelCore::NamedPortTable::const_iterator KernelCore::FindNamedPort(
527     const std::string& name) const {
528     return impl->named_ports.find(name);
529 }
530 
IsValidNamedPort(NamedPortTable::const_iterator port) const531 bool KernelCore::IsValidNamedPort(NamedPortTable::const_iterator port) const {
532     return port != impl->named_ports.cend();
533 }
534 
CreateNewObjectID()535 u32 KernelCore::CreateNewObjectID() {
536     return impl->next_object_id++;
537 }
538 
CreateNewThreadID()539 u64 KernelCore::CreateNewThreadID() {
540     return impl->next_thread_id++;
541 }
542 
CreateNewKernelProcessID()543 u64 KernelCore::CreateNewKernelProcessID() {
544     return impl->next_kernel_process_id++;
545 }
546 
CreateNewUserProcessID()547 u64 KernelCore::CreateNewUserProcessID() {
548     return impl->next_user_process_id++;
549 }
550 
GlobalHandleTable()551 Kernel::HandleTable& KernelCore::GlobalHandleTable() {
552     return impl->global_handle_table;
553 }
554 
GlobalHandleTable() const555 const Kernel::HandleTable& KernelCore::GlobalHandleTable() const {
556     return impl->global_handle_table;
557 }
558 
RegisterCoreThread(std::size_t core_id)559 void KernelCore::RegisterCoreThread(std::size_t core_id) {
560     impl->RegisterCoreThread(core_id);
561 }
562 
RegisterHostThread()563 void KernelCore::RegisterHostThread() {
564     impl->RegisterHostThread();
565 }
566 
GetCurrentHostThreadID() const567 u32 KernelCore::GetCurrentHostThreadID() const {
568     return impl->GetCurrentHostThreadID();
569 }
570 
GetCurrentEmuThreadID() const571 Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
572     return impl->GetCurrentEmuThreadID();
573 }
574 
MemoryManager()575 Memory::MemoryManager& KernelCore::MemoryManager() {
576     return *impl->memory_manager;
577 }
578 
MemoryManager() const579 const Memory::MemoryManager& KernelCore::MemoryManager() const {
580     return *impl->memory_manager;
581 }
582 
GetUserSlabHeapPages()583 Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() {
584     return *impl->user_slab_heap_pages;
585 }
586 
GetUserSlabHeapPages() const587 const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const {
588     return *impl->user_slab_heap_pages;
589 }
590 
GetHidSharedMem()591 Kernel::SharedMemory& KernelCore::GetHidSharedMem() {
592     return *impl->hid_shared_mem;
593 }
594 
GetHidSharedMem() const595 const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const {
596     return *impl->hid_shared_mem;
597 }
598 
GetFontSharedMem()599 Kernel::SharedMemory& KernelCore::GetFontSharedMem() {
600     return *impl->font_shared_mem;
601 }
602 
GetFontSharedMem() const603 const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const {
604     return *impl->font_shared_mem;
605 }
606 
GetIrsSharedMem()607 Kernel::SharedMemory& KernelCore::GetIrsSharedMem() {
608     return *impl->irs_shared_mem;
609 }
610 
GetIrsSharedMem() const611 const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const {
612     return *impl->irs_shared_mem;
613 }
614 
GetTimeSharedMem()615 Kernel::SharedMemory& KernelCore::GetTimeSharedMem() {
616     return *impl->time_shared_mem;
617 }
618 
GetTimeSharedMem() const619 const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const {
620     return *impl->time_shared_mem;
621 }
622 
Suspend(bool in_suspention)623 void KernelCore::Suspend(bool in_suspention) {
624     const bool should_suspend = exception_exited || in_suspention;
625     {
626         SchedulerLock lock(*this);
627         ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep;
628         for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
629             impl->suspend_threads[i]->SetStatus(status);
630         }
631     }
632 }
633 
IsMulticore() const634 bool KernelCore::IsMulticore() const {
635     return impl->is_multicore;
636 }
637 
ExceptionalExit()638 void KernelCore::ExceptionalExit() {
639     exception_exited = true;
640     Suspend(true);
641 }
642 
EnterSVCProfile()643 void KernelCore::EnterSVCProfile() {
644     std::size_t core = impl->GetCurrentHostThreadID();
645     impl->svc_ticks[core] = MicroProfileEnter(MICROPROFILE_TOKEN(Kernel_SVC));
646 }
647 
ExitSVCProfile()648 void KernelCore::ExitSVCProfile() {
649     std::size_t core = impl->GetCurrentHostThreadID();
650     MicroProfileLeave(MICROPROFILE_TOKEN(Kernel_SVC), impl->svc_ticks[core]);
651 }
652 
653 } // namespace Kernel
654