diff options
| author | 2015-08-05 21:39:53 -0300 | |
|---|---|---|
| committer | 2015-08-16 01:03:48 -0300 | |
| commit | 14eca982f4da2bfd4d2c105bc33722e88e59da5f (patch) | |
| tree | d812de676c6e2d056ac43abec89251aa36162165 /src | |
| parent | Kernel: Add more infrastructure to support different memory layouts (diff) | |
| download | yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.gz yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.tar.xz yuzu-14eca982f4da2bfd4d2c105bc33722e88e59da5f.zip | |
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.
Diffstat (limited to 'src')
| -rw-r--r-- | src/core/hle/function_wrappers.h | 8 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 10 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.h | 2 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/svc.cpp | 48 | ||||
| -rw-r--r-- | src/core/memory.h | 4 |
6 files changed, 73 insertions, 3 deletions
diff --git a/src/core/hle/function_wrappers.h b/src/core/hle/function_wrappers.h index 1a0518926..5846a161b 100644 --- a/src/core/hle/function_wrappers.h +++ b/src/core/hle/function_wrappers.h | |||
| @@ -172,6 +172,14 @@ template<ResultCode func(u32, s64, s64)> void Wrap() { | |||
| 172 | FuncReturn(func(PARAM(0), param1, param2).raw); | 172 | FuncReturn(func(PARAM(0), param1, param2).raw); |
| 173 | } | 173 | } |
| 174 | 174 | ||
| 175 | template<ResultCode func(s64*, Handle, u32)> void Wrap() { | ||
| 176 | s64 param_1 = 0; | ||
| 177 | u32 retval = func(¶m_1, PARAM(1), PARAM(2)).raw; | ||
| 178 | Core::g_app_core->SetReg(1, (u32)param_1); | ||
| 179 | Core::g_app_core->SetReg(2, (u32)(param_1 >> 32)); | ||
| 180 | FuncReturn(retval); | ||
| 181 | } | ||
| 182 | |||
| 175 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 183 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
| 176 | // Function wrappers that return type u32 | 184 | // Function wrappers that return type u32 |
| 177 | 185 | ||
diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 1f45e6cf8..124047a53 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp | |||
| @@ -110,6 +110,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | |||
| 110 | auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, | 110 | auto vma = vm_manager.MapMemoryBlock(segment.addr, codeset->memory, |
| 111 | segment.offset, segment.size, memory_state).Unwrap(); | 111 | segment.offset, segment.size, memory_state).Unwrap(); |
| 112 | vm_manager.Reprotect(vma, permissions); | 112 | vm_manager.Reprotect(vma, permissions); |
| 113 | misc_memory_used += segment.size; | ||
| 113 | }; | 114 | }; |
| 114 | 115 | ||
| 115 | // Map CodeSet segments | 116 | // Map CodeSet segments |
| @@ -121,6 +122,7 @@ void Process::Run(s32 main_thread_priority, u32 stack_size) { | |||
| 121 | vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, | 122 | vm_manager.MapMemoryBlock(Memory::HEAP_VADDR_END - stack_size, |
| 122 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked | 123 | std::make_shared<std::vector<u8>>(stack_size, 0), 0, stack_size, MemoryState::Locked |
| 123 | ).Unwrap(); | 124 | ).Unwrap(); |
| 125 | misc_memory_used += stack_size; | ||
| 124 | 126 | ||
| 125 | vm_manager.LogLayout(Log::Level::Debug); | 127 | vm_manager.LogLayout(Log::Level::Debug); |
| 126 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); | 128 | Kernel::SetupMainThread(codeset->entrypoint, main_thread_priority); |
| @@ -162,6 +164,8 @@ ResultVal<VAddr> Process::HeapAllocate(VAddr target, u32 size, VMAPermission per | |||
| 162 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); | 164 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, heap_memory, target - heap_start, size, MemoryState::Private)); |
| 163 | vm_manager.Reprotect(vma, perms); | 165 | vm_manager.Reprotect(vma, perms); |
| 164 | 166 | ||
| 167 | heap_used += size; | ||
| 168 | |||
| 165 | return MakeResult<VAddr>(heap_end - size); | 169 | return MakeResult<VAddr>(heap_end - size); |
| 166 | } | 170 | } |
| 167 | 171 | ||
| @@ -173,6 +177,8 @@ ResultCode Process::HeapFree(VAddr target, u32 size) { | |||
| 173 | ResultCode result = vm_manager.UnmapRange(target, size); | 177 | ResultCode result = vm_manager.UnmapRange(target, size); |
| 174 | if (result.IsError()) return result; | 178 | if (result.IsError()) return result; |
| 175 | 179 | ||
| 180 | heap_used -= size; | ||
| 181 | |||
| 176 | return RESULT_SUCCESS; | 182 | return RESULT_SUCCESS; |
| 177 | } | 183 | } |
| 178 | 184 | ||
| @@ -206,6 +212,8 @@ ResultVal<VAddr> Process::LinearAllocate(VAddr target, u32 size, VMAPermission p | |||
| 206 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); | 212 | CASCADE_RESULT(auto vma, vm_manager.MapMemoryBlock(target, linheap_memory, offset, size, MemoryState::Continuous)); |
| 207 | vm_manager.Reprotect(vma, perms); | 213 | vm_manager.Reprotect(vma, perms); |
| 208 | 214 | ||
| 215 | linear_heap_used += size; | ||
| 216 | |||
| 209 | return MakeResult<VAddr>(target); | 217 | return MakeResult<VAddr>(target); |
| 210 | } | 218 | } |
| 211 | 219 | ||
| @@ -226,6 +234,8 @@ ResultCode Process::LinearFree(VAddr target, u32 size) { | |||
| 226 | ResultCode result = vm_manager.UnmapRange(target, size); | 234 | ResultCode result = vm_manager.UnmapRange(target, size); |
| 227 | if (result.IsError()) return result; | 235 | if (result.IsError()) return result; |
| 228 | 236 | ||
| 237 | linear_heap_used -= size; | ||
| 238 | |||
| 229 | if (target + size == heap_end) { | 239 | if (target + size == heap_end) { |
| 230 | // End of linear heap has been freed, so check what's the last allocated block in it and | 240 | // End of linear heap has been freed, so check what's the last allocated block in it and |
| 231 | // reduce the size. | 241 | // reduce the size. |
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h index 7c3a78b9e..60e17f251 100644 --- a/src/core/hle/kernel/process.h +++ b/src/core/hle/kernel/process.h | |||
| @@ -136,6 +136,8 @@ public: | |||
| 136 | // The left/right bounds of the address space covered by heap_memory. | 136 | // The left/right bounds of the address space covered by heap_memory. |
| 137 | VAddr heap_start = 0, heap_end = 0; | 137 | VAddr heap_start = 0, heap_end = 0; |
| 138 | 138 | ||
| 139 | u32 heap_used = 0, linear_heap_used = 0, misc_memory_used = 0; | ||
| 140 | |||
| 139 | MemoryRegionInfo* memory_region = nullptr; | 141 | MemoryRegionInfo* memory_region = nullptr; |
| 140 | 142 | ||
| 141 | /// Bitmask of the used TLS slots | 143 | /// Bitmask of the used TLS slots |
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index 29ea6d531..c10126513 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp | |||
| @@ -117,6 +117,7 @@ void Thread::Stop() { | |||
| 117 | wait_objects.clear(); | 117 | wait_objects.clear(); |
| 118 | 118 | ||
| 119 | Kernel::g_current_process->used_tls_slots[tls_index] = false; | 119 | Kernel::g_current_process->used_tls_slots[tls_index] = false; |
| 120 | g_current_process->misc_memory_used -= Memory::TLS_ENTRY_SIZE; | ||
| 120 | 121 | ||
| 121 | HLE::Reschedule(__func__); | 122 | HLE::Reschedule(__func__); |
| 122 | } | 123 | } |
| @@ -414,6 +415,7 @@ ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, | |||
| 414 | } | 415 | } |
| 415 | 416 | ||
| 416 | ASSERT_MSG(thread->tls_index != -1, "Out of TLS space"); | 417 | ASSERT_MSG(thread->tls_index != -1, "Out of TLS space"); |
| 418 | g_current_process->misc_memory_used += Memory::TLS_ENTRY_SIZE; | ||
| 417 | 419 | ||
| 418 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used | 420 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used |
| 419 | // to initialize the context | 421 | // to initialize the context |
| @@ -504,7 +506,7 @@ void Thread::SetWaitSynchronizationOutput(s32 output) { | |||
| 504 | } | 506 | } |
| 505 | 507 | ||
| 506 | VAddr Thread::GetTLSAddress() const { | 508 | VAddr Thread::GetTLSAddress() const { |
| 507 | return Memory::TLS_AREA_VADDR + tls_index * 0x200; | 509 | return Memory::TLS_AREA_VADDR + tls_index * Memory::TLS_ENTRY_SIZE; |
| 508 | } | 510 | } |
| 509 | 511 | ||
| 510 | //////////////////////////////////////////////////////////////////////////////////////////////////// | 512 | //////////////////////////////////////////////////////////////////////////////////////////////////// |
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp index e1a416def..89ac45a6f 100644 --- a/src/core/hle/svc.cpp +++ b/src/core/hle/svc.cpp | |||
| @@ -774,6 +774,52 @@ static ResultCode CreateMemoryBlock(Handle* out_handle, u32 addr, u32 size, u32 | |||
| 774 | return RESULT_SUCCESS; | 774 | return RESULT_SUCCESS; |
| 775 | } | 775 | } |
| 776 | 776 | ||
| 777 | static ResultCode GetProcessInfo(s64* out, Handle process_handle, u32 type) { | ||
| 778 | LOG_TRACE(Kernel_SVC, "called process=0x%08X type=%u", process_handle, type); | ||
| 779 | |||
| 780 | using Kernel::Process; | ||
| 781 | Kernel::SharedPtr<Process> process = Kernel::g_handle_table.Get<Process>(process_handle); | ||
| 782 | if (process == nullptr) | ||
| 783 | return ERR_INVALID_HANDLE; | ||
| 784 | |||
| 785 | switch (type) { | ||
| 786 | case 0: | ||
| 787 | case 2: | ||
| 788 | // TODO(yuriks): Type 0 returns a slightly higher number than type 2, but I'm not sure | ||
| 789 | // what's the difference between them. | ||
| 790 | *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; | ||
| 791 | break; | ||
| 792 | case 1: | ||
| 793 | case 3: | ||
| 794 | case 4: | ||
| 795 | case 5: | ||
| 796 | case 6: | ||
| 797 | case 7: | ||
| 798 | case 8: | ||
| 799 | // These are valid, but not implemented yet | ||
| 800 | LOG_ERROR(Kernel_SVC, "unimplemented GetProcessInfo type=%u", type); | ||
| 801 | break; | ||
| 802 | case 20: | ||
| 803 | *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase(); | ||
| 804 | break; | ||
| 805 | default: | ||
| 806 | LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type); | ||
| 807 | |||
| 808 | if (type >= 21 && type <= 23) { | ||
| 809 | return ResultCode( // 0xE0E01BF4 | ||
| 810 | ErrorDescription::NotImplemented, ErrorModule::OS, | ||
| 811 | ErrorSummary::InvalidArgument, ErrorLevel::Usage); | ||
| 812 | } else { | ||
| 813 | return ResultCode( // 0xD8E007ED | ||
| 814 | ErrorDescription::InvalidEnumValue, ErrorModule::Kernel, | ||
| 815 | ErrorSummary::InvalidArgument, ErrorLevel::Permanent); | ||
| 816 | } | ||
| 817 | break; | ||
| 818 | } | ||
| 819 | |||
| 820 | return RESULT_SUCCESS; | ||
| 821 | } | ||
| 822 | |||
| 777 | namespace { | 823 | namespace { |
| 778 | struct FunctionDef { | 824 | struct FunctionDef { |
| 779 | using Func = void(); | 825 | using Func = void(); |
| @@ -828,7 +874,7 @@ static const FunctionDef SVC_Table[] = { | |||
| 828 | {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, | 874 | {0x28, HLE::Wrap<GetSystemTick>, "GetSystemTick"}, |
| 829 | {0x29, nullptr, "GetHandleInfo"}, | 875 | {0x29, nullptr, "GetHandleInfo"}, |
| 830 | {0x2A, nullptr, "GetSystemInfo"}, | 876 | {0x2A, nullptr, "GetSystemInfo"}, |
| 831 | {0x2B, nullptr, "GetProcessInfo"}, | 877 | {0x2B, HLE::Wrap<GetProcessInfo>, "GetProcessInfo"}, |
| 832 | {0x2C, nullptr, "GetThreadInfo"}, | 878 | {0x2C, nullptr, "GetThreadInfo"}, |
| 833 | {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, | 879 | {0x2D, HLE::Wrap<ConnectToPort>, "ConnectToPort"}, |
| 834 | {0x2E, nullptr, "SendSyncRequest1"}, | 880 | {0x2E, nullptr, "SendSyncRequest1"}, |
diff --git a/src/core/memory.h b/src/core/memory.h index d1d32f0dd..c136cbd55 100644 --- a/src/core/memory.h +++ b/src/core/memory.h | |||
| @@ -105,9 +105,11 @@ enum : VAddr { | |||
| 105 | // hardcoded value. | 105 | // hardcoded value. |
| 106 | /// Area where TLS (Thread-Local Storage) buffers are allocated. | 106 | /// Area where TLS (Thread-Local Storage) buffers are allocated. |
| 107 | TLS_AREA_VADDR = 0x1FF82000, | 107 | TLS_AREA_VADDR = 0x1FF82000, |
| 108 | TLS_AREA_SIZE = 0x00030000, // Each TLS buffer is 0x200 bytes, allows for 300 threads | 108 | TLS_ENTRY_SIZE = 0x200, |
| 109 | TLS_AREA_SIZE = 300 * TLS_ENTRY_SIZE, // Allows for up to 300 threads | ||
| 109 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, | 110 | TLS_AREA_VADDR_END = TLS_AREA_VADDR + TLS_AREA_SIZE, |
| 110 | 111 | ||
| 112 | |||
| 111 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. | 113 | /// Equivalent to LINEAR_HEAP_VADDR, but expanded to cover the extra memory in the New 3DS. |
| 112 | NEW_LINEAR_HEAP_VADDR = 0x30000000, | 114 | NEW_LINEAR_HEAP_VADDR = 0x30000000, |
| 113 | NEW_LINEAR_HEAP_SIZE = 0x10000000, | 115 | NEW_LINEAR_HEAP_SIZE = 0x10000000, |