diff options
Diffstat (limited to 'src/core/hle/kernel/kernel.cpp')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 134 |
1 files changed, 78 insertions, 56 deletions
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index e8ece8164..b6e6f115e 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_resource_limit.h" #include "core/hle/kernel/k_scheduler.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(); @@ -118,34 +118,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 +176,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::Create(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 +213,17 @@ 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::Create( + system, ThreadType::Main, fmt::format("DummyThread:{}", GetHostThreadId()), 0, + KThread::DefaultThreadPriority, 0, static_cast<u32>(3), 0, nullptr, + []([[maybe_unused]] void* arg) { UNREACHABLE(); }, 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 +236,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,20 +247,21 @@ 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() { @@ -291,8 +308,11 @@ struct KernelCore::Impl { // Allocate slab heaps user_slab_heap_pages = std::make_unique<Memory::SlabHeap<Memory::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 +327,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; @@ -345,11 +364,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 +399,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 +481,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,8 +569,8 @@ 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() { @@ -613,9 +625,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 +668,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 |
