Kernel: Implement svcGetSystemInfo
This makes smealum/ctrulib@b96dd51d33 work with Citra.
This commit is contained in:
parent
32f92b4a69
commit
84a22cb594
@ -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…
Reference in New Issue
Block a user