Răsfoiți Sursa

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 ani în urmă
părinte
comite
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,