mirror of
https://github.com/Atmosphere-NX/Atmosphere
synced 2024-11-10 07:06:34 +00:00
kern: add kernel object debug
This commit is contained in:
parent
0acd79c8c2
commit
1a6e003a5d
16 changed files with 341 additions and 15 deletions
|
@ -112,6 +112,7 @@ namespace ams::kern::arch::arm64 {
|
||||||
L1PageTableEntry *Finalize();
|
L1PageTableEntry *Finalize();
|
||||||
|
|
||||||
void Dump(uintptr_t start, size_t size) const;
|
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 BeginTraversal(TraversalEntry *out_entry, TraversalContext *out_context, KProcessAddress address) const;
|
||||||
bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const;
|
bool ContinueTraversal(TraversalEntry *out_entry, TraversalContext *context) const;
|
||||||
|
|
|
@ -232,14 +232,18 @@ namespace ams::kern::arch::arm64 {
|
||||||
return this->page_table.UnmapPhysicalMemoryUnsafe(address, size);
|
return this->page_table.UnmapPhysicalMemoryUnsafe(address, size);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpTable() const {
|
|
||||||
return this->page_table.DumpTable();
|
|
||||||
}
|
|
||||||
|
|
||||||
void DumpMemoryBlocks() const {
|
void DumpMemoryBlocks() const {
|
||||||
return this->page_table.DumpMemoryBlocks();
|
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 {
|
bool GetPhysicalAddress(KPhysicalAddress *out, KProcessAddress address) const {
|
||||||
return this->page_table.GetPhysicalAddress(out, address);
|
return this->page_table.GetPhysicalAddress(out, address);
|
||||||
}
|
}
|
||||||
|
|
|
@ -62,6 +62,10 @@ namespace ams::kern::arch::arm64 {
|
||||||
}
|
}
|
||||||
|
|
||||||
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; }
|
constexpr u64 GetIdentityMapTtbr0(s32 core_id) const { return this->ttbr0_identity[core_id]; }
|
||||||
|
|
||||||
|
size_t CountPageTables() const {
|
||||||
|
return this->page_table.CountPageTables();
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,6 +25,8 @@ namespace ams::kern::KDumpObject {
|
||||||
void DumpThreadCallStack();
|
void DumpThreadCallStack();
|
||||||
void DumpThreadCallStack(u64 thread_id);
|
void DumpThreadCallStack(u64 thread_id);
|
||||||
|
|
||||||
|
void DumpKernelObject();
|
||||||
|
|
||||||
void DumpHandle();
|
void DumpHandle();
|
||||||
void DumpHandle(u64 process_id);
|
void DumpHandle(u64 process_id);
|
||||||
|
|
||||||
|
|
|
@ -90,6 +90,8 @@ namespace ams::kern {
|
||||||
|
|
||||||
size_t GetFreeSize() const { return this->heap.GetFreeSize(); }
|
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 GetPageOffset(KVirtualAddress address) const { return this->heap.GetPageOffset(address); }
|
||||||
constexpr size_t GetPageOffsetToEnd(KVirtualAddress address) const { return this->heap.GetPageOffsetToEnd(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 GetFreeSize() {
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
for (size_t i = 0; i < this->num_managers; i++) {
|
for (size_t i = 0; i < this->num_managers; i++) {
|
||||||
|
KScopedLightLock lk(this->pool_locks[this->managers[i].GetPool()]);
|
||||||
total += this->managers[i].GetFreeSize();
|
total += this->managers[i].GetFreeSize();
|
||||||
}
|
}
|
||||||
return total;
|
return total;
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetFreeSize(Pool pool) {
|
size_t GetFreeSize(Pool pool) {
|
||||||
|
KScopedLightLock lk(this->pool_locks[pool]);
|
||||||
|
|
||||||
constexpr Direction GetSizeDirection = Direction_FromFront;
|
constexpr Direction GetSizeDirection = Direction_FromFront;
|
||||||
size_t total = 0;
|
size_t total = 0;
|
||||||
for (auto *manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr; manager = this->GetNextManager(manager, GetSizeDirection)) {
|
for (auto *manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr; manager = this->GetNextManager(manager, GetSizeDirection)) {
|
||||||
|
@ -260,6 +265,15 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
return total;
|
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:
|
public:
|
||||||
static size_t CalculateManagementOverheadSize(size_t region_size) {
|
static size_t CalculateManagementOverheadSize(size_t region_size) {
|
||||||
return Impl::CalculateManagementOverheadSize(region_size);
|
return Impl::CalculateManagementOverheadSize(region_size);
|
||||||
|
|
|
@ -147,6 +147,7 @@ namespace ams::kern {
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t GetFreeSize() const { return this->GetNumFreePages() * PageSize; }
|
size_t GetFreeSize() const { return this->GetNumFreePages() * PageSize; }
|
||||||
|
void DumpFreeList() const;
|
||||||
|
|
||||||
void UpdateUsedSize() {
|
void UpdateUsedSize() {
|
||||||
this->used_size = this->heap_size - (this->GetNumFreePages() * PageSize);
|
this->used_size = this->heap_size - (this->GetNumFreePages() * PageSize);
|
||||||
|
|
|
@ -382,9 +382,9 @@ namespace ams::kern {
|
||||||
Result MapPhysicalMemoryUnsafe(KProcessAddress address, size_t size);
|
Result MapPhysicalMemoryUnsafe(KProcessAddress address, size_t size);
|
||||||
Result UnmapPhysicalMemoryUnsafe(KProcessAddress address, size_t size);
|
Result UnmapPhysicalMemoryUnsafe(KProcessAddress address, size_t size);
|
||||||
|
|
||||||
void DumpTable() const {
|
void DumpMemoryBlocksLocked() const {
|
||||||
KScopedLightLock lk(this->general_lock);
|
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
||||||
this->GetImpl().Dump(GetInteger(this->address_space_start), this->address_space_end - this->address_space_start);
|
this->memory_block_manager.DumpBlocks();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpMemoryBlocks() const {
|
void DumpMemoryBlocks() const {
|
||||||
|
@ -392,9 +392,14 @@ namespace ams::kern {
|
||||||
this->DumpMemoryBlocksLocked();
|
this->DumpMemoryBlocksLocked();
|
||||||
}
|
}
|
||||||
|
|
||||||
void DumpMemoryBlocksLocked() const {
|
void DumpPageTable() const {
|
||||||
MESOSPHERE_ASSERT(this->IsLockedByCurrentThread());
|
KScopedLightLock lk(this->general_lock);
|
||||||
this->memory_block_manager.DumpBlocks();
|
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:
|
public:
|
||||||
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
KProcessAddress GetAddressSpaceStart() const { return this->address_space_start; }
|
||||||
|
|
|
@ -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 KThread *GetRunningThread(s32 core) const { return this->running_threads[core]; }
|
||||||
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return this->running_thread_idle_counts[core]; }
|
constexpr u64 GetRunningThreadIdleCount(s32 core) const { return this->running_thread_idle_counts[core]; }
|
||||||
|
|
||||||
|
|
|
@ -140,7 +140,21 @@ namespace ams::kern {
|
||||||
|
|
||||||
void *obj = this->GetImpl()->Allocate();
|
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<uintptr_t>::is_always_lock_free);
|
||||||
|
std::atomic_ref<uintptr_t> peak_ref(this->peak);
|
||||||
|
|
||||||
|
const uintptr_t alloc_peak = reinterpret_cast<uintptr_t>(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;
|
return obj;
|
||||||
}
|
}
|
||||||
|
@ -165,6 +179,29 @@ namespace ams::kern {
|
||||||
uintptr_t GetSlabHeapAddress() const {
|
uintptr_t GetSlabHeapAddress() const {
|
||||||
return this->start;
|
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<uintptr_t>(cur))) {
|
||||||
|
++remaining;
|
||||||
|
cur = cur->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (cur == nullptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return remaining;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename T>
|
template<typename T>
|
||||||
|
|
|
@ -48,6 +48,8 @@ namespace ams::kern {
|
||||||
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
||||||
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
||||||
static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); }
|
static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); }
|
||||||
|
|
||||||
|
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename Derived, typename Base>
|
template<typename Derived, typename Base>
|
||||||
|
@ -116,6 +118,8 @@ namespace ams::kern {
|
||||||
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
static size_t GetSlabHeapSize() { return s_slab_heap.GetSlabHeapSize(); }
|
||||||
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
static size_t GetPeakIndex() { return s_slab_heap.GetPeakIndex(); }
|
||||||
static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); }
|
static uintptr_t GetSlabHeapAddress() { return s_slab_heap.GetSlabHeapAddress(); }
|
||||||
|
|
||||||
|
static size_t GetNumRemaining() { return s_slab_heap.GetNumRemaining(); }
|
||||||
};
|
};
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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<L2PageTableEntry>(GetTableEntry(KMemoryLayout::GetLinearVirtualAddress(l1_entry.GetTable()), l2_index));
|
||||||
|
if (l2_entry->IsTable()) {
|
||||||
|
++num_tables;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
return num_tables;
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,7 +22,7 @@ namespace ams::kern::init {
|
||||||
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
#define FOREACH_SLAB_TYPE(HANDLER, ...) \
|
||||||
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
HANDLER(KProcess, (SLAB_COUNT(KProcess)), ## __VA_ARGS__) \
|
||||||
HANDLER(KThread, (SLAB_COUNT(KThread)), ## __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(KEvent, (SLAB_COUNT(KEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEvent, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
HANDLER(KInterruptEventTask, (SLAB_COUNT(KInterruptEvent)), ## __VA_ARGS__) \
|
||||||
|
@ -77,7 +77,7 @@ namespace ams::kern::init {
|
||||||
|
|
||||||
namespace test {
|
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);
|
static_assert(RequiredSizeForExtraThreadCount <= KernelSlabHeapAdditionalSize);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -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. */
|
/* Identify any sessions. */
|
||||||
{
|
{
|
||||||
|
@ -268,6 +268,204 @@ namespace ams::kern::KDumpObject {
|
||||||
MESOSPHERE_RELEASE_LOG("\n");
|
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<KProcess *>(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<KThread *>(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<KEvent *>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(lim >> 32), static_cast<u32>(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<KResourceLimit *>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(lim >> 32), static_cast<u32>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(max >> 32), static_cast<u32>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(max >> 32), static_cast<u32>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(max >> 32), static_cast<u32>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(max >> 32), static_cast<u32>(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<u32>(cur >> 32), static_cast<u32>(cur), static_cast<u32>(max >> 32), static_cast<u32>(max));
|
||||||
|
mm.DumpFreeList(KMemoryManager::Pool_SystemNonSecure);
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
MESOSPHERE_RELEASE_LOG("\n");
|
||||||
|
}
|
||||||
|
|
||||||
void DumpHandle() {
|
void DumpHandle() {
|
||||||
MESOSPHERE_RELEASE_LOG("Dump Handle\n");
|
MESOSPHERE_RELEASE_LOG("Dump Handle\n");
|
||||||
|
|
||||||
|
|
|
@ -132,4 +132,29 @@ namespace ams::kern {
|
||||||
return util::AlignUp(overhead_size, PageSize);
|
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());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,9 @@ namespace ams::kern::svc {
|
||||||
KDumpObject::DumpThreadCallStack(arg0);
|
KDumpObject::DumpThreadCallStack(arg0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
case ams::svc::KernelDebugType_KernelObject:
|
||||||
|
KDumpObject::DumpKernelObject();
|
||||||
|
break;
|
||||||
case ams::svc::KernelDebugType_Handle:
|
case ams::svc::KernelDebugType_Handle:
|
||||||
if (arg0 == static_cast<u64>(-1)) {
|
if (arg0 == static_cast<u64>(-1)) {
|
||||||
KDumpObject::DumpHandle();
|
KDumpObject::DumpHandle();
|
||||||
|
|
|
@ -472,7 +472,7 @@ namespace ams::svc {
|
||||||
enum KernelDebugType : u32 {
|
enum KernelDebugType : u32 {
|
||||||
KernelDebugType_Thread = 0,
|
KernelDebugType_Thread = 0,
|
||||||
KernelDebugType_ThreadCallStack = 1,
|
KernelDebugType_ThreadCallStack = 1,
|
||||||
|
KernelDebugType_KernelObject = 2,
|
||||||
KernelDebugType_Handle = 3,
|
KernelDebugType_Handle = 3,
|
||||||
|
|
||||||
KernelDebugType_Process = 7,
|
KernelDebugType_Process = 7,
|
||||||
|
|
Loading…
Reference in a new issue