diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table_impl.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table_impl.hpp index 95c94dced..b82db110d 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table_impl.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_page_table_impl.hpp @@ -112,6 +112,7 @@ namespace ams::kern::arch::arm64 { L1PageTableEntry *Finalize(); void Dump(uintptr_t start, size_t size) const; + size_t CountPageTables() const; bool BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const; bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const; diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp index 48a9e8081..33c361c64 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_process_page_table.hpp @@ -232,14 +232,18 @@ namespace ams::kern::arch::arm64 { return this->page_table.UnmapPhysicalMemoryUnsafe(address, size); } - void DumpTable() const { - return this->page_table.DumpTable(); - } - void DumpMemoryBlocks() const { return this->page_table.DumpMemoryBlocks(); } + void DumpPageTable() const { + return this->page_table.DumpPageTable(); + } + + size_t CountPageTables() const { + return this->page_table.CountPageTables(); + } + bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const { return this->page_table.GetPhysicalAddress(out, address); } diff --git a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_supervisor_page_table.hpp b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_supervisor_page_table.hpp index 8e795aa7c..3854accf4 100644 --- a/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_supervisor_page_table.hpp +++ b/libraries/libmesosphere/include/mesosphere/arch/arm64/kern_k_supervisor_page_table.hpp @@ -62,6 +62,10 @@ namespace ams::kern::arch::arm64 { } constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; } + + size_t CountPageTables() const { + return this->page_table.CountPageTables(); + } }; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp index 376d22518..ade036e75 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_dump_object.hpp @@ -25,6 +25,8 @@ namespace ams::kern::KDumpObject { void DumpThreadCallStack(); void DumpThreadCallStack(u64 thread_id); + void DumpKernelObject(); + void DumpHandle(); void DumpHandle(u64 process_id); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp index 86d133442..30c740eab 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp @@ -90,6 +90,8 @@ namespace ams::kern { size_t GetFreeSize() const { return this->heap.GetFreeSize(); } + void DumpFreeList() const { return this->heap.DumpFreeList(); } + constexpr size_t GetPageOffset(KVirtualAddress address) const { return this->heap.GetPageOffset(address); } constexpr size_t GetPageOffsetToEnd(KVirtualAddress address) const { return this->heap.GetPageOffsetToEnd(address); } @@ -247,12 +249,15 @@ namespace ams::kern { size_t GetFreeSize() { size_t total = 0; for (size_t i = 0; i < this->num_managers; i++) { + KScopedLightLock lk(this->pool_locks[this->managers[i].GetPool()]); total += this->managers[i].GetFreeSize(); } return total; } size_t GetFreeSize(Pool pool) { + KScopedLightLock lk(this->pool_locks[pool]); + constexpr Direction GetSizeDirection = Direction_FromFront; size_t total = 0; for (auto *manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr; manager = this->GetNextManager(manager, GetSizeDirection)) { @@ -260,6 +265,15 @@ namespace ams::kern { } return total; } + + void DumpFreeList(Pool pool) { + KScopedLightLock lk(this->pool_locks[pool]); + + constexpr Direction DumpDirection = Direction_FromFront; + for (auto *manager = this->GetFirstManager(pool, DumpDirection); manager != nullptr; manager = this->GetNextManager(manager, DumpDirection)) { + manager->DumpFreeList(); + } + } public: static size_t CalculateManagementOverheadSize(size_t region_size) { return Impl::CalculateManagementOverheadSize(region_size); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp index 3f11d6e68..35ac503bd 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp @@ -147,6 +147,7 @@ namespace ams::kern { } size_t GetFreeSize() const { return this->GetNumFreePages() * PageSize; } + void DumpFreeList() const; void UpdateUsedSize() { this->used_size = this->heap_size - (this->GetNumFreePages() * PageSize); diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp index f22d476c8..18e42d97d 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_table_base.hpp @@ -382,9 +382,9 @@ namespace ams::kern { Result MapPhysicalMemoryUnsafe(KProcessAddress address, size_t size); Result UnmapPhysicalMemoryUnsafe(KProcessAddress address, size_t size); - void DumpTable() const { - KScopedLightLock lk(this->general_lock); - this->GetImpl().Dump(GetInteger(this->address_space_start), this->address_space_end - this->address_space_start); + void DumpMemoryBlocksLocked() const { + MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); + this->memory_block_manager.DumpBlocks(); } void DumpMemoryBlocks() const { @@ -392,9 +392,14 @@ namespace ams::kern { this->DumpMemoryBlocksLocked(); } - void DumpMemoryBlocksLocked() const { - MESOSPHERE_ASSERT(this->IsLockedByCurrentThread()); - this->memory_block_manager.DumpBlocks(); + void DumpPageTable() const { + KScopedLightLock lk(this->general_lock); + this->GetImpl().Dump(GetInteger(this->address_space_start), this->address_space_end - this->address_space_start); + } + + size_t CountPageTables() const { + KScopedLightLock lk(this->general_lock); + return this->GetImpl().CountPageTables(); } public: KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp index accb4fe7b..2066325fc 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_process.hpp @@ -305,6 +305,11 @@ namespace ams::kern { } } + const KDynamicPageManager &GetDynamicPageManager() const { return this->dynamic_page_manager; } + const KMemoryBlockSlabManager &GetMemoryBlockSlabManager() const { return this->memory_block_slab_manager; } + const KBlockInfoManager &GetBlockInfoManager() const { return this->block_info_manager; } + const KPageTableManager &GetPageTableManager() const { return this->page_table_manager; } + constexpr KThread *GetRunningThread(s32 core) const { return this->running_threads[core]; } constexpr u64 GetRunningThreadIdleCount(s32 core) const { return this->running_thread_idle_counts[core]; } diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp index 494777700..0dfc84814 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_slab_heap.hpp @@ -140,7 +140,21 @@ namespace ams::kern { void *obj = this->GetImpl()->Allocate(); - /* TODO: under some debug define, track the peak for statistics, as N does? */ + /* Track the allocated peak. */ + #if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) + if (AMS_LIKELY(obj != nullptr)) { + static_assert(std::atomic_ref::is_always_lock_free); + std::atomic_ref peak_ref(this->peak); + + const uintptr_t alloc_peak = reinterpret_cast(obj) + this->GetObjectSize(); + uintptr_t cur_peak = this->peak; + do { + if (alloc_peak <= cur_peak) { + break; + } + } while (!peak_ref.compare_exchange_strong(cur_peak, alloc_peak)); + } + #endif return obj; } @@ -165,6 +179,29 @@ namespace ams::kern { uintptr_t GetSlabHeapAddress() const { return this->start; } + + size_t GetNumRemaining() const { + size_t remaining = 0; + + /* Only calculate the number of remaining objects under debug configuration. */ + #if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) + while (true) { + auto *cur = this->GetImpl()->GetHead(); + remaining = 0; + + while (this->Contains(reinterpret_cast(cur))) { + ++remaining; + cur = cur->next; + } + + if (cur == nullptr) { + break; + } + } + #endif + + return remaining; + } }; template diff --git a/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp b/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp index e665c182d..ce27e13c5 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_slab_helpers.hpp @@ -48,6 +48,8 @@ namespace ams::kern { static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); } static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); } static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); } + + static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); } }; template @@ -116,6 +118,8 @@ namespace ams::kern { static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); } static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); } static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); } + + static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); } }; } 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 f2c8a8bdc..cd5ddb47a 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 @@ -431,5 +431,28 @@ namespace ams::kern::arch::arm64 { } } + size_t KPageTableImpl::CountPageTables() const { + size_t num_tables = 0; + + #if defined(MESOSPHERE_BUILD_FOR_DEBUGGING) + { + ++num_tables; + for (size_t l1_index = 0; l1_index < this->num_entries; ++l1_index) { + auto &l1_entry = this->table[l1_index]; + if (l1_entry.IsTable()) { + ++num_tables; + for (size_t l2_index = 0; l2_index < MaxPageTableEntries; ++l2_index) { + auto *l2_entry = GetPointer(GetTableEntry(KMemoryLayout::GetLinearVirtualAddress(l1_entry.GetTable()), l2_index)); + if (l2_entry->IsTable()) { + ++num_tables; + } + } + } + } + } + #endif + + return num_tables; + } } diff --git a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp index 812623a24..804ab0a1e 100644 --- a/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp +++ b/libraries/libmesosphere/source/init/kern_init_slab_setup.cpp @@ -22,7 +22,7 @@ namespace ams::kern::init { #define FOREACH_SLAB_TYPE(HANDLER, ...) \ HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \ HANDLER(KThread, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \ - HANDLER(KLinkedListNode, (SLAB_COUNT(KThread) * 17), ## __VA_ARGS__) \ + HANDLER(KLinkedListNode, (SLAB_COUNT(KThread)), ## __VA_ARGS__) \ HANDLER(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \ HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \ HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \ @@ -77,7 +77,7 @@ namespace ams::kern::init { namespace test { - constexpr size_t RequiredSizeForExtraThreadCount = SlabCountExtraKThread * (sizeof(KThread) + (sizeof(KLinkedListNode) * 17) + (sizeof(KThreadLocalPage) / 8) + sizeof(KEventInfo)); + constexpr size_t RequiredSizeForExtraThreadCount = SlabCountExtraKThread * (sizeof(KThread) + sizeof(KLinkedListNode) + (sizeof(KThreadLocalPage) / 8) + sizeof(KEventInfo)); static_assert(RequiredSizeForExtraThreadCount <= KernelSlabHeapAdditionalSize); } diff --git a/libraries/libmesosphere/source/kern_k_dump_object.cpp b/libraries/libmesosphere/source/kern_k_dump_object.cpp index 96f35a196..747829475 100644 --- a/libraries/libmesosphere/source/kern_k_dump_object.cpp +++ b/libraries/libmesosphere/source/kern_k_dump_object.cpp @@ -181,7 +181,7 @@ namespace ams::kern::KDumpObject { } } } - MESOSPHERE_RELEASE_LOG("%-9s: Handle %08x Obj=%p Cur=%3d Max=%3d Peak=%3d\n", name, handle, obj.GetPointerUnsafe(), client->GetNumSessions(), client->GetMaxSessions(), client->GetPeakSessions()); + MESOSPHERE_RELEASE_LOG("%-9s: Handle %08x Obj=%p Cur=%3d Peak=%3d Max=%3d\n", name, handle, obj.GetPointerUnsafe(), client->GetNumSessions(), client->GetPeakSessions(), client->GetMaxSessions()); /* Identify any sessions. */ { @@ -268,6 +268,204 @@ namespace ams::kern::KDumpObject { MESOSPHERE_RELEASE_LOG("\n"); } + void DumpKernelObject() { + MESOSPHERE_LOG("Dump Kernel Object\n"); + + { + /* Static slab heaps. */ + { + #define DUMP_KSLABOBJ(__OBJECT__) \ + MESOSPHERE_RELEASE_LOG(#__OBJECT__ "\n"); \ + MESOSPHERE_RELEASE_LOG(" Cur=%3zu Peak=%3zu Max=%3zu\n", __OBJECT__::GetSlabHeapSize() - __OBJECT__::GetNumRemaining(), __OBJECT__::GetPeakIndex(), __OBJECT__::GetSlabHeapSize()) + + DUMP_KSLABOBJ(KPageBuffer); + DUMP_KSLABOBJ(KEvent); + DUMP_KSLABOBJ(KInterruptEvent); + DUMP_KSLABOBJ(KProcess); + DUMP_KSLABOBJ(KThread); + DUMP_KSLABOBJ(KPort); + DUMP_KSLABOBJ(KSharedMemory); + DUMP_KSLABOBJ(KTransferMemory); + DUMP_KSLABOBJ(KDeviceAddressSpace); + DUMP_KSLABOBJ(KDebug); + DUMP_KSLABOBJ(KSession); + DUMP_KSLABOBJ(KLightSession); + DUMP_KSLABOBJ(KLinkedListNode); + DUMP_KSLABOBJ(KThreadLocalPage); + DUMP_KSLABOBJ(KObjectName); + DUMP_KSLABOBJ(KEventInfo); + DUMP_KSLABOBJ(KSessionRequest); + DUMP_KSLABOBJ(KResourceLimit); + DUMP_KSLABOBJ(KAlpha); + DUMP_KSLABOBJ(KBeta); + + #undef DUMP_KSLABOBJ + + } + MESOSPHERE_RELEASE_LOG("\n"); + + /* Dynamic slab heaps. */ + { + /* Memory block slabs. */ + { + MESOSPHERE_RELEASE_LOG("App Memory Block\n"); + auto &app = Kernel::GetApplicationMemoryBlockManager(); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", app.GetUsed(), app.GetPeak(), app.GetCount()); + MESOSPHERE_RELEASE_LOG("Sys Memory Block\n"); + auto &sys = Kernel::GetSystemMemoryBlockManager(); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", sys.GetUsed(), sys.GetPeak(), sys.GetCount()); + } + + /* KBlockInfo slab. */ + { + MESOSPHERE_RELEASE_LOG("KBlockInfo\n"); + auto &manager = Kernel::GetBlockInfoManager(); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount()); + } + + /* Page Table slab. */ + { + MESOSPHERE_RELEASE_LOG("Page Table\n"); + auto &manager = Kernel::GetPageTableManager(); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", manager.GetUsed(), manager.GetPeak(), manager.GetCount()); + } + } + MESOSPHERE_RELEASE_LOG("\n"); + + /* Process resources. */ + { + KProcess::ListAccessor accessor; + + size_t process_pts = 0; + + const auto end = accessor.end(); + for (auto it = accessor.begin(); it != end; ++it) { + KProcess *process = static_cast(std::addressof(*it)); + + /* Count the number of threads. */ + int threads = 0; + { + KThread::ListAccessor thr_accessor; + const auto thr_end = thr_accessor.end(); + for (auto thr_it = thr_accessor.begin(); thr_it != thr_end; ++thr_it) { + KThread *thread = static_cast(std::addressof(*thr_it)); + if (thread->GetOwnerProcess() == process) { + ++threads; + } + } + } + + /* Count the number of events. */ + int events = 0; + { + KEvent::ListAccessor ev_accessor; + const auto ev_end = ev_accessor.end(); + for (auto ev_it = ev_accessor.begin(); ev_it != ev_end; ++ev_it) { + KEvent *event = static_cast(std::addressof(*ev_it)); + if (event->GetOwner() == process) { + ++events; + } + } + } + + size_t pts = process->GetPageTable().CountPageTables(); + process_pts += pts; + + MESOSPHERE_RELEASE_LOG("%-12s: PID=%3lu Thread %4d / Event %4d / PageTable %5zu\n", process->GetName(), process->GetId(), threads, events, pts); + if (process->GetTotalSystemResourceSize() != 0) { + MESOSPHERE_RELEASE_LOG(" System Resource\n"); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetDynamicPageManager().GetUsed(), process->GetDynamicPageManager().GetPeak(), process->GetDynamicPageManager().GetCount()); + MESOSPHERE_RELEASE_LOG(" Memory Block\n"); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetMemoryBlockSlabManager().GetUsed(), process->GetMemoryBlockSlabManager().GetPeak(), process->GetMemoryBlockSlabManager().GetCount()); + MESOSPHERE_RELEASE_LOG(" Page Table\n"); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetPageTableManager().GetUsed(), process->GetPageTableManager().GetPeak(), process->GetPageTableManager().GetCount()); + MESOSPHERE_RELEASE_LOG(" Block Info\n"); + MESOSPHERE_RELEASE_LOG(" Cur=%6zu Peak=%6zu Max=%6zu\n", process->GetBlockInfoManager().GetUsed(), process->GetBlockInfoManager().GetPeak(), process->GetBlockInfoManager().GetCount()); + } + } + + MESOSPHERE_RELEASE_LOG("Process Page Table %zu\n", process_pts); + MESOSPHERE_RELEASE_LOG("Kernel Page Table %zu\n", Kernel::GetKernelPageTable().CountPageTables()); + } + MESOSPHERE_RELEASE_LOG("\n"); + + /* Resource limits. */ + { + auto &sys_rl = Kernel::GetSystemResourceLimit(); + + u64 cur = sys_rl.GetCurrentValue(ams::svc::LimitableResource_PhysicalMemoryMax); + u64 lim = sys_rl.GetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax); + MESOSPHERE_RELEASE_LOG("System ResourceLimit PhysicalMemory 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(lim >> 32), static_cast(lim)); + + cur = sys_rl.GetCurrentValue(ams::svc::LimitableResource_ThreadCountMax); + lim = sys_rl.GetLimitValue(ams::svc::LimitableResource_ThreadCountMax); + MESOSPHERE_RELEASE_LOG("System ResourceLimit Thread %4lu / %4lu\n", cur, lim); + + cur = sys_rl.GetCurrentValue(ams::svc::LimitableResource_EventCountMax); + lim = sys_rl.GetLimitValue(ams::svc::LimitableResource_EventCountMax); + MESOSPHERE_RELEASE_LOG("System ResourceLimit Event %4lu / %4lu\n", cur, lim); + + cur = sys_rl.GetCurrentValue(ams::svc::LimitableResource_TransferMemoryCountMax); + lim = sys_rl.GetLimitValue(ams::svc::LimitableResource_TransferMemoryCountMax); + MESOSPHERE_RELEASE_LOG("System ResourceLimit TransferMemory %4lu / %4lu\n", cur, lim); + + cur = sys_rl.GetCurrentValue(ams::svc::LimitableResource_SessionCountMax); + lim = sys_rl.GetLimitValue(ams::svc::LimitableResource_SessionCountMax); + MESOSPHERE_RELEASE_LOG("System ResourceLimit Session %4lu / %4lu\n", cur, lim); + + { + KResourceLimit::ListAccessor accessor; + + const auto end = accessor.end(); + for (auto it = accessor.begin(); it != end; ++it) { + KResourceLimit *rl = static_cast(std::addressof(*it)); + cur = rl->GetCurrentValue(ams::svc::LimitableResource_PhysicalMemoryMax); + lim = rl->GetLimitValue(ams::svc::LimitableResource_PhysicalMemoryMax); + MESOSPHERE_RELEASE_LOG("ResourceLimit %zu PhysicalMemory 0x%01x_%08x / 0x%01x_%08x\n", rl->GetSlabIndex(), static_cast(cur >> 32), static_cast(cur), static_cast(lim >> 32), static_cast(lim)); + } + } + } + MESOSPHERE_RELEASE_LOG("\n"); + + /* Memory Manager. */ + { + auto &mm = Kernel::GetMemoryManager(); + u64 max = mm.GetSize(); + u64 cur = max - mm.GetFreeSize(); + MESOSPHERE_RELEASE_LOG("Kernel Heap Size 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(max >> 32), static_cast(max)); + MESOSPHERE_RELEASE_LOG("\n"); + + max = mm.GetSize(KMemoryManager::Pool_Application); + cur = max - mm.GetFreeSize(KMemoryManager::Pool_Application); + MESOSPHERE_RELEASE_LOG("Application 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(max >> 32), static_cast(max)); + mm.DumpFreeList(KMemoryManager::Pool_Application); + MESOSPHERE_RELEASE_LOG("\n"); + + max = mm.GetSize(KMemoryManager::Pool_Applet); + cur = max - mm.GetFreeSize(KMemoryManager::Pool_Applet); + MESOSPHERE_RELEASE_LOG("Applet 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(max >> 32), static_cast(max)); + mm.DumpFreeList(KMemoryManager::Pool_Applet); + MESOSPHERE_RELEASE_LOG("\n"); + + max = mm.GetSize(KMemoryManager::Pool_System); + cur = max - mm.GetFreeSize(KMemoryManager::Pool_System); + MESOSPHERE_RELEASE_LOG("System 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(max >> 32), static_cast(max)); + mm.DumpFreeList(KMemoryManager::Pool_System); + MESOSPHERE_RELEASE_LOG("\n"); + + max = mm.GetSize(KMemoryManager::Pool_SystemNonSecure); + cur = max - mm.GetFreeSize(KMemoryManager::Pool_SystemNonSecure); + MESOSPHERE_RELEASE_LOG("SystemNonSecure 0x%01x_%08x / 0x%01x_%08x\n", static_cast(cur >> 32), static_cast(cur), static_cast(max >> 32), static_cast(max)); + mm.DumpFreeList(KMemoryManager::Pool_SystemNonSecure); + MESOSPHERE_RELEASE_LOG("\n"); + } + MESOSPHERE_RELEASE_LOG("\n"); + + } + + MESOSPHERE_RELEASE_LOG("\n"); + } + void DumpHandle() { MESOSPHERE_RELEASE_LOG("Dump Handle\n"); diff --git a/libraries/libmesosphere/source/kern_k_page_heap.cpp b/libraries/libmesosphere/source/kern_k_page_heap.cpp index 6199649e8..428a238e2 100644 --- a/libraries/libmesosphere/source/kern_k_page_heap.cpp +++ b/libraries/libmesosphere/source/kern_k_page_heap.cpp @@ -132,4 +132,29 @@ namespace ams::kern { return util::AlignUp(overhead_size, PageSize); } + void KPageHeap::DumpFreeList() const { + MESOSPHERE_RELEASE_LOG("KPageHeap::DumpFreeList %p\n", this); + + for (size_t i = 0; i < this->num_blocks; ++i) { + const size_t block_size = this->blocks[i].GetSize(); + const char *suffix; + size_t size; + if (block_size >= 1_GB) { + suffix = "GiB"; + size = block_size / 1_GB; + } else if (block_size >= 1_MB) { + suffix = "MiB"; + size = block_size / 1_MB; + } else if (block_size >= 1_KB) { + suffix = "KiB"; + size = block_size / 1_KB; + } else { + suffix = "B"; + size = block_size; + } + + MESOSPHERE_RELEASE_LOG(" %4zu %s block x %zu\n", size, suffix, this->blocks[i].GetNumFreeBlocks()); + } + } + } diff --git a/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp b/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp index 632d7a9cf..d16643cd6 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_kernel_debug.cpp @@ -41,6 +41,9 @@ namespace ams::kern::svc { KDumpObject::DumpThreadCallStack(arg0); } break; + case ams::svc::KernelDebugType_KernelObject: + KDumpObject::DumpKernelObject(); + break; case ams::svc::KernelDebugType_Handle: if (arg0 == static_cast(-1)) { KDumpObject::DumpHandle(); diff --git a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp index 5b4d14e26..e5f048798 100644 --- a/libraries/libvapours/include/vapours/svc/svc_types_common.hpp +++ b/libraries/libvapours/include/vapours/svc/svc_types_common.hpp @@ -472,7 +472,7 @@ namespace ams::svc { enum KernelDebugType : u32 { KernelDebugType_Thread = 0, KernelDebugType_ThreadCallStack = 1, - + KernelDebugType_KernelObject = 2, KernelDebugType_Handle = 3, KernelDebugType_Process = 7,