فهرست منبع

Kernel: Implement svcGetProcessInfo in a basic way

This also adds some basic memory usage accounting. These two types are
used by Super Smash Bros. during startup.
Yuri Kunde Schlesner 11 سال پیش
والد
کامیت
14eca982f4

+ 8 - 0
src/core/hle/function_wrappers.h

@@ -172,6 +172,14 @@ template<ResultCode func(u32, s64, s64)> void Wrap() {
     FuncReturn(func(PARAM(0), param1, param2).raw);
 }
 
+template<ResultCode func(s64*, Handle, u32)> void Wrap() {
+    s64 param_1 = 0;
+    u32 retval = func(&param_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);
+}
+
 ////////////////////////////////////////////////////////////////////////////////////////////////////
 // Function wrappers that return type u32
 

+ 10 - 0
src/core/hle/kernel/process.cpp

@@ -110,6 +110,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
         auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory,
                 segment.offset, segment.size, memory_state).Unwrap();
         vm_manager.Reprotect(vma, permissions);
+        misc_memory_used += segment.size;
     };
 
     // Map CodeSet segments
@@ -121,6 +122,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) {
     vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size,
             std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked
             ).Unwrap();
+    misc_memory_used += stack_size;
 
     vm_manager.LogLayout(Log::Level::Debug);
     Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority);
@@ -162,6 +164,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per
     CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private));
     vm_manager.Reprotect(vma, perms);
 
+    heap_used += size;
+
     return MakeResult<VAddr>(heap_end - size);
 }
 
@@ -173,6 +177,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) {
     ResultCode result = vm_manager.UnmapRange(target, size);
     if (result.IsError()) return result;
 
+    heap_used -= size;
+
     return RESULT_SUCCESS;
 }
 
@@ -206,6 +212,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p
     CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous));
     vm_manager.Reprotect(vma, perms);
 
+    linear_heap_used += size;
+
     return MakeResult<VAddr>(target);
 }
 
@@ -226,6 +234,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) {
     ResultCode result = vm_manager.UnmapRange(target, size);
     if (result.IsError()) return result;
 
+    linear_heap_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
         // reduce the size.

+ 2 - 0
src/core/hle/kernel/process.h

@@ -136,6 +136,8 @@ public:
     // The left/right bounds of the address space covered by heap_memory.
     VAddr heap_start = 0, heap_end = 0;
 
+    u32 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0;
+
     MemoryRegionInfo* memory_region = nullptr;
 
     /// Bitmask of the used TLS slots

+ 3 - 1
src/core/hle/kernel/thread.cpp

@@ -117,6 +117,7 @@ void Thread::Stop() {
     wait_objects.clear();
 
     Kernel::g_current_process->used_tls_slots[tls_index] = false;
+    g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE;
 
     HLE::Reschedule(__func__);
 }
@@ -414,6 +415,7 @@ ResultVal<SharedPtr<Thread>> 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;
 
     // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used
     // to initialize the context
@@ -504,7 +506,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) {
 }
 
 VAddr Thread::GetTLSAddress() const {
-    return Memory::TLS_AREA_VADDR + tls_index * 0x200;
+    return Memory::TLS_AREA_VADDR + tls_index * Memory::TLS_ENTRY_SIZE;
 }
 
 ////////////////////////////////////////////////////////////////////////////////////////////////////

+ 47 - 1
src/core/hle/svc.cpp

@@ -774,6 +774,52 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32
     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);
+
+    using Kernel::Process;
+    Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle);
+    if (process == nullptr)
+        return ERR_INVALID_HANDLE;
+
+    switch (type) {
+    case 0:
+    case 2:
+        // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure
+        // what's the difference between them.
+        *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
+        break;
+    case 1:
+    case 3:
+    case 4:
+    case 5:
+    case 6:
+    case 7:
+    case 8:
+        // These are valid, but not implemented yet
+        LOG_ERROR(Kernel_SVC, "unimplemented GetProcessInfo type=%u", type);
+        break;
+    case 20:
+        *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase();
+        break;
+    default:
+        LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type);
+
+        if (type >= 21 && type <= 23) {
+            return ResultCode( // 0xE0E01BF4
+                    ErrorDescription::NotImplemented, ErrorModule::OS,
+                    ErrorSummary::InvalidArgument, ErrorLevel::Usage);
+        } else {
+            return ResultCode( // 0xD8E007ED
+                    ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
+                    ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
+        }
+        break;
+    }
+
+    return RESULT_SUCCESS;
+}
+
 namespace {
     struct FunctionDef {
         using Func = void();
@@ -828,7 +874,7 @@ static const FunctionDef SVC_Table[] = {
     {0x28, HLE::Wrap<GetSystemTick>,        "GetSystemTick"},
     {0x29, nullptr,                         "GetHandleInfo"},
     {0x2A, nullptr,                         "GetSystemInfo"},
-    {0x2B, nullptr,                         "GetProcessInfo"},
+    {0x2B, HLE::Wrap<GetProcessInfo>,       "GetProcessInfo"},
     {0x2C, nullptr,                         "GetThreadInfo"},
     {0x2D, HLE::Wrap<ConnectToPort>,        "ConnectToPort"},
     {0x2E, nullptr,                         "SendSyncRequest1"},

+ 3 - 1
src/core/memory.h

@@ -105,9 +105,11 @@ enum : VAddr {
     // hardcoded value.
     /// Area where TLS (Thread-Local Storage) buffers are allocated.
     TLS_AREA_VADDR     = 0x1FF82000,
-    TLS_AREA_SIZE      = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads
+    TLS_ENTRY_SIZE     = 0x200,
+    TLS_AREA_SIZE      = 300 * TLS_ENTRY_SIZE, // Allows for up to 300 threads
     TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE,
 
+
     /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS.
     NEW_LINEAR_HEAP_VADDR     = 0x30000000,
     NEW_LINEAR_HEAP_SIZE      = 0x10000000,