summaryrefslogtreecommitdiffstats
path: root/src/core/hle/kernel/kernel.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
-rw-r--r--src/core/hle/kernel/kernel.cpp230
1 files changed, 128 insertions, 102 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index e8ece8164..780008b08 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -26,20 +26,19 @@
#include "core/device_memory.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/client_port.h"
-#include "core/hle/kernel/errors.h"
#include "core/hle/kernel/handle_table.h"
+#include "core/hle/kernel/k_memory_layout.h"
+#include "core/hle/kernel/k_memory_manager.h"
+#include "core/hle/kernel/k_resource_limit.h"
#include "core/hle/kernel/k_scheduler.h"
+#include "core/hle/kernel/k_shared_memory.h"
+#include "core/hle/kernel/k_slab_heap.h"
+#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
-#include "core/hle/kernel/memory/memory_layout.h"
-#include "core/hle/kernel/memory/memory_manager.h"
-#include "core/hle/kernel/memory/slab_heap.h"
#include "core/hle/kernel/physical_core.h"
#include "core/hle/kernel/process.h"
-#include "core/hle/kernel/resource_limit.h"
#include "core/hle/kernel/service_thread.h"
-#include "core/hle/kernel/shared_memory.h"
-#include "core/hle/kernel/synchronization.h"
-#include "core/hle/kernel/thread.h"
+#include "core/hle/kernel/svc_results.h"
#include "core/hle/kernel/time_manager.h"
#include "core/hle/lock.h"
#include "core/hle/result.h"
@@ -51,22 +50,23 @@ namespace Kernel {
struct KernelCore::Impl {
explicit Impl(Core::System& system, KernelCore& kernel)
- : synchronization{system}, time_manager{system}, global_handle_table{kernel}, system{
- system} {}
+ : time_manager{system}, global_handle_table{kernel}, system{system} {}
void SetMulticore(bool is_multicore) {
this->is_multicore = is_multicore;
}
void Initialize(KernelCore& kernel) {
+ global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
+
RegisterHostThread();
- global_scheduler_context = std::make_unique<Kernel::GlobalSchedulerContext>(kernel);
service_thread_manager =
std::make_unique<Common::ThreadWorker>(1, "yuzu:ServiceThreadManager");
+ is_phantom_mode_for_singlecore = false;
InitializePhysicalCores();
- InitializeSystemResourceLimit(kernel);
+ InitializeSystemResourceLimit(kernel, system);
InitializeMemoryLayout();
InitializePreemption(kernel);
InitializeSchedulers();
@@ -101,8 +101,6 @@ struct KernelCore::Impl {
current_process = nullptr;
- system_resource_limit = nullptr;
-
global_handle_table.Clear();
preemption_event = nullptr;
@@ -111,6 +109,13 @@ struct KernelCore::Impl {
exclusive_monitor.reset();
+ hid_shared_mem = nullptr;
+ font_shared_mem = nullptr;
+ irs_shared_mem = nullptr;
+ time_shared_mem = nullptr;
+
+ system_resource_limit = nullptr;
+
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
}
@@ -118,34 +123,40 @@ struct KernelCore::Impl {
void InitializePhysicalCores() {
exclusive_monitor =
Core::MakeExclusiveMonitor(system.Memory(), Core::Hardware::NUM_CPU_CORES);
- for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
schedulers[i] = std::make_unique<Kernel::KScheduler>(system, i);
cores.emplace_back(i, system, *schedulers[i], interrupts);
}
}
void InitializeSchedulers() {
- for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
+ for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
cores[i].Scheduler().Initialize();
}
}
// Creates the default system resource limit
- void InitializeSystemResourceLimit(KernelCore& kernel) {
- system_resource_limit = ResourceLimit::Create(kernel);
+ void InitializeSystemResourceLimit(KernelCore& kernel, Core::System& system) {
+ system_resource_limit = std::make_shared<KResourceLimit>(kernel, system);
// If setting the default system values fails, then something seriously wrong has occurred.
- ASSERT(system_resource_limit->SetLimitValue(ResourceType::PhysicalMemory, 0x100000000)
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::PhysicalMemory, 0x100000000)
+ .IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Threads, 800).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Events, 700).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::TransferMemory, 200)
.IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(ResourceType::Threads, 800).IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(ResourceType::Events, 700).IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(ResourceType::TransferMemory, 200).IsSuccess());
- ASSERT(system_resource_limit->SetLimitValue(ResourceType::Sessions, 900).IsSuccess());
+ ASSERT(system_resource_limit->SetLimitValue(LimitableResource::Sessions, 933).IsSuccess());
- if (!system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0) ||
- !system_resource_limit->Reserve(ResourceType::PhysicalMemory, 0x60000)) {
+ // Derived from recent software updates. The kernel reserves 27MB
+ constexpr u64 kernel_size{0x1b00000};
+ if (!system_resource_limit->Reserve(LimitableResource::PhysicalMemory, kernel_size)) {
UNREACHABLE();
}
+ // Reserve secure applet memory, introduced in firmware 5.0.0
+ constexpr u64 secure_applet_memory_size{0x400000};
+ ASSERT(system_resource_limit->Reserve(LimitableResource::PhysicalMemory,
+ secure_applet_memory_size));
}
void InitializePreemption(KernelCore& kernel) {
@@ -170,11 +181,9 @@ struct KernelCore::Impl {
std::string name = "Suspend Thread Id:" + std::to_string(i);
std::function<void(void*)> init_func = Core::CpuManager::GetSuspendThreadStartFunc();
void* init_func_parameter = system.GetCpuManager().GetStartFuncParamater();
- const auto type =
- static_cast<ThreadType>(THREADTYPE_KERNEL | THREADTYPE_HLE | THREADTYPE_SUSPEND);
- auto thread_res =
- Thread::Create(system, type, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
- nullptr, std::move(init_func), init_func_parameter);
+ auto thread_res = KThread::CreateThread(
+ system, ThreadType::HighPriority, std::move(name), 0, 0, 0, static_cast<u32>(i), 0,
+ nullptr, std::move(init_func), init_func_parameter);
suspend_threads[i] = std::move(thread_res).Unwrap();
}
@@ -209,6 +218,16 @@ struct KernelCore::Impl {
return host_thread_id;
}
+ // Gets the dummy KThread for the caller, allocating a new one if this is the first time
+ KThread* GetHostDummyThread() {
+ const thread_local auto thread =
+ KThread::CreateThread(
+ system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0,
+ KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr)
+ .Unwrap();
+ return thread.get();
+ }
+
/// Registers a CPU core thread by allocating a host thread ID for it
void RegisterCoreThread(std::size_t core_id) {
ASSERT(core_id < Core::Hardware::NUM_CPU_CORES);
@@ -221,6 +240,7 @@ struct KernelCore::Impl {
/// Registers a new host thread by allocating a host thread ID for it
void RegisterHostThread() {
[[maybe_unused]] const auto this_id = GetHostThreadId();
+ [[maybe_unused]] const auto dummy_thread = GetHostDummyThread();
}
[[nodiscard]] u32 GetCurrentHostThreadID() {
@@ -231,25 +251,26 @@ struct KernelCore::Impl {
return this_id;
}
- [[nodiscard]] Core::EmuThreadHandle GetCurrentEmuThreadID() {
- Core::EmuThreadHandle result = Core::EmuThreadHandle::InvalidHandle();
- result.host_handle = GetCurrentHostThreadID();
- if (result.host_handle >= Core::Hardware::NUM_CPU_CORES) {
- return result;
- }
- const Kernel::KScheduler& sched = cores[result.host_handle].Scheduler();
- const Kernel::Thread* current = sched.GetCurrentThread();
- if (current != nullptr && !current->IsPhantomMode()) {
- result.guest_handle = current->GetGlobalHandle();
- } else {
- result.guest_handle = InvalidHandle;
+ bool IsPhantomModeForSingleCore() const {
+ return is_phantom_mode_for_singlecore;
+ }
+
+ void SetIsPhantomModeForSingleCore(bool value) {
+ ASSERT(!is_multicore);
+ is_phantom_mode_for_singlecore = value;
+ }
+
+ KThread* GetCurrentEmuThread() {
+ const auto thread_id = GetCurrentHostThreadID();
+ if (thread_id >= Core::Hardware::NUM_CPU_CORES) {
+ return GetHostDummyThread();
}
- return result;
+ return schedulers[thread_id]->GetCurrentThread();
}
void InitializeMemoryLayout() {
// Initialize memory layout
- constexpr Memory::MemoryLayout layout{Memory::MemoryLayout::GetDefaultLayout()};
+ constexpr KMemoryLayout layout{KMemoryLayout::GetDefaultLayout()};
constexpr std::size_t hid_size{0x40000};
constexpr std::size_t font_size{0x1100000};
constexpr std::size_t irs_size{0x8000};
@@ -260,39 +281,42 @@ struct KernelCore::Impl {
constexpr PAddr time_addr{layout.System().StartAddress() + hid_size + font_size + irs_size};
// Initialize memory manager
- memory_manager = std::make_unique<Memory::MemoryManager>();
- memory_manager->InitializeManager(Memory::MemoryManager::Pool::Application,
+ memory_manager = std::make_unique<KMemoryManager>();
+ memory_manager->InitializeManager(KMemoryManager::Pool::Application,
layout.Application().StartAddress(),
layout.Application().EndAddress());
- memory_manager->InitializeManager(Memory::MemoryManager::Pool::Applet,
+ memory_manager->InitializeManager(KMemoryManager::Pool::Applet,
layout.Applet().StartAddress(),
layout.Applet().EndAddress());
- memory_manager->InitializeManager(Memory::MemoryManager::Pool::System,
+ memory_manager->InitializeManager(KMemoryManager::Pool::System,
layout.System().StartAddress(),
layout.System().EndAddress());
- hid_shared_mem = Kernel::SharedMemory::Create(
- system.Kernel(), system.DeviceMemory(), nullptr,
- {hid_addr, hid_size / Memory::PageSize}, Memory::MemoryPermission::None,
- Memory::MemoryPermission::Read, hid_addr, hid_size, "HID:SharedMemory");
- font_shared_mem = Kernel::SharedMemory::Create(
- system.Kernel(), system.DeviceMemory(), nullptr,
- {font_pa, font_size / Memory::PageSize}, Memory::MemoryPermission::None,
- Memory::MemoryPermission::Read, font_pa, font_size, "Font:SharedMemory");
- irs_shared_mem = Kernel::SharedMemory::Create(
- system.Kernel(), system.DeviceMemory(), nullptr,
- {irs_addr, irs_size / Memory::PageSize}, Memory::MemoryPermission::None,
- Memory::MemoryPermission::Read, irs_addr, irs_size, "IRS:SharedMemory");
- time_shared_mem = Kernel::SharedMemory::Create(
- system.Kernel(), system.DeviceMemory(), nullptr,
- {time_addr, time_size / Memory::PageSize}, Memory::MemoryPermission::None,
- Memory::MemoryPermission::Read, time_addr, time_size, "Time:SharedMemory");
+ hid_shared_mem = Kernel::KSharedMemory::Create(
+ system.Kernel(), system.DeviceMemory(), nullptr, {hid_addr, hid_size / PageSize},
+ KMemoryPermission::None, KMemoryPermission::Read, hid_addr, hid_size,
+ "HID:SharedMemory");
+ font_shared_mem = Kernel::KSharedMemory::Create(
+ system.Kernel(), system.DeviceMemory(), nullptr, {font_pa, font_size / PageSize},
+ KMemoryPermission::None, KMemoryPermission::Read, font_pa, font_size,
+ "Font:SharedMemory");
+ irs_shared_mem = Kernel::KSharedMemory::Create(
+ system.Kernel(), system.DeviceMemory(), nullptr, {irs_addr, irs_size / PageSize},
+ KMemoryPermission::None, KMemoryPermission::Read, irs_addr, irs_size,
+ "IRS:SharedMemory");
+ time_shared_mem = Kernel::KSharedMemory::Create(
+ system.Kernel(), system.DeviceMemory(), nullptr, {time_addr, time_size / PageSize},
+ KMemoryPermission::None, KMemoryPermission::Read, time_addr, time_size,
+ "Time:SharedMemory");
// Allocate slab heaps
- user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::Page>>();
+ user_slab_heap_pages = std::make_unique<KSlabHeap<Page>>();
+ constexpr u64 user_slab_heap_size{0x1ef000};
+ // Reserve slab heaps
+ ASSERT(
+ system_resource_limit->Reserve(LimitableResource::PhysicalMemory, user_slab_heap_size));
// Initialize slab heaps
- constexpr u64 user_slab_heap_size{0x3de000};
user_slab_heap_pages->Initialize(
system.DeviceMemory().GetPointer(Core::DramMemoryMap::SlabHeapBase),
user_slab_heap_size);
@@ -307,10 +331,9 @@ struct KernelCore::Impl {
std::vector<std::shared_ptr<Process>> process_list;
Process* current_process = nullptr;
std::unique_ptr<Kernel::GlobalSchedulerContext> global_scheduler_context;
- Kernel::Synchronization synchronization;
Kernel::TimeManager time_manager;
- std::shared_ptr<ResourceLimit> system_resource_limit;
+ std::shared_ptr<KResourceLimit> system_resource_limit;
std::shared_ptr<Core::Timing::EventType> preemption_event;
@@ -329,14 +352,14 @@ struct KernelCore::Impl {
std::atomic<u32> next_host_thread_id{Core::Hardware::NUM_CPU_CORES};
// Kernel memory management
- std::unique_ptr<Memory::MemoryManager> memory_manager;
- std::unique_ptr<Memory::SlabHeap<Memory::Page>> user_slab_heap_pages;
+ std::unique_ptr<KMemoryManager> memory_manager;
+ std::unique_ptr<KSlabHeap<Page>> user_slab_heap_pages;
// Shared memory for services
- std::shared_ptr<Kernel::SharedMemory> hid_shared_mem;
- std::shared_ptr<Kernel::SharedMemory> font_shared_mem;
- std::shared_ptr<Kernel::SharedMemory> irs_shared_mem;
- std::shared_ptr<Kernel::SharedMemory> time_shared_mem;
+ std::shared_ptr<Kernel::KSharedMemory> hid_shared_mem;
+ std::shared_ptr<Kernel::KSharedMemory> font_shared_mem;
+ std::shared_ptr<Kernel::KSharedMemory> irs_shared_mem;
+ std::shared_ptr<Kernel::KSharedMemory> time_shared_mem;
// Threads used for services
std::unordered_set<std::shared_ptr<Kernel::ServiceThread>> service_threads;
@@ -345,11 +368,12 @@ struct KernelCore::Impl {
// the release of itself
std::unique_ptr<Common::ThreadWorker> service_thread_manager;
- std::array<std::shared_ptr<Thread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
+ std::array<std::shared_ptr<KThread>, Core::Hardware::NUM_CPU_CORES> suspend_threads{};
std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES> interrupts{};
std::array<std::unique_ptr<Kernel::KScheduler>, Core::Hardware::NUM_CPU_CORES> schedulers{};
bool is_multicore{};
+ bool is_phantom_mode_for_singlecore{};
u32 single_core_thread_id{};
std::array<u64, Core::Hardware::NUM_CPU_CORES> svc_ticks{};
@@ -379,12 +403,12 @@ void KernelCore::Shutdown() {
impl->Shutdown();
}
-std::shared_ptr<ResourceLimit> KernelCore::GetSystemResourceLimit() const {
+std::shared_ptr<KResourceLimit> KernelCore::GetSystemResourceLimit() const {
return impl->system_resource_limit;
}
-std::shared_ptr<Thread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
- return impl->global_handle_table.Get<Thread>(handle);
+std::shared_ptr<KThread> KernelCore::RetrieveThreadFromGlobalHandleTable(Handle handle) const {
+ return impl->global_handle_table.Get<KThread>(handle);
}
void KernelCore::AppendNewProcess(std::shared_ptr<Process> process) {
@@ -461,14 +485,6 @@ const std::array<Core::CPUInterruptHandler, Core::Hardware::NUM_CPU_CORES>& Kern
return impl->interrupts;
}
-Kernel::Synchronization& KernelCore::Synchronization() {
- return impl->synchronization;
-}
-
-const Kernel::Synchronization& KernelCore::Synchronization() const {
- return impl->synchronization;
-}
-
Kernel::TimeManager& KernelCore::TimeManager() {
return impl->time_manager;
}
@@ -557,55 +573,55 @@ u32 KernelCore::GetCurrentHostThreadID() const {
return impl->GetCurrentHostThreadID();
}
-Core::EmuThreadHandle KernelCore::GetCurrentEmuThreadID() const {
- return impl->GetCurrentEmuThreadID();
+KThread* KernelCore::GetCurrentEmuThread() const {
+ return impl->GetCurrentEmuThread();
}
-Memory::MemoryManager& KernelCore::MemoryManager() {
+KMemoryManager& KernelCore::MemoryManager() {
return *impl->memory_manager;
}
-const Memory::MemoryManager& KernelCore::MemoryManager() const {
+const KMemoryManager& KernelCore::MemoryManager() const {
return *impl->memory_manager;
}
-Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() {
+KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() {
return *impl->user_slab_heap_pages;
}
-const Memory::SlabHeap<Memory::Page>& KernelCore::GetUserSlabHeapPages() const {
+const KSlabHeap<Page>& KernelCore::GetUserSlabHeapPages() const {
return *impl->user_slab_heap_pages;
}
-Kernel::SharedMemory& KernelCore::GetHidSharedMem() {
+Kernel::KSharedMemory& KernelCore::GetHidSharedMem() {
return *impl->hid_shared_mem;
}
-const Kernel::SharedMemory& KernelCore::GetHidSharedMem() const {
+const Kernel::KSharedMemory& KernelCore::GetHidSharedMem() const {
return *impl->hid_shared_mem;
}
-Kernel::SharedMemory& KernelCore::GetFontSharedMem() {
+Kernel::KSharedMemory& KernelCore::GetFontSharedMem() {
return *impl->font_shared_mem;
}
-const Kernel::SharedMemory& KernelCore::GetFontSharedMem() const {
+const Kernel::KSharedMemory& KernelCore::GetFontSharedMem() const {
return *impl->font_shared_mem;
}
-Kernel::SharedMemory& KernelCore::GetIrsSharedMem() {
+Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() {
return *impl->irs_shared_mem;
}
-const Kernel::SharedMemory& KernelCore::GetIrsSharedMem() const {
+const Kernel::KSharedMemory& KernelCore::GetIrsSharedMem() const {
return *impl->irs_shared_mem;
}
-Kernel::SharedMemory& KernelCore::GetTimeSharedMem() {
+Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() {
return *impl->time_shared_mem;
}
-const Kernel::SharedMemory& KernelCore::GetTimeSharedMem() const {
+const Kernel::KSharedMemory& KernelCore::GetTimeSharedMem() const {
return *impl->time_shared_mem;
}
@@ -613,9 +629,11 @@ void KernelCore::Suspend(bool in_suspention) {
const bool should_suspend = exception_exited || in_suspention;
{
KScopedSchedulerLock lock(*this);
- ThreadStatus status = should_suspend ? ThreadStatus::Ready : ThreadStatus::WaitSleep;
+ const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting;
for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
- impl->suspend_threads[i]->SetStatus(status);
+ impl->suspend_threads[i]->SetState(state);
+ impl->suspend_threads[i]->SetWaitReasonForDebugging(
+ ThreadWaitReasonForDebugging::Suspended);
}
}
}
@@ -654,4 +672,12 @@ void KernelCore::ReleaseServiceThread(std::weak_ptr<Kernel::ServiceThread> servi
});
}
+bool KernelCore::IsPhantomModeForSingleCore() const {
+ return impl->IsPhantomModeForSingleCore();
+}
+
+void KernelCore::SetIsPhantomModeForSingleCore(bool value) {
+ impl->SetIsPhantomModeForSingleCore(value);
+}
+
} // namespace Kernel