diff options
Diffstat (limited to '')
-rw-r--r-- | src/core/hle/kernel/kernel.cpp | 230 |
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 |