summaryrefslogtreecommitdiff
path: root/src/core/hle/kernel/svc.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/core/hle/kernel/svc.cpp')
-rw-r--r--src/core/hle/kernel/svc.cpp268
1 files changed, 68 insertions, 200 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 395962885..813450115 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -355,7 +355,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
355 KScopedSchedulerLock lock(kernel); 355 KScopedSchedulerLock lock(kernel);
356 thread->SetState(ThreadState::Waiting); 356 thread->SetState(ThreadState::Waiting);
357 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC); 357 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
358 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 358 session->SendSyncRequest(thread, system.Memory(), system.CoreTiming());
359 } 359 }
360 360
361 KSynchronizationObject* dummy{}; 361 KSynchronizationObject* dummy{};
@@ -368,18 +368,13 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
368 368
369/// Get the ID for the specified thread. 369/// Get the ID for the specified thread.
370static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) { 370static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
371 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
372
373 // Get the thread from its handle. 371 // Get the thread from its handle.
374 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 372 KScopedAutoObject thread =
375 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 373 system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
376 if (!thread) { 374 R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
377 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
378 return ResultInvalidHandle;
379 }
380 375
381 // Get the thread's id. 376 // Get the thread's id.
382 *out_thread_id = thread->GetThreadID(); 377 *out_thread_id = thread->GetId();
383 return RESULT_SUCCESS; 378 return RESULT_SUCCESS;
384} 379}
385 380
@@ -396,30 +391,7 @@ static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
396 391
397/// Gets the ID of the specified process or a specified thread's owning process. 392/// Gets the ID of the specified process or a specified thread's owning process.
398static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) { 393static ResultCode GetProcessId(Core::System& system, u64* process_id, Handle handle) {
399 LOG_DEBUG(Kernel_SVC, "called handle=0x{:08X}", handle); 394 __debugbreak();
400
401 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
402 const std::shared_ptr<Process> process = handle_table.Get<Process>(handle);
403 if (process) {
404 *process_id = process->GetProcessID();
405 return RESULT_SUCCESS;
406 }
407
408 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
409 if (thread) {
410 const Process* const owner_process = thread->GetOwnerProcess();
411 if (!owner_process) {
412 LOG_ERROR(Kernel_SVC, "Non-existent owning process encountered.");
413 return ResultInvalidHandle;
414 }
415
416 *process_id = owner_process->GetProcessID();
417 return RESULT_SUCCESS;
418 }
419
420 // NOTE: This should also handle debug objects before returning.
421
422 LOG_ERROR(Kernel_SVC, "Handle does not exist, handle=0x{:08X}", handle);
423 return ResultInvalidHandle; 395 return ResultInvalidHandle;
424} 396}
425 397
@@ -460,14 +432,30 @@ static ResultCode WaitSynchronization(Core::System& system, s32* index, VAddr ha
460 432
461 for (u64 i = 0; i < handle_count; ++i) { 433 for (u64 i = 0; i < handle_count; ++i) {
462 const Handle handle = memory.Read32(handles_address + i * sizeof(Handle)); 434 const Handle handle = memory.Read32(handles_address + i * sizeof(Handle));
463 const auto object = handle_table.Get<KSynchronizationObject>(handle);
464 435
465 if (object == nullptr) { 436 bool succeeded{};
466 LOG_ERROR(Kernel_SVC, "Object is a nullptr"); 437 {
467 return ResultInvalidHandle; 438 auto object = handle_table.Get<KSynchronizationObject>(handle);
439 if (object) {
440 objects[i] = object.get();
441 succeeded = true;
442 }
468 } 443 }
469 444
470 objects[i] = object.get(); 445 // TODO(bunnei): WORKAROUND WHILE WE HAVE TWO HANDLE TABLES
446 if (!succeeded) {
447 {
448 auto object = handle_table.GetObject<KSynchronizationObject>(handle);
449
450 if (object.IsNull()) {
451 LOG_ERROR(Kernel_SVC, "Object is a nullptr");
452 return ResultInvalidHandle;
453 }
454
455 objects[i] = object.GetPointerUnsafe();
456 succeeded = true;
457 }
458 }
471 } 459 }
472 return KSynchronizationObject::Wait(kernel, index, objects.data(), 460 return KSynchronizationObject::Wait(kernel, index, objects.data(),
473 static_cast<s32>(objects.size()), nano_seconds); 461 static_cast<s32>(objects.size()), nano_seconds);
@@ -481,19 +469,7 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u
481 469
482/// Resumes a thread waiting on WaitSynchronization 470/// Resumes a thread waiting on WaitSynchronization
483static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { 471static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
484 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 472 __debugbreak();
485
486 // Get the thread from its handle.
487 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
488 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
489
490 if (!thread) {
491 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
492 return ResultInvalidHandle;
493 }
494
495 // Cancel the thread's wait.
496 thread->WaitCancel();
497 return RESULT_SUCCESS; 473 return RESULT_SUCCESS;
498} 474}
499 475
@@ -899,9 +875,10 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
899 return ResultInvalidCombination; 875 return ResultInvalidCombination;
900 } 876 }
901 877
902 const auto thread = system.Kernel().CurrentProcess()->GetHandleTable().Get<KThread>( 878 KScopedAutoObject thread =
903 static_cast<Handle>(handle)); 879 system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(
904 if (!thread) { 880 static_cast<Handle>(handle));
881 if (thread.IsNull()) {
905 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", 882 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}",
906 static_cast<Handle>(handle)); 883 static_cast<Handle>(handle));
907 return ResultInvalidHandle; 884 return ResultInvalidHandle;
@@ -910,7 +887,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
910 const auto& core_timing = system.CoreTiming(); 887 const auto& core_timing = system.CoreTiming();
911 const auto& scheduler = *system.Kernel().CurrentScheduler(); 888 const auto& scheduler = *system.Kernel().CurrentScheduler();
912 const auto* const current_thread = scheduler.GetCurrentThread(); 889 const auto* const current_thread = scheduler.GetCurrentThread();
913 const bool same_thread = current_thread == thread.get(); 890 const bool same_thread = current_thread == thread.GetPointerUnsafe();
914 891
915 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); 892 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
916 u64 out_ticks = 0; 893 u64 out_ticks = 0;
@@ -1055,45 +1032,7 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
1055/// Sets the thread activity 1032/// Sets the thread activity
1056static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, 1033static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1057 ThreadActivity thread_activity) { 1034 ThreadActivity thread_activity) {
1058 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, 1035 __debugbreak();
1059 thread_activity);
1060
1061 // Validate the activity.
1062 constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
1063 return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
1064 };
1065 if (!IsValidThreadActivity(thread_activity)) {
1066 LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
1067 thread_activity);
1068 return ResultInvalidEnumValue;
1069 }
1070
1071 // Get the thread from its handle.
1072 auto& kernel = system.Kernel();
1073 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1074 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1075 if (!thread) {
1076 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
1077 return ResultInvalidHandle;
1078 }
1079
1080 // Check that the activity is being set on a non-current thread for the current process.
1081 if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
1082 LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
1083 return ResultInvalidHandle;
1084 }
1085 if (thread.get() == GetCurrentThreadPointer(kernel)) {
1086 LOG_ERROR(Kernel_SVC, "Thread is busy");
1087 return ResultBusy;
1088 }
1089
1090 // Set the activity.
1091 const auto set_result = thread->SetActivity(thread_activity);
1092 if (set_result.IsError()) {
1093 LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
1094 return set_result;
1095 }
1096
1097 return RESULT_SUCCESS; 1036 return RESULT_SUCCESS;
1098} 1037}
1099 1038
@@ -1107,36 +1046,7 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
1107 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context, 1046 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
1108 thread_handle); 1047 thread_handle);
1109 1048
1110 // Get the thread from its handle. 1049 __debugbreak();
1111 const auto* current_process = system.Kernel().CurrentProcess();
1112 const std::shared_ptr<KThread> thread =
1113 current_process->GetHandleTable().Get<KThread>(thread_handle);
1114 if (!thread) {
1115 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
1116 return ResultInvalidHandle;
1117 }
1118
1119 // Require the handle be to a non-current thread in the current process.
1120 if (thread->GetOwnerProcess() != current_process) {
1121 LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
1122 return ResultInvalidHandle;
1123 }
1124 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
1125 LOG_ERROR(Kernel_SVC, "Current thread is busy.");
1126 return ResultBusy;
1127 }
1128
1129 // Get the thread context.
1130 std::vector<u8> context;
1131 const auto context_result = thread->GetThreadContext3(context);
1132 if (context_result.IsError()) {
1133 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
1134 context_result.raw);
1135 return context_result;
1136 }
1137
1138 // Copy the thread context to user space.
1139 system.Memory().WriteBlock(out_context, context.data(), context.size());
1140 1050
1141 return RESULT_SUCCESS; 1051 return RESULT_SUCCESS;
1142} 1052}
@@ -1164,30 +1074,26 @@ static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, H
1164} 1074}
1165 1075
1166/// Sets the priority for the specified thread 1076/// Sets the priority for the specified thread
1167static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { 1077static ResultCode SetThreadPriority(Core::System& system, Handle thread_handle, u32 priority) {
1168 LOG_TRACE(Kernel_SVC, "called"); 1078 // Get the current process.
1079 Process& process = *system.Kernel().CurrentProcess();
1169 1080
1170 // Validate the priority. 1081 // Validate the priority.
1171 if (HighestThreadPriority > priority || priority > LowestThreadPriority) { 1082 R_UNLESS(HighestThreadPriority <= priority && priority <= LowestThreadPriority,
1172 LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); 1083 ResultInvalidPriority);
1173 return ResultInvalidPriority; 1084 R_UNLESS(process.CheckThreadPriority(priority), ResultInvalidPriority);
1174 }
1175 1085
1176 // Get the thread from its handle. 1086 // Get the thread from its handle.
1177 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1087 KScopedAutoObject thread = process.GetHandleTable().GetObject<KThread>(thread_handle);
1178 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1088 R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
1179 if (!thread) {
1180 LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
1181 return ResultInvalidHandle;
1182 }
1183 1089
1184 // Set the thread priority. 1090 // Set the thread priority.
1185 thread->SetBasePriority(priority); 1091 thread->SetBasePriority(priority);
1186 return RESULT_SUCCESS; 1092 return RESULT_SUCCESS;
1187} 1093}
1188 1094
1189static ResultCode SetThreadPriority32(Core::System& system, Handle handle, u32 priority) { 1095static ResultCode SetThreadPriority32(Core::System& system, Handle thread_handle, u32 priority) {
1190 return SetThreadPriority(system, handle, priority); 1096 return SetThreadPriority(system, thread_handle, priority);
1191} 1097}
1192 1098
1193/// Get which CPU core is executing the current thread 1099/// Get which CPU core is executing the current thread
@@ -1480,7 +1386,7 @@ static void ExitProcess32(Core::System& system) {
1480 ExitProcess(system); 1386 ExitProcess(system);
1481} 1387}
1482 1388
1483static constexpr bool IsValidCoreId(int32_t core_id) { 1389static constexpr bool IsValidVirtualCoreId(int32_t core_id) {
1484 return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES)); 1390 return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES));
1485} 1391}
1486 1392
@@ -1500,7 +1406,7 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1500 } 1406 }
1501 1407
1502 // Validate arguments. 1408 // Validate arguments.
1503 if (!IsValidCoreId(core_id)) { 1409 if (!IsValidVirtualCoreId(core_id)) {
1504 LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); 1410 LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
1505 return ResultInvalidCoreId; 1411 return ResultInvalidCoreId;
1506 } 1412 }
@@ -1822,8 +1728,11 @@ static void GetSystemTick32(Core::System& system, u32* time_low, u32* time_high)
1822static ResultCode CloseHandle(Core::System& system, Handle handle) { 1728static ResultCode CloseHandle(Core::System& system, Handle handle) {
1823 LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle); 1729 LOG_TRACE(Kernel_SVC, "Closing handle 0x{:08X}", handle);
1824 1730
1825 auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1731 // Remove the handle.
1826 return handle_table.Close(handle); 1732 R_UNLESS(system.Kernel().CurrentProcess()->GetHandleTable().Remove(handle),
1733 ResultInvalidHandle);
1734
1735 return RESULT_SUCCESS;
1827} 1736}
1828 1737
1829static ResultCode CloseHandle32(Core::System& system, Handle handle) { 1738static ResultCode CloseHandle32(Core::System& system, Handle handle) {
@@ -1925,23 +1834,7 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
1925 1834
1926static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id, 1835static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
1927 u64* out_affinity_mask) { 1836 u64* out_affinity_mask) {
1928 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 1837 __debugbreak();
1929
1930 // Get the thread from its handle.
1931 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1932 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1933 if (!thread) {
1934 LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
1935 return ResultInvalidHandle;
1936 }
1937
1938 // Get the core mask.
1939 const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
1940 if (result.IsError()) {
1941 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
1942 return result;
1943 }
1944
1945 return RESULT_SUCCESS; 1838 return RESULT_SUCCESS;
1946} 1839}
1947 1840
@@ -1956,58 +1849,33 @@ static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle
1956 1849
1957static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id, 1850static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
1958 u64 affinity_mask) { 1851 u64 affinity_mask) {
1959 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}",
1960 thread_handle, core_id, affinity_mask);
1961
1962 const auto& current_process = *system.Kernel().CurrentProcess();
1963
1964 // Determine the core id/affinity mask. 1852 // Determine the core id/affinity mask.
1965 if (core_id == Svc::IdealCoreUseProcessValue) { 1853 if (core_id == IdealCoreUseProcessValue) {
1966 core_id = current_process.GetIdealCoreId(); 1854 core_id = system.Kernel().CurrentProcess()->GetIdealCoreId();
1967 affinity_mask = (1ULL << core_id); 1855 affinity_mask = (1ULL << core_id);
1968 } else { 1856 } else {
1969 // Validate the affinity mask. 1857 // Validate the affinity mask.
1970 const u64 process_core_mask = current_process.GetCoreMask(); 1858 const u64 process_core_mask = system.Kernel().CurrentProcess()->GetCoreMask();
1971 if ((affinity_mask | process_core_mask) != process_core_mask) { 1859 R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId);
1972 LOG_ERROR(Kernel_SVC, 1860 R_UNLESS(affinity_mask != 0, ResultInvalidCombination);
1973 "Affinity mask does match the process core mask (affinity mask={:016X}, core "
1974 "mask={:016X})",
1975 affinity_mask, process_core_mask);
1976 return ResultInvalidCoreId;
1977 }
1978 if (affinity_mask == 0) {
1979 LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
1980 return ResultInvalidCombination;
1981 }
1982 1861
1983 // Validate the core id. 1862 // Validate the core id.
1984 if (IsValidCoreId(core_id)) { 1863 if (IsValidVirtualCoreId(core_id)) {
1985 if (((1ULL << core_id) & affinity_mask) == 0) { 1864 R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination);
1986 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
1987 return ResultInvalidCombination;
1988 }
1989 } else { 1865 } else {
1990 if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { 1866 R_UNLESS(core_id == IdealCoreNoUpdate || core_id == IdealCoreDontCare,
1991 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); 1867 ResultInvalidCoreId);
1992 return ResultInvalidCoreId;
1993 }
1994 } 1868 }
1995 } 1869 }
1996 1870
1997 // Get the thread from its handle. 1871 // Get the thread from its handle.
1998 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1872 KScopedAutoObject thread =
1999 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1873 system.Kernel().CurrentProcess()->GetHandleTable().GetObject<KThread>(thread_handle);
2000 if (!thread) { 1874 R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
2001 LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
2002 return ResultInvalidHandle;
2003 }
2004 1875
2005 // Set the core mask. 1876 // Set the core mask.
2006 const auto set_result = thread->SetCoreMask(core_id, affinity_mask); 1877 R_TRY(thread->SetCoreMask(core_id, affinity_mask));
2007 if (set_result.IsError()) { 1878
2008 LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
2009 return set_result;
2010 }
2011 return RESULT_SUCCESS; 1879 return RESULT_SUCCESS;
2012} 1880}
2013 1881
@@ -2105,7 +1973,7 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
2105 *out_write = *write_create_result; 1973 *out_write = *write_create_result;
2106 1974
2107 // Add the writable event to the handle table. 1975 // Add the writable event to the handle table.
2108 auto handle_guard = SCOPE_GUARD({ handle_table.Close(*write_create_result); }); 1976 auto handle_guard = SCOPE_GUARD({ handle_table.Remove(*write_create_result); });
2109 1977
2110 // Add the readable event to the handle table. 1978 // Add the readable event to the handle table.
2111 const auto read_create_result = handle_table.Create(event->GetReadableEvent()); 1979 const auto read_create_result = handle_table.Create(event->GetReadableEvent());