mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 13:50:03 +00:00 
			
		
		
		
	Kernel: Implement svcGetSystemInfo
This makes smealum/ctrulib@b96dd51d33 work with Citra.
This commit is contained in:
		
							parent
							
								
									32f92b4a69
								
							
						
					
					
						commit
						84a22cb594
					
				
					 7 changed files with 95 additions and 1 deletions
				
			
		|  | @ -159,6 +159,14 @@ template<ResultCode func(s32*, u32, s32)> void Wrap() { | ||||||
|     FuncReturn(retval); |     FuncReturn(retval); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  | template<ResultCode func(s64*, u32, s32)> 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<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { | template<ResultCode func(u32*, u32, u32, u32, u32)> void Wrap() { | ||||||
|     u32 param_1 = 0; |     u32 param_1 = 0; | ||||||
|     u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; |     u32 retval = func(¶m_1, PARAM(1), PARAM(2), PARAM(3), PARAM(4)).raw; | ||||||
|  |  | ||||||
|  | @ -51,6 +51,7 @@ void MemoryInit(u32 mem_type) { | ||||||
|     for (int i = 0; i < 3; ++i) { |     for (int i = 0; i < 3; ++i) { | ||||||
|         memory_regions[i].base = base; |         memory_regions[i].base = base; | ||||||
|         memory_regions[i].size = memory_region_sizes[mem_type][i]; |         memory_regions[i].size = memory_region_sizes[mem_type][i]; | ||||||
|  |         memory_regions[i].used = 0; | ||||||
|         memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>(); |         memory_regions[i].linear_heap_memory = std::make_shared<std::vector<u8>>(); | ||||||
| 
 | 
 | ||||||
|         base += memory_regions[i].size; |         base += memory_regions[i].size; | ||||||
|  | @ -72,6 +73,7 @@ void MemoryShutdown() { | ||||||
|     for (auto& region : memory_regions) { |     for (auto& region : memory_regions) { | ||||||
|         region.base = 0; |         region.base = 0; | ||||||
|         region.size = 0; |         region.size = 0; | ||||||
|  |         region.used = 0; | ||||||
|         region.linear_heap_memory = nullptr; |         region.linear_heap_memory = nullptr; | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -17,6 +17,7 @@ class VMManager; | ||||||
| struct MemoryRegionInfo { | struct MemoryRegionInfo { | ||||||
|     u32 base; // Not an address, but offset from start of FCRAM
 |     u32 base; // Not an address, but offset from start of FCRAM
 | ||||||
|     u32 size; |     u32 size; | ||||||
|  |     u32 used; | ||||||
| 
 | 
 | ||||||
|     std::shared_ptr<std::vector<u8>> linear_heap_memory; |     std::shared_ptr<std::vector<u8>> linear_heap_memory; | ||||||
| }; | }; | ||||||
|  |  | ||||||
|  | @ -111,6 +111,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | ||||||
|                 segment.offset, segment.size, memory_state).Unwrap(); |                 segment.offset, segment.size, memory_state).Unwrap(); | ||||||
|         vm_manager.Reprotect(vma, permissions); |         vm_manager.Reprotect(vma, permissions); | ||||||
|         misc_memory_used += segment.size; |         misc_memory_used += segment.size; | ||||||
|  |         memory_region->used += segment.size; | ||||||
|     }; |     }; | ||||||
| 
 | 
 | ||||||
|     // Map CodeSet segments
 |     // Map CodeSet segments
 | ||||||
|  | @ -123,6 +124,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | ||||||
|             std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked |             std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked | ||||||
|             ).Unwrap(); |             ).Unwrap(); | ||||||
|     misc_memory_used += stack_size; |     misc_memory_used += stack_size; | ||||||
|  |     memory_region->used += stack_size; | ||||||
| 
 | 
 | ||||||
|     vm_manager.LogLayout(Log::Level::Debug); |     vm_manager.LogLayout(Log::Level::Debug); | ||||||
|     Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); |     Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | ||||||
|  | @ -165,6 +167,7 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | ||||||
|     vm_manager.Reprotect(vma, perms); |     vm_manager.Reprotect(vma, perms); | ||||||
| 
 | 
 | ||||||
|     heap_used += size; |     heap_used += size; | ||||||
|  |     memory_region->used += size; | ||||||
| 
 | 
 | ||||||
|     return MakeResult<VAddr>(heap_end - size); |     return MakeResult<VAddr>(heap_end - size); | ||||||
| } | } | ||||||
|  | @ -182,6 +185,7 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | ||||||
|     if (result.IsError()) return result; |     if (result.IsError()) return result; | ||||||
| 
 | 
 | ||||||
|     heap_used -= size; |     heap_used -= size; | ||||||
|  |     memory_region->used -= size; | ||||||
| 
 | 
 | ||||||
|     return RESULT_SUCCESS; |     return RESULT_SUCCESS; | ||||||
| } | } | ||||||
|  | @ -217,6 +221,7 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | ||||||
|     vm_manager.Reprotect(vma, perms); |     vm_manager.Reprotect(vma, perms); | ||||||
| 
 | 
 | ||||||
|     linear_heap_used += size; |     linear_heap_used += size; | ||||||
|  |     memory_region->used += size; | ||||||
| 
 | 
 | ||||||
|     return MakeResult<VAddr>(target); |     return MakeResult<VAddr>(target); | ||||||
| } | } | ||||||
|  | @ -243,6 +248,7 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | ||||||
|     if (result.IsError()) return result; |     if (result.IsError()) return result; | ||||||
| 
 | 
 | ||||||
|     linear_heap_used -= size; |     linear_heap_used -= size; | ||||||
|  |     memory_region->used -= size; | ||||||
| 
 | 
 | ||||||
|     if (target + size == heap_end) { |     if (target + size == heap_end) { | ||||||
|         // End of linear heap has been freed, so check what's the last allocated block in it and
 |         // End of linear heap has been freed, so check what's the last allocated block in it and
 | ||||||
|  |  | ||||||
|  | @ -20,6 +20,7 @@ | ||||||
| #include "core/hle/kernel/kernel.h" | #include "core/hle/kernel/kernel.h" | ||||||
| #include "core/hle/kernel/process.h" | #include "core/hle/kernel/process.h" | ||||||
| #include "core/hle/kernel/thread.h" | #include "core/hle/kernel/thread.h" | ||||||
|  | #include "core/hle/kernel/memory.h" | ||||||
| #include "core/hle/kernel/mutex.h" | #include "core/hle/kernel/mutex.h" | ||||||
| #include "core/hle/result.h" | #include "core/hle/result.h" | ||||||
| #include "core/memory.h" | #include "core/memory.h" | ||||||
|  | @ -118,6 +119,7 @@ void Thread::Stop() { | ||||||
| 
 | 
 | ||||||
|     Kernel::g_current_process->used_tls_slots[tls_index] = false; |     Kernel::g_current_process->used_tls_slots[tls_index] = false; | ||||||
|     g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE; |     g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE; | ||||||
|  |     g_current_process->memory_region->used -= Memory::TLS_ENTRY_SIZE; | ||||||
| 
 | 
 | ||||||
|     HLE::Reschedule(__func__); |     HLE::Reschedule(__func__); | ||||||
| } | } | ||||||
|  | @ -416,6 +418,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | ||||||
| 
 | 
 | ||||||
|     ASSERT_MSG(thread->tls_index != -1, "Out of TLS space"); |     ASSERT_MSG(thread->tls_index != -1, "Out of TLS space"); | ||||||
|     g_current_process->misc_memory_used += Memory::TLS_ENTRY_SIZE; |     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
 |     // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
 | ||||||
|     // to initialize the context
 |     // to initialize the context
 | ||||||
|  |  | ||||||
|  | @ -778,6 +778,51 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 | ||||||
|     return RESULT_SUCCESS; |     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) { | static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | ||||||
|     LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, 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>,      "DuplicateHandle"}, |     {0x27, HLE::Wrap<DuplicateHandle>,      "DuplicateHandle"}, | ||||||
|     {0x28, HLE::Wrap<GetSystemTick>,        "GetSystemTick"}, |     {0x28, HLE::Wrap<GetSystemTick>,        "GetSystemTick"}, | ||||||
|     {0x29, nullptr,                         "GetHandleInfo"}, |     {0x29, nullptr,                         "GetHandleInfo"}, | ||||||
|     {0x2A, nullptr,                         "GetSystemInfo"}, |     {0x2A, HLE::Wrap<GetSystemInfo>,        "GetSystemInfo"}, | ||||||
|     {0x2B, HLE::Wrap<GetProcessInfo>,       "GetProcessInfo"}, |     {0x2B, HLE::Wrap<GetProcessInfo>,       "GetProcessInfo"}, | ||||||
|     {0x2C, nullptr,                         "GetThreadInfo"}, |     {0x2C, nullptr,                         "GetThreadInfo"}, | ||||||
|     {0x2D, HLE::Wrap<ConnectToPort>,        "ConnectToPort"}, |     {0x2D, HLE::Wrap<ConnectToPort>,        "ConnectToPort"}, | ||||||
|  |  | ||||||
|  | @ -41,6 +41,35 @@ enum ArbitrationType { | ||||||
| 
 | 
 | ||||||
| namespace SVC { | 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); | void CallSVC(u32 immediate); | ||||||
| 
 | 
 | ||||||
| } // namespace
 | } // namespace
 | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue