From 84a22cb5947b0733a043429032367227e73342dc Mon Sep 17 00:00:00 2001 From: Yuri Kunde Schlesner Date: Thu, 26 Nov 2015 19:00:16 -0800 Subject: [PATCH] Kernel: Implement svcGetSystemInfo This makes smealum/ctrulib@b96dd51d3349961189d4ab1bc2a5c45deff21c09 work with Citra. --- src/core/hle/function_wrappers.h | 8 ++++++ src/core/hle/kernel/memory.cpp | 2 ++ src/core/hle/kernel/memory.h | 1 + src/core/hle/kernel/process.cpp | 6 ++++ src/core/hle/kernel/thread.cpp | 3 ++ src/core/hle/svc.cpp | 47 +++++++++++++++++++++++++++++++- src/core/hle/svc.h | 29 ++++++++++++++++++++ 7 files changed, 95 insertions(+), 1 deletion(-) diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 5846a161b..3501e45db 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h @@ -159,6 +159,14 @@ template void Wrap() { FuncReturn(retval); } +template void Wrap() { + s64 param_1 = 0; + u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; + Core::g_app_core->SetReg(1, (u32)param_1); + Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); + FuncReturn(retval); +} + template void Wrap() { u32 param_1 = 0; u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; diff --git a/src/core/hle/kernel/memory.cpp b/src/core/hle/kernel/memory.cpp index e4fc5f3c4..0cfb43fc7 100644 --- a/src/core/hle/kernel/memory.cpp +++ b/src/core/hle/kernel/memory.cpp @@ -51,6 +51,7 @@ void MemoryInit(u32 mem_type) { for (int i = 0; i < 3; ++i) { memory_regions[i].base = base; memory_regions[i].size = memory_region_sizes[mem_type][i]; + memory_regions[i].used = 0; memory_regions[i].linear_heap_memory = std::make_shared>(); base += memory_regions[i].size; @@ -72,6 +73,7 @@ void MemoryShutdown() { for (auto& region : memory_regions) { region.base = 0; region.size = 0; + region.used = 0; region.linear_heap_memory = nullptr; } } diff --git a/src/core/hle/kernel/memory.h b/src/core/hle/kernel/memory.h index 36690b091..091c1f89f 100644 --- a/src/core/hle/kernel/memory.h +++ b/src/core/hle/kernel/memory.h @@ -17,6 +17,7 @@ class VMManager; struct MemoryRegionInfo { u32 base; // Not an address, but offset from start of FCRAM u32 size; + u32 used; std::shared_ptr> linear_heap_memory; }; diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index c2b4963d4..d148efde2 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -111,6 +111,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { segment.offset, segment.size, memory_state).Unwrap(); vm_manager.Reprotect(vma, permissions); misc_memory_used += segment.size; + memory_region->used += segment.size; }; // Map CodeSet segments @@ -123,6 +124,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { std::make_shared>(stack_size, 0), 0, stack_size, MemoryState::Locked ).Unwrap(); misc_memory_used += stack_size; + memory_region->used += stack_size; vm_manager.LogLayout(Log::Level::Debug); Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); @@ -165,6 +167,7 @@ ResultVal Process::HeapAllocate(VAddr target, u32 size, VMAPermission per vm_manager.Reprotect(vma, perms); heap_used += size; + memory_region->used += size; return MakeResult(heap_end - size); } @@ -182,6 +185,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { if (result.IsError()) return result; heap_used -= size; + memory_region->used -= size; return RESULT_SUCCESS; } @@ -217,6 +221,7 @@ ResultVal Process::LinearAllocate(VAddr target, u32 size, VMAPermission p vm_manager.Reprotect(vma, perms); linear_heap_used += size; + memory_region->used += size; return MakeResult(target); } @@ -243,6 +248,7 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { if (result.IsError()) return result; linear_heap_used -= size; + memory_region->used -= size; if (target + size == heap_end) { // End of linear heap has been freed, so check what's the last allocated block in it and diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 00fa995f6..c08fc1c7a 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -20,6 +20,7 @@ #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/process.h" #include "core/hle/kernel/thread.h" +#include "core/hle/kernel/memory.h" #include "core/hle/kernel/mutex.h" #include "core/hle/result.h" #include "core/memory.h" @@ -118,6 +119,7 @@ void Thread::Stop() { Kernel::g_current_process->used_tls_slots[tls_index] = false; g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE; + g_current_process->memory_region->used -= Memory::TLS_ENTRY_SIZE; HLE::Reschedule(__func__); } @@ -416,6 +418,7 @@ ResultVal> Thread::Create(std::string name, VAddr entry_point, ASSERT_MSG(thread->tls_index != -1, "Out of TLS space"); g_current_process->misc_memory_used += Memory::TLS_ENTRY_SIZE; + g_current_process->memory_region->used += Memory::TLS_ENTRY_SIZE; // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used // to initialize the context diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index 45d5f3c5d..7f63ff505 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp @@ -778,6 +778,51 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 return RESULT_SUCCESS; } +static ResultCode GetSystemInfo(s64* out, u32 type, s32 param) { + using Kernel::MemoryRegion; + + LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u param=%d", process_handle, type, param); + + switch ((SystemInfoType)type) { + case SystemInfoType::REGION_MEMORY_USAGE: + switch ((SystemInfoMemUsageRegion)param) { + case SystemInfoMemUsageRegion::ALL: + *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used + + Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used + + Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; + break; + case SystemInfoMemUsageRegion::APPLICATION: + *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::APPLICATION)->used; + break; + case SystemInfoMemUsageRegion::SYSTEM: + *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::SYSTEM)->used; + break; + case SystemInfoMemUsageRegion::BASE: + *out = Kernel::GetMemoryRegion(Kernel::MemoryRegion::BASE)->used; + break; + default: + LOG_ERROR(Kernel_SVC, "unknown GetSystemInfo type=0 region: param=%d", param); + *out = 0; + break; + } + break; + case SystemInfoType::KERNEL_ALLOCATED_PAGES: + LOG_ERROR(Kernel_SVC, "unimplemented GetSystemInfo type=2 param=%d", type, param); + *out = 0; + break; + case SystemInfoType::KERNEL_SPAWNED_PIDS: + *out = 5; + break; + default: + LOG_ERROR(Kernel_SVC, "unknown GetSystemInfo type=%u param=%d", type, param); + *out = 0; + break; + } + + // This function never returns an error, even if invalid parameters were passed. + return RESULT_SUCCESS; +} + static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type); @@ -877,7 +922,7 @@ static const FunctionDef SVC_Table[] = { {0x27, HLE::Wrap, "DuplicateHandle"}, {0x28, HLE::Wrap, "GetSystemTick"}, {0x29, nullptr, "GetHandleInfo"}, - {0x2A, nullptr, "GetSystemInfo"}, + {0x2A, HLE::Wrap, "GetSystemInfo"}, {0x2B, HLE::Wrap, "GetProcessInfo"}, {0x2C, nullptr, "GetThreadInfo"}, {0x2D, HLE::Wrap, "ConnectToPort"}, diff --git a/src/core/hle/svc.h b/src/core/hle/svc.h index 12de9ffbe..4b9c71e06 100644 --- a/src/core/hle/svc.h +++ b/src/core/hle/svc.h @@ -41,6 +41,35 @@ enum ArbitrationType { namespace SVC { +/// Values accepted by svcGetSystemInfo's type parameter. +enum class SystemInfoType { + /** + * Reports total used memory for all regions or a specific one, according to the extra + * parameter. See `SystemInfoMemUsageRegion`. + */ + REGION_MEMORY_USAGE = 0, + /** + * Returns the memory usage for certain allocations done internally by the kernel. + */ + KERNEL_ALLOCATED_PAGES = 2, + /** + * "This returns the total number of processes which were launched directly by the kernel. + * For the ARM11 NATIVE_FIRM kernel, this is 5, for processes sm, fs, pm, loader, and pxi." + */ + KERNEL_SPAWNED_PIDS = 26, +}; + +/** + * Accepted by svcGetSystemInfo param with REGION_MEMORY_USAGE type. Selects a region to query + * memory usage of. + */ +enum class SystemInfoMemUsageRegion { + ALL = 0, + APPLICATION = 1, + SYSTEM = 2, + BASE = 3, +}; + void CallSVC(u32 immediate); } // namespace