summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorGravatar Yuri Kunde Schlesner2015-08-05 21:39:53 -0300
committerGravatar Yuri Kunde Schlesner2015-08-16 01:03:48 -0300
commit14eca982f4da2bfd4d2c105bc33722e88e59da5f (patch)
treed812de676c6e2d056ac43abec89251aa36162165 /src
parentKernel: Add more infrastructure to support different memory layouts (diff)
downloadyuzu-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.h8
-rw-r--r--src/core/hle/kernel/process.cpp10
-rw-r--r--src/core/hle/kernel/process.h2
-rw-r--r--src/core/hle/kernel/thread.cpp4
-rw-r--r--src/core/hle/svc.cpp48
-rw-r--r--src/core/memory.h4
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
175template<ResultCode func(s64*, Handle, u32)> void Wrap() {
176 s64 param_1 = 0;
177 u32 retval = func(&param_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
506VAddr Thread::GetTLSAddress() const { 508VAddr 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
777static 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
777namespace { 823namespace {
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,