From 058f223b97309e2409e2c9fceb12c4a29adfbd03 Mon Sep 17 00:00:00 2001 From: Michael Scire Date: Tue, 21 Jul 2020 01:59:48 -0700 Subject: [PATCH] kern: finish SvcGetSystemInfo --- .../mesosphere/kern_k_memory_manager.hpp | 19 ++++++++++ .../include/mesosphere/kern_k_page_heap.hpp | 2 + .../source/svc/kern_svc_info.cpp | 37 +++++++++++++++++++ 3 files changed, 58 insertions(+) diff --git a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp index 8c17c54e0..468469e2c 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_memory_manager.hpp @@ -73,6 +73,8 @@ namespace ams::kern { constexpr size_t GetSize() const { return this->heap.GetSize(); } constexpr KVirtualAddress GetEndAddress() const { return this->heap.GetEndAddress(); } + size_t GetFreeSize() const { return this->heap.GetFreeSize(); } + constexpr void SetNext(Impl *n) { this->next = n; } constexpr void SetPrev(Impl *n) { this->prev = n; } constexpr Impl *GetNext() const { return this->next; } @@ -204,6 +206,23 @@ namespace ams::kern { } return total; } + + size_t GetFreeSize() { + size_t total = 0; + for (size_t i = 0; i < this->num_managers; i++) { + total += this->managers[i].GetFreeSize(); + } + return total; + } + + size_t GetFreeSize(Pool pool) { + constexpr Direction GetSizeDirection = Direction_FromFront; + size_t total = 0; + for (auto *manager = this->GetFirstManager(pool, GetSizeDirection); manager != nullptr; manager = this->GetNextManager(manager, GetSizeDirection)) { + total += manager->GetFreeSize(); + } + return total; + } public: static size_t CalculateMetadataOverheadSize(size_t region_size) { return Impl::CalculateMetadataOverheadSize(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 47148acd8..f5dcfe5b3 100644 --- a/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp +++ b/libraries/libmesosphere/include/mesosphere/kern_k_page_heap.hpp @@ -145,6 +145,8 @@ namespace ams::kern { return Initialize(heap_address, heap_size, metadata_address, metadata_size, MemoryBlockPageShifts, NumMemoryBlockPageShifts); } + size_t GetFreeSize() const { return this->GetNumFreePages() * PageSize; } + void UpdateUsedSize() { this->used_size = this->heap_size - (this->GetNumFreePages() * PageSize); } diff --git a/libraries/libmesosphere/source/svc/kern_svc_info.cpp b/libraries/libmesosphere/source/svc/kern_svc_info.cpp index 9b44dbb03..4604849b3 100644 --- a/libraries/libmesosphere/source/svc/kern_svc_info.cpp +++ b/libraries/libmesosphere/source/svc/kern_svc_info.cpp @@ -139,11 +139,48 @@ namespace ams::kern::svc { return ResultSuccess(); } + constexpr bool IsValidMemoryPool(u64 pool) { + switch (static_cast(pool)) { + case KMemoryManager::Pool_Application: + case KMemoryManager::Pool_Applet: + case KMemoryManager::Pool_System: + case KMemoryManager::Pool_SystemNonSecure: + return true; + default: + return false; + } + } + Result GetSystemInfo(u64 *out, ams::svc::SystemInfoType info_type, ams::svc::Handle handle, u64 info_subtype) { MESOSPHERE_LOG("GetSystemInfo(%p, %u, %08x, %lu) was called\n", out, static_cast(info_type), static_cast(handle), info_subtype); ON_SCOPE_EXIT{ MESOSPHERE_LOG("GetSystemInfo returned %016lx\n", *out); }; switch (info_type) { + case ams::svc::SystemInfoType_TotalPhysicalMemorySize: + case ams::svc::SystemInfoType_UsedPhysicalMemorySize: + { + /* Verify the input handle is invalid. */ + R_UNLESS(handle == ams::svc::InvalidHandle, svc::ResultInvalidHandle()); + + /* Verify the sub-type is valid. */ + R_UNLESS(IsValidMemoryPool(info_subtype), svc::ResultInvalidCombination()); + + /* Convert to pool. */ + const auto pool = static_cast(info_subtype); + + /* Get the memory size. */ + auto &mm = Kernel::GetMemoryManager(); + switch (info_type) { + case ams::svc::SystemInfoType_TotalPhysicalMemorySize: + *out = mm.GetSize(pool); + break; + case ams::svc::SystemInfoType_UsedPhysicalMemorySize: + *out = mm.GetSize(pool) - mm.GetFreeSize(pool); + break; + MESOSPHERE_UNREACHABLE_DEFAULT_CASE(); + } + } + break; case ams::svc::SystemInfoType_InitialProcessIdRange: { R_UNLESS(handle == ams::svc::InvalidHandle, svc::ResultInvalidHandle());