summaryrefslogtreecommitdiff
path: root/src/core/hle/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/svc.cpp')
-rw-r--r--src/core/hle/svc.cpp96
1 files changed, 31 insertions, 65 deletions
diff --git a/src/core/hle/svc.cpp b/src/core/hle/svc.cpp
index 8538cfc9d..30230d65a 100644
--- a/src/core/hle/svc.cpp
+++ b/src/core/hle/svc.cpp
@@ -14,6 +14,7 @@
14#include "core/hle/kernel/address_arbiter.h" 14#include "core/hle/kernel/address_arbiter.h"
15#include "core/hle/kernel/client_port.h" 15#include "core/hle/kernel/client_port.h"
16#include "core/hle/kernel/client_session.h" 16#include "core/hle/kernel/client_session.h"
17#include "core/hle/kernel/errors.h"
17#include "core/hle/kernel/event.h" 18#include "core/hle/kernel/event.h"
18#include "core/hle/kernel/memory.h" 19#include "core/hle/kernel/memory.h"
19#include "core/hle/kernel/mutex.h" 20#include "core/hle/kernel/mutex.h"
@@ -37,25 +38,6 @@ using Kernel::ERR_INVALID_HANDLE;
37 38
38namespace SVC { 39namespace SVC {
39 40
40const ResultCode ERR_NOT_FOUND(ErrorDescription::NotFound, ErrorModule::Kernel,
41 ErrorSummary::NotFound, ErrorLevel::Permanent); // 0xD88007FA
42const ResultCode ERR_PORT_NAME_TOO_LONG(ErrorDescription(30), ErrorModule::OS,
43 ErrorSummary::InvalidArgument,
44 ErrorLevel::Usage); // 0xE0E0181E
45
46const ResultCode ERR_SYNC_TIMEOUT(ErrorDescription::Timeout, ErrorModule::OS,
47 ErrorSummary::StatusChanged, ErrorLevel::Info);
48
49const ResultCode ERR_MISALIGNED_ADDRESS{// 0xE0E01BF1
50 ErrorDescription::MisalignedAddress, ErrorModule::OS,
51 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
52const ResultCode ERR_MISALIGNED_SIZE{// 0xE0E01BF2
53 ErrorDescription::MisalignedSize, ErrorModule::OS,
54 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
55const ResultCode ERR_INVALID_COMBINATION{// 0xE0E01BEE
56 ErrorDescription::InvalidCombination, ErrorModule::OS,
57 ErrorSummary::InvalidArgument, ErrorLevel::Usage};
58
59enum ControlMemoryOperation { 41enum ControlMemoryOperation {
60 MEMOP_FREE = 1, 42 MEMOP_FREE = 1,
61 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel 43 MEMOP_RESERVE = 2, // This operation seems to be unsupported in the kernel
@@ -195,8 +177,7 @@ static ResultCode MapMemoryBlock(Kernel::Handle handle, u32 addr, u32 permission
195 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions); 177 LOG_ERROR(Kernel_SVC, "unknown permissions=0x%08X", permissions);
196 } 178 }
197 179
198 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, 180 return Kernel::ERR_INVALID_COMBINATION;
199 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
200} 181}
201 182
202static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) { 183static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) {
@@ -216,16 +197,16 @@ static ResultCode UnmapMemoryBlock(Kernel::Handle handle, u32 addr) {
216/// Connect to an OS service given the port name, returns the handle to the port to out 197/// Connect to an OS service given the port name, returns the handle to the port to out
217static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) { 198static ResultCode ConnectToPort(Kernel::Handle* out_handle, const char* port_name) {
218 if (port_name == nullptr) 199 if (port_name == nullptr)
219 return ERR_NOT_FOUND; 200 return Kernel::ERR_NOT_FOUND;
220 if (std::strlen(port_name) > 11) 201 if (std::strlen(port_name) > 11)
221 return ERR_PORT_NAME_TOO_LONG; 202 return Kernel::ERR_PORT_NAME_TOO_LONG;
222 203
223 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name); 204 LOG_TRACE(Kernel_SVC, "called port_name=%s", port_name);
224 205
225 auto it = Service::g_kernel_named_ports.find(port_name); 206 auto it = Service::g_kernel_named_ports.find(port_name);
226 if (it == Service::g_kernel_named_ports.end()) { 207 if (it == Service::g_kernel_named_ports.end()) {
227 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name); 208 LOG_WARNING(Kernel_SVC, "tried to connect to unknown port: %s", port_name);
228 return ERR_NOT_FOUND; 209 return Kernel::ERR_NOT_FOUND;
229 } 210 }
230 211
231 auto client_port = it->second; 212 auto client_port = it->second;
@@ -275,7 +256,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
275 if (object->ShouldWait(thread)) { 256 if (object->ShouldWait(thread)) {
276 257
277 if (nano_seconds == 0) 258 if (nano_seconds == 0)
278 return ERR_SYNC_TIMEOUT; 259 return Kernel::RESULT_TIMEOUT;
279 260
280 thread->wait_objects = {object}; 261 thread->wait_objects = {object};
281 object->AddWaitingThread(thread); 262 object->AddWaitingThread(thread);
@@ -289,7 +270,7 @@ static ResultCode WaitSynchronization1(Kernel::Handle handle, s64 nano_seconds)
289 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread 270 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread
290 // resumes due to a signal in its wait objects. 271 // resumes due to a signal in its wait objects.
291 // Otherwise we retain the default value of timeout. 272 // Otherwise we retain the default value of timeout.
292 return ERR_SYNC_TIMEOUT; 273 return Kernel::RESULT_TIMEOUT;
293 } 274 }
294 275
295 object->Acquire(thread); 276 object->Acquire(thread);
@@ -304,8 +285,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
304 285
305 // Check if 'handles' is invalid 286 // Check if 'handles' is invalid
306 if (handles == nullptr) 287 if (handles == nullptr)
307 return ResultCode(ErrorDescription::InvalidPointer, ErrorModule::Kernel, 288 return Kernel::ERR_INVALID_POINTER;
308 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
309 289
310 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If 290 // NOTE: on real hardware, there is no nullptr check for 'out' (tested with firmware 4.4). If
311 // this happens, the running application will crash. 291 // this happens, the running application will crash.
@@ -313,8 +293,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
313 293
314 // Check if 'handle_count' is invalid 294 // Check if 'handle_count' is invalid
315 if (handle_count < 0) 295 if (handle_count < 0)
316 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, 296 return Kernel::ERR_OUT_OF_RANGE;
317 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
318 297
319 using ObjectPtr = Kernel::SharedPtr<Kernel::WaitObject>; 298 using ObjectPtr = Kernel::SharedPtr<Kernel::WaitObject>;
320 std::vector<ObjectPtr> objects(handle_count); 299 std::vector<ObjectPtr> objects(handle_count);
@@ -344,7 +323,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
344 // If a timeout value of 0 was provided, just return the Timeout error code instead of 323 // If a timeout value of 0 was provided, just return the Timeout error code instead of
345 // suspending the thread. 324 // suspending the thread.
346 if (nano_seconds == 0) 325 if (nano_seconds == 0)
347 return ERR_SYNC_TIMEOUT; 326 return Kernel::RESULT_TIMEOUT;
348 327
349 // Put the thread to sleep 328 // Put the thread to sleep
350 thread->status = THREADSTATUS_WAIT_SYNCH_ALL; 329 thread->status = THREADSTATUS_WAIT_SYNCH_ALL;
@@ -365,7 +344,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
365 *out = -1; 344 *out = -1;
366 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to 345 // Note: The output of this SVC will be set to RESULT_SUCCESS if the thread resumes due to
367 // a signal in one of its wait objects. 346 // a signal in one of its wait objects.
368 return ERR_SYNC_TIMEOUT; 347 return Kernel::RESULT_TIMEOUT;
369 } else { 348 } else {
370 // Find the first object that is acquirable in the provided list of objects 349 // Find the first object that is acquirable in the provided list of objects
371 auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) { 350 auto itr = std::find_if(objects.begin(), objects.end(), [thread](const ObjectPtr& object) {
@@ -385,7 +364,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
385 // If a timeout value of 0 was provided, just return the Timeout error code instead of 364 // If a timeout value of 0 was provided, just return the Timeout error code instead of
386 // suspending the thread. 365 // suspending the thread.
387 if (nano_seconds == 0) 366 if (nano_seconds == 0)
388 return ERR_SYNC_TIMEOUT; 367 return Kernel::RESULT_TIMEOUT;
389 368
390 // Put the thread to sleep 369 // Put the thread to sleep
391 thread->status = THREADSTATUS_WAIT_SYNCH_ANY; 370 thread->status = THREADSTATUS_WAIT_SYNCH_ANY;
@@ -411,7 +390,7 @@ static ResultCode WaitSynchronizationN(s32* out, Kernel::Handle* handles, s32 ha
411 // Otherwise we retain the default value of timeout, and -1 in the out parameter 390 // Otherwise we retain the default value of timeout, and -1 in the out parameter
412 thread->wait_set_output = true; 391 thread->wait_set_output = true;
413 *out = -1; 392 *out = -1;
414 return ERR_SYNC_TIMEOUT; 393 return Kernel::RESULT_TIMEOUT;
415 } 394 }
416} 395}
417 396
@@ -520,22 +499,20 @@ static ResultCode GetResourceLimitLimitValues(s64* values, Kernel::Handle resour
520} 499}
521 500
522/// Creates a new thread 501/// Creates a new thread
523static ResultCode CreateThread(Kernel::Handle* out_handle, s32 priority, u32 entry_point, u32 arg, 502static ResultCode CreateThread(Kernel::Handle* out_handle, u32 priority, u32 entry_point, u32 arg,
524 u32 stack_top, s32 processor_id) { 503 u32 stack_top, s32 processor_id) {
525 using Kernel::Thread; 504 using Kernel::Thread;
526 505
527 std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point); 506 std::string name = Common::StringFromFormat("unknown-%08" PRIX32, entry_point);
528 507
529 if (priority > THREADPRIO_LOWEST) { 508 if (priority > THREADPRIO_LOWEST) {
530 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, 509 return Kernel::ERR_OUT_OF_RANGE;
531 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
532 } 510 }
533 511
534 using Kernel::ResourceLimit; 512 using Kernel::ResourceLimit;
535 Kernel::SharedPtr<ResourceLimit>& resource_limit = Kernel::g_current_process->resource_limit; 513 Kernel::SharedPtr<ResourceLimit>& resource_limit = Kernel::g_current_process->resource_limit;
536 if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) { 514 if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) {
537 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::OS, 515 return Kernel::ERR_NOT_AUTHORIZED;
538 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
539 } 516 }
540 517
541 switch (processor_id) { 518 switch (processor_id) {
@@ -605,8 +582,7 @@ static ResultCode GetThreadPriority(s32* priority, Kernel::Handle handle) {
605/// Sets the priority for the specified thread 582/// Sets the priority for the specified thread
606static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) { 583static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) {
607 if (priority > THREADPRIO_LOWEST) { 584 if (priority > THREADPRIO_LOWEST) {
608 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::OS, 585 return Kernel::ERR_OUT_OF_RANGE;
609 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
610 } 586 }
611 587
612 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle); 588 SharedPtr<Kernel::Thread> thread = Kernel::g_handle_table.Get<Kernel::Thread>(handle);
@@ -618,8 +594,7 @@ static ResultCode SetThreadPriority(Kernel::Handle handle, s32 priority) {
618 // the one from the thread owner's resource limit. 594 // the one from the thread owner's resource limit.
619 Kernel::SharedPtr<ResourceLimit>& resource_limit = Kernel::g_current_process->resource_limit; 595 Kernel::SharedPtr<ResourceLimit>& resource_limit = Kernel::g_current_process->resource_limit;
620 if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) { 596 if (resource_limit->GetMaxResourceValue(Kernel::ResourceTypes::PRIORITY) > priority) {
621 return ResultCode(ErrorDescription::NotAuthorized, ErrorModule::OS, 597 return Kernel::ERR_NOT_AUTHORIZED;
622 ErrorSummary::WrongArgument, ErrorLevel::Permanent);
623 } 598 }
624 599
625 thread->SetPriority(priority); 600 thread->SetPriority(priority);
@@ -743,8 +718,7 @@ static ResultCode QueryProcessMemory(MemoryInfo* memory_info, PageInfo* page_inf
743 auto vma = process->vm_manager.FindVMA(addr); 718 auto vma = process->vm_manager.FindVMA(addr);
744 719
745 if (vma == Kernel::g_current_process->vm_manager.vma_map.end()) 720 if (vma == Kernel::g_current_process->vm_manager.vma_map.end())
746 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, 721 return Kernel::ERR_INVALID_ADDRESS;
747 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
748 722
749 memory_info->base_address = vma->second.base; 723 memory_info->base_address = vma->second.base;
750 memory_info->permission = static_cast<u32>(vma->second.permissions); 724 memory_info->permission = static_cast<u32>(vma->second.permissions);
@@ -842,8 +816,7 @@ static ResultCode SetTimer(Kernel::Handle handle, s64 initial, s64 interval) {
842 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle); 816 LOG_TRACE(Kernel_SVC, "called timer=0x%08X", handle);
843 817
844 if (initial < 0 || interval < 0) { 818 if (initial < 0 || interval < 0) {
845 return ResultCode(ErrorDescription::OutOfRange, ErrorModule::Kernel, 819 return Kernel::ERR_OUT_OF_RANGE_KERNEL;
846 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
847 } 820 }
848 821
849 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle); 822 SharedPtr<Timer> timer = Kernel::g_handle_table.Get<Timer>(handle);
@@ -902,8 +875,7 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si
902 using Kernel::SharedMemory; 875 using Kernel::SharedMemory;
903 876
904 if (size % Memory::PAGE_SIZE != 0) 877 if (size % Memory::PAGE_SIZE != 0)
905 return ResultCode(ErrorDescription::MisalignedSize, ErrorModule::OS, 878 return Kernel::ERR_MISALIGNED_SIZE;
906 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
907 879
908 SharedPtr<SharedMemory> shared_memory = nullptr; 880 SharedPtr<SharedMemory> shared_memory = nullptr;
909 881
@@ -924,16 +896,14 @@ static ResultCode CreateMemoryBlock(Kernel::Handle* out_handle, u32 addr, u32 si
924 896
925 if (!VerifyPermissions(static_cast<MemoryPermission>(my_permission)) || 897 if (!VerifyPermissions(static_cast<MemoryPermission>(my_permission)) ||
926 !VerifyPermissions(static_cast<MemoryPermission>(other_permission))) 898 !VerifyPermissions(static_cast<MemoryPermission>(other_permission)))
927 return ResultCode(ErrorDescription::InvalidCombination, ErrorModule::OS, 899 return Kernel::ERR_INVALID_COMBINATION;
928 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
929 900
930 // TODO(Subv): Processes with memory type APPLICATION are not allowed 901 // TODO(Subv): Processes with memory type APPLICATION are not allowed
931 // to create memory blocks with addr = 0, any attempts to do so 902 // to create memory blocks with addr = 0, any attempts to do so
932 // should return error 0xD92007EA. 903 // should return error 0xD92007EA.
933 if ((addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) && 904 if ((addr < Memory::PROCESS_IMAGE_VADDR || addr + size > Memory::SHARED_MEMORY_VADDR_END) &&
934 addr != 0) { 905 addr != 0) {
935 return ResultCode(ErrorDescription::InvalidAddress, ErrorModule::OS, 906 return Kernel::ERR_INVALID_ADDRESS;
936 ErrorSummary::InvalidArgument, ErrorLevel::Usage);
937 } 907 }
938 908
939 // When trying to create a memory block with address = 0, 909 // When trying to create a memory block with address = 0,
@@ -1035,7 +1005,7 @@ static ResultCode GetProcessInfo(s64* out, Kernel::Handle process_handle, u32 ty
1035 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used; 1005 *out = process->heap_used + process->linear_heap_used + process->misc_memory_used;
1036 if (*out % Memory::PAGE_SIZE != 0) { 1006 if (*out % Memory::PAGE_SIZE != 0) {
1037 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned"); 1007 LOG_ERROR(Kernel_SVC, "called, memory size not page-aligned");
1038 return ERR_MISALIGNED_SIZE; 1008 return Kernel::ERR_MISALIGNED_SIZE;
1039 } 1009 }
1040 break; 1010 break;
1041 case 1: 1011 case 1:
@@ -1051,19 +1021,15 @@ static ResultCode GetProcessInfo(s64* out, Kernel::Handle process_handle, u32 ty
1051 case 20: 1021 case 20:
1052 *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase(); 1022 *out = Memory::FCRAM_PADDR - process->GetLinearHeapBase();
1053 break; 1023 break;
1024 case 21:
1025 case 22:
1026 case 23:
1027 // These return a different error value than higher invalid values
1028 LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type);
1029 return Kernel::ERR_NOT_IMPLEMENTED;
1054 default: 1030 default:
1055 LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type); 1031 LOG_ERROR(Kernel_SVC, "unknown GetProcessInfo type=%u", type);
1056 1032 return Kernel::ERR_INVALID_ENUM_VALUE;
1057 if (type >= 21 && type <= 23) {
1058 return ResultCode( // 0xE0E01BF4
1059 ErrorDescription::NotImplemented, ErrorModule::OS, ErrorSummary::InvalidArgument,
1060 ErrorLevel::Usage);
1061 } else {
1062 return ResultCode( // 0xD8E007ED
1063 ErrorDescription::InvalidEnumValue, ErrorModule::Kernel,
1064 ErrorSummary::InvalidArgument, ErrorLevel::Permanent);
1065 }
1066 break;
1067 } 1033 }
1068 1034
1069 return RESULT_SUCCESS; 1035 return RESULT_SUCCESS;