diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_dpc_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_dpc_manager.hpp index 2b720140f..c19d7d07b 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_dpc_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_dpc_manager.hpp @@ -39,6 +39,7 @@ namespace ams::kern { } static NOINLINE void HandleDpc(); + static void Sync(); }; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp index 5892534ec..43bf7977a 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp @@ -34,6 +34,14 @@ namespace ams::kern::KDumpObject { void DumpMemory(); void DumpMemory(u64 process_id); + void DumpKernelPageTable(); + void DumpPageTable(); + void DumpPageTable(u64 process_id); + + void DumpKernelCpuUtilization(); + void DumpCpuUtilization(); + void DumpCpuUtilization(u64 process_id); + void DumpProcess(); void DumpProcess(u64 process_id); diff --git a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table_impl.cpp b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table_impl.cpp index cd5ddb47a..49e857a2a 100644 --- a/libraries/libmesosphere/source/arch/arm64/kern_k_page_table_impl.cpp +++ b/libraries/libmesosphere/source/arch/arm64/kern_k_page_table_impl.cpp @@ -312,9 +312,6 @@ namespace ams::kern::arch::arm64 { const uintptr_t end = start + size; const uintptr_t last = end - 1; - MESOSPHERE_LOG("==== PAGE TABLE DUMP START (%012lx - %012lx) ====\n", start, last); - ON_SCOPE_EXIT { MESOSPHERE_LOG("==== PAGE TABLE DUMP END ====\n"); }; - /* Define tracking variables. */ bool unmapped = false; uintptr_t unmapped_start = 0; @@ -344,11 +341,27 @@ namespace ams::kern::arch::arm64 { cur = util::AlignDown(cur, L1BlockSize); if (unmapped) { unmapped = false; - MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1); + MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1); } /* Print. */ - MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast(l1_entry)); + MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=1G Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur, + *reinterpret_cast(l1_entry), + reinterpret_cast(GetInteger(l1_entry->GetBlock())), + l1_entry->IsMapped(), + l1_entry->IsUserExecuteNever(), + l1_entry->IsPrivilegedExecuteNever(), + l1_entry->IsContiguous(), + !l1_entry->IsGlobal(), + static_cast(l1_entry->GetAccessFlag()), + static_cast(l1_entry->GetShareable()), + l1_entry->IsReadOnly(), + l1_entry->IsUserAccessible(), + l1_entry->IsNonSecure(), + static_cast(l1_entry->GetPageAttribute()), + l1_entry->IsHeadMergeDisabled(), + l1_entry->IsHeadAndBodyMergeDisabled(), + l1_entry->IsTailMergeDisabled()); /* Advance. */ cur += L1BlockSize; @@ -373,11 +386,27 @@ namespace ams::kern::arch::arm64 { cur = util::AlignDown(cur, L2BlockSize); if (unmapped) { unmapped = false; - MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1); + MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1); } /* Print. */ - MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast(l2_entry)); + MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=2M Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur, + *reinterpret_cast(l2_entry), + reinterpret_cast(GetInteger(l2_entry->GetBlock())), + l2_entry->IsMapped(), + l2_entry->IsUserExecuteNever(), + l2_entry->IsPrivilegedExecuteNever(), + l2_entry->IsContiguous(), + !l2_entry->IsGlobal(), + static_cast(l2_entry->GetAccessFlag()), + static_cast(l2_entry->GetShareable()), + l2_entry->IsReadOnly(), + l2_entry->IsUserAccessible(), + l2_entry->IsNonSecure(), + static_cast(l2_entry->GetPageAttribute()), + l2_entry->IsHeadMergeDisabled(), + l2_entry->IsHeadAndBodyMergeDisabled(), + l2_entry->IsTailMergeDisabled()); /* Advance. */ cur += L2BlockSize; @@ -402,11 +431,27 @@ namespace ams::kern::arch::arm64 { cur = util::AlignDown(cur, L3BlockSize); if (unmapped) { unmapped = false; - MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, cur - 1); + MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, cur - 1); } /* Print. */ - MESOSPHERE_LOG("%012lx: %016lx\n", cur, *reinterpret_cast(l3_entry)); + MESOSPHERE_RELEASE_LOG("%016lx: %016lx PA=%p SZ=4K Mapped=%d UXN=%d PXN=%d Cont=%d nG=%d AF=%d SH=%x RO=%d UA=%d NS=%d AttrIndx=%d NoMerge=%d,%d,%d\n", cur, + *reinterpret_cast(l3_entry), + reinterpret_cast(GetInteger(l3_entry->GetBlock())), + l3_entry->IsMapped(), + l3_entry->IsUserExecuteNever(), + l3_entry->IsPrivilegedExecuteNever(), + l3_entry->IsContiguous(), + !l3_entry->IsGlobal(), + static_cast(l3_entry->GetAccessFlag()), + static_cast(l3_entry->GetShareable()), + l3_entry->IsReadOnly(), + l3_entry->IsUserAccessible(), + l3_entry->IsNonSecure(), + static_cast(l3_entry->GetPageAttribute()), + l3_entry->IsHeadMergeDisabled(), + l3_entry->IsHeadAndBodyMergeDisabled(), + l3_entry->IsTailMergeDisabled()); /* Advance. */ cur += L3BlockSize; @@ -427,7 +472,7 @@ namespace ams::kern::arch::arm64 { /* Print the last unmapped range if necessary. */ if (unmapped) { - MESOSPHERE_LOG("%012lx - %012lx: ---\n", unmapped_start, last); + MESOSPHERE_RELEASE_LOG("%016lx - %016lx: not mapped\n", unmapped_start, last); } } diff --git a/libraries/libmesosphere/source/kern_k_dpc_manager.cpp b/libraries/libmesosphere/source/kern_k_dpc_manager.cpp index 9fbcaf0bf..62ae50a6e 100644 --- a/libraries/libmesosphere/source/kern_k_dpc_manager.cpp +++ b/libraries/libmesosphere/source/kern_k_dpc_manager.cpp @@ -21,10 +21,11 @@ namespace ams::kern { class KDpcTask { private: - static inline KLightLock s_lock; - static inline KLightConditionVariable s_cond_var; - static inline u64 s_core_mask; - static inline KDpcTask *s_task; + static constinit inline KLightLock s_req_lock; + static constinit inline KLightLock s_lock; + static constinit inline KLightConditionVariable s_cond_var; + static constinit inline u64 s_core_mask; + static constinit inline KDpcTask *s_task; private: static bool HasRequest(s32 core_id) { return (s_core_mask & (1ull << core_id)) != 0; @@ -40,12 +41,35 @@ namespace ams::kern { public: virtual void DoTask() { /* ... */ } + static void Request(KDpcTask *task) { + KScopedLightLock rlk(s_req_lock); + + /* Acquire the requested task. */ + MESOSPHERE_ABORT_UNLESS(s_task == nullptr); + s_task = task; + { + KScopedLightLock lk(s_lock); + MESOSPHERE_ABORT_UNLESS(s_core_mask == 0); + + for (auto core = 0; core < static_cast(cpu::NumCores); ++core) { + SetRequest(core); + } + + s_cond_var.Broadcast(); + + while (s_core_mask != 0) { + s_cond_var.Wait(std::addressof(s_lock), -1ll); + } + } + s_task = nullptr; + } + static void WaitForRequest() { /* Wait for a request to come in. */ const auto core_id = GetCurrentCoreId(); KScopedLightLock lk(s_lock); while (!HasRequest(core_id)) { - s_cond_var.Wait(&s_lock, -1ll); + s_cond_var.Wait(std::addressof(s_lock), -1ll); } } @@ -54,7 +78,7 @@ namespace ams::kern { const auto core_id = GetCurrentCoreId(); KScopedLightLock lk(s_lock); while (!HasRequest(core_id)) { - s_cond_var.Wait(&s_lock, timeout); + s_cond_var.Wait(std::addressof(s_lock), timeout); if (KHardwareTimer::GetTick() >= timeout) { return false; } @@ -147,6 +171,9 @@ namespace ams::kern { } void KDpcManager::HandleDpc() { + MESOSPHERE_ASSERT(!KInterruptManager::AreInterruptsEnabled()); + MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread()); + /* The only deferred procedure supported by Horizon is thread termination. */ /* Check if we need to terminate the current thread. */ KThread *cur_thread = GetCurrentThreadPointer(); @@ -156,4 +183,11 @@ namespace ams::kern { } } + void KDpcManager::Sync() { + MESOSPHERE_ASSERT(!KScheduler::IsSchedulerLockedByCurrentThread()); + + KDpcTask dummy_task; + KDpcTask::Request(std::addressof(dummy_task)); + } + } diff --git a/libraries/libmesosphere/source/kern_k_dump_object.cpp b/libraries/libmesosphere/source/kern_k_dump_object.cpp index 9fa4484a2..628d3e869 100644 --- a/libraries/libmesosphere/source/kern_k_dump_object.cpp +++ b/libraries/libmesosphere/source/kern_k_dump_object.cpp @@ -166,6 +166,12 @@ namespace ams::kern::KDumpObject { MESOSPHERE_RELEASE_LOG("\n\n"); } + void DumpPageTable(KProcess *process) { + MESOSPHERE_RELEASE_LOG("Process ID=%3lu (%s)\n", process->GetId(), process->GetName()); + process->GetPageTable().DumpPageTable(); + MESOSPHERE_RELEASE_LOG("\n\n"); + } + void DumpProcess(KProcess *process) { MESOSPHERE_RELEASE_LOG("Process ID=%3lu index=%3zu State=%d (%s)\n", process->GetId(), process->GetSlabIndex(), process->GetState(), process->GetName()); } @@ -600,6 +606,60 @@ namespace ams::kern::KDumpObject { MESOSPHERE_RELEASE_LOG("\n"); } + void DumpKernelPageTable() { + MESOSPHERE_RELEASE_LOG("Dump Kernel PageTable\n"); + + { + Kernel::GetKernelPageTable().DumpPageTable(); + } + + MESOSPHERE_RELEASE_LOG("\n"); + } + + void DumpPageTable() { + MESOSPHERE_RELEASE_LOG("Dump Process\n"); + + { + /* Lock the list. */ + KProcess::ListAccessor accessor; + const auto end = accessor.end(); + + /* Dump each process. */ + for (auto it = accessor.begin(); it != end; ++it) { + DumpPageTable(static_cast(std::addressof(*it))); + } + } + + MESOSPHERE_RELEASE_LOG("\n"); + } + + void DumpPageTable(u64 process_id) { + MESOSPHERE_RELEASE_LOG("Dump PageTable\n"); + + { + /* Find and dump the target process. */ + if (KProcess *process = KProcess::GetProcessFromId(process_id); process != nullptr) { + ON_SCOPE_EXIT { process->Close(); }; + DumpPageTable(process); + } + } + + MESOSPHERE_RELEASE_LOG("\n"); + } + + void DumpKernelCpuUtilization() { + /* TODO */ + } + + void DumpCpuUtilization() { + /* TODO */ + } + + void DumpCpuUtilization(u64 process_id) { + /* TODO */ + MESOSPHERE_UNUSED(process_id); + } + void DumpProcess(u64 process_id) { MESOSPHERE_RELEASE_LOG("Dump Process\n"); diff --git a/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp index a94b35894..125e24642 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp @@ -60,6 +60,31 @@ namespace ams::kern::svc { KDumpObject::DumpMemory(arg0); } break; + case ams::svc::KernelDebugType_PageTable: + if (arg0 == static_cast(-2)) { + KDumpObject::DumpKernelPageTable(); + } else if (arg0 == static_cast(-1)) { + KDumpObject::DumpPageTable(); + } else { + KDumpObject::DumpPageTable(arg0); + } + break; + case ams::svc::KernelDebugType_CpuUtilization: + { + const auto old_prio = GetCurrentThread().GetBasePriority(); + GetCurrentThread().SetBasePriority(3); + + if (arg0 == static_cast(-2)) { + KDumpObject::DumpKernelCpuUtilization(); + } else if (arg0 == static_cast(-1)) { + KDumpObject::DumpCpuUtilization(); + } else { + KDumpObject::DumpCpuUtilization(arg0); + } + + GetCurrentThread().SetBasePriority(old_prio); + } + break; case ams::svc::KernelDebugType_Process: if (arg0 == static_cast(-1)) { KDumpObject::DumpProcess();