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.cpp355
1 files changed, 152 insertions, 203 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 2512bfd98..dbef854f8 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -351,7 +351,8 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
352 } 352 }
353 353
354 return thread->GetSignalingResult(); 354 KSynchronizationObject* dummy{};
355 return thread->GetWaitResult(std::addressof(dummy));
355} 356}
356 357
357static ResultCode SendSyncRequest32(Core::System& system, Handle handle) { 358static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
@@ -359,27 +360,26 @@ static ResultCode SendSyncRequest32(Core::System& system, Handle handle) {
359} 360}
360 361
361/// Get the ID for the specified thread. 362/// Get the ID for the specified thread.
362static ResultCode GetThreadId(Core::System& system, u64* thread_id, Handle thread_handle) { 363static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle thread_handle) {
363 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 364 LOG_TRACE(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
364 365
366 // Get the thread from its handle.
365 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 367 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
366 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 368 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
367 if (!thread) { 369 R_UNLESS(thread, Svc::ResultInvalidHandle);
368 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", thread_handle);
369 return ERR_INVALID_HANDLE;
370 }
371 370
372 *thread_id = thread->GetThreadID(); 371 // Get the thread's id.
372 *out_thread_id = thread->GetThreadID();
373 return RESULT_SUCCESS; 373 return RESULT_SUCCESS;
374} 374}
375 375
376static ResultCode GetThreadId32(Core::System& system, u32* thread_id_low, u32* thread_id_high, 376static ResultCode GetThreadId32(Core::System& system, u32* out_thread_id_low,
377 Handle thread_handle) { 377 u32* out_thread_id_high, Handle thread_handle) {
378 u64 thread_id{}; 378 u64 out_thread_id{};
379 const ResultCode result{GetThreadId(system, &thread_id, thread_handle)}; 379 const ResultCode result{GetThreadId(system, &out_thread_id, thread_handle)};
380 380
381 *thread_id_low = static_cast<u32>(thread_id >> 32); 381 *out_thread_id_low = static_cast<u32>(out_thread_id >> 32);
382 *thread_id_high = static_cast<u32>(thread_id & std::numeric_limits<u32>::max()); 382 *out_thread_id_high = static_cast<u32>(out_thread_id & std::numeric_limits<u32>::max());
383 383
384 return result; 384 return result;
385} 385}
@@ -473,15 +473,13 @@ static ResultCode WaitSynchronization32(Core::System& system, u32 timeout_low, u
473static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) { 473static ResultCode CancelSynchronization(Core::System& system, Handle thread_handle) {
474 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle); 474 LOG_TRACE(Kernel_SVC, "called thread=0x{:X}", thread_handle);
475 475
476 // Get the thread from its handle.
476 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 477 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
477 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 478 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
478 if (!thread) { 479 R_UNLESS(thread, Svc::ResultInvalidHandle);
479 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
480 thread_handle);
481 return ERR_INVALID_HANDLE;
482 }
483 480
484 thread->CancelWait(); 481 // Cancel the thread's wait.
482 thread->WaitCancel();
485 return RESULT_SUCCESS; 483 return RESULT_SUCCESS;
486} 484}
487 485
@@ -630,7 +628,7 @@ static void Break(Core::System& system, u32 reason, u64 info1, u64 info2) {
630 handle_debug_buffer(info1, info2); 628 handle_debug_buffer(info1, info2);
631 629
632 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 630 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
633 const auto thread_processor_id = current_thread->GetProcessorID(); 631 const auto thread_processor_id = current_thread->GetActiveCore();
634 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace(); 632 system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
635 } 633 }
636} 634}
@@ -888,7 +886,7 @@ static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, u64 ha
888 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks(); 886 const u64 prev_ctx_ticks = scheduler.GetLastContextSwitchTicks();
889 u64 out_ticks = 0; 887 u64 out_ticks = 0;
890 if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) { 888 if (same_thread && info_sub_id == 0xFFFFFFFFFFFFFFFF) {
891 const u64 thread_ticks = current_thread->GetTotalCPUTimeTicks(); 889 const u64 thread_ticks = current_thread->GetCpuTime();
892 890
893 out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks); 891 out_ticks = thread_ticks + (core_timing.GetCPUTicks() - prev_ctx_ticks);
894 } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) { 892 } else if (same_thread && info_sub_id == system.CurrentCoreIndex()) {
@@ -1025,127 +1023,109 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
1025 return UnmapPhysicalMemory(system, addr, size); 1023 return UnmapPhysicalMemory(system, addr, size);
1026} 1024}
1027 1025
1028/// Sets the thread activity 1026constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
1029static ResultCode SetThreadActivity(Core::System& system, Handle handle, u32 activity) { 1027 switch (thread_activity) {
1030 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", handle, activity); 1028 case Svc::ThreadActivity::Runnable:
1031 if (activity > static_cast<u32>(ThreadActivity::Paused)) { 1029 case Svc::ThreadActivity::Paused:
1032 return ERR_INVALID_ENUM_VALUE; 1030 return true;
1031 default:
1032 return false;
1033 } 1033 }
1034}
1034 1035
1035 const auto* current_process = system.Kernel().CurrentProcess(); 1036/// Sets the thread activity
1036 const std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle); 1037static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1037 if (!thread) { 1038 Svc::ThreadActivity thread_activity) {
1038 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); 1039 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
1039 return ERR_INVALID_HANDLE; 1040 thread_activity);
1040 }
1041 1041
1042 if (thread->GetOwnerProcess() != current_process) { 1042 // Validate the activity.
1043 LOG_ERROR(Kernel_SVC, 1043 R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue);
1044 "The current process does not own the current thread, thread_handle={:08X} "
1045 "thread_pid={}, "
1046 "current_process_pid={}",
1047 handle, thread->GetOwnerProcess()->GetProcessID(),
1048 current_process->GetProcessID());
1049 return ERR_INVALID_HANDLE;
1050 }
1051 1044
1052 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { 1045 // Get the thread from its handle.
1053 LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); 1046 auto& kernel = system.Kernel();
1054 return ERR_BUSY; 1047 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1055 } 1048 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1049 R_UNLESS(thread, Svc::ResultInvalidHandle);
1050
1051 // Check that the activity is being set on a non-current thread for the current process.
1052 R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle);
1053 R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy);
1054
1055 // Set the activity.
1056 R_TRY(thread->SetActivity(thread_activity));
1056 1057
1057 return thread->SetActivity(static_cast<ThreadActivity>(activity)); 1058 return RESULT_SUCCESS;
1058} 1059}
1059 1060
1060static ResultCode SetThreadActivity32(Core::System& system, Handle handle, u32 activity) { 1061static ResultCode SetThreadActivity32(Core::System& system, Handle thread_handle,
1061 return SetThreadActivity(system, handle, activity); 1062 Svc::ThreadActivity thread_activity) {
1063 return SetThreadActivity(system, thread_handle, thread_activity);
1062} 1064}
1063 1065
1064/// Gets the thread context 1066/// Gets the thread context
1065static ResultCode GetThreadContext(Core::System& system, VAddr thread_context, Handle handle) { 1067static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Handle thread_handle) {
1066 LOG_DEBUG(Kernel_SVC, "called, context=0x{:08X}, thread=0x{:X}", thread_context, handle); 1068 LOG_DEBUG(Kernel_SVC, "called, out_context=0x{:08X}, thread_handle=0x{:X}", out_context,
1069 thread_handle);
1067 1070
1071 // Get the thread from its handle.
1068 const auto* current_process = system.Kernel().CurrentProcess(); 1072 const auto* current_process = system.Kernel().CurrentProcess();
1069 const std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle); 1073 const std::shared_ptr<KThread> thread =
1070 if (!thread) { 1074 current_process->GetHandleTable().Get<KThread>(thread_handle);
1071 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); 1075 R_UNLESS(thread, Svc::ResultInvalidHandle);
1072 return ERR_INVALID_HANDLE;
1073 }
1074 1076
1075 if (thread->GetOwnerProcess() != current_process) { 1077 // Require the handle be to a non-current thread in the current process.
1076 LOG_ERROR(Kernel_SVC, 1078 R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle);
1077 "The current process does not own the current thread, thread_handle={:08X} " 1079 R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(),
1078 "thread_pid={}, " 1080 Svc::ResultBusy);
1079 "current_process_pid={}",
1080 handle, thread->GetOwnerProcess()->GetProcessID(),
1081 current_process->GetProcessID());
1082 return ERR_INVALID_HANDLE;
1083 }
1084 1081
1085 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { 1082 // Get the thread context.
1086 LOG_ERROR(Kernel_SVC, "The thread handle specified is the current running thread"); 1083 std::vector<u8> context;
1087 return ERR_BUSY; 1084 R_TRY(thread->GetThreadContext3(context));
1088 }
1089 1085
1090 Core::ARM_Interface::ThreadContext64 ctx = thread->GetContext64(); 1086 // Copy the thread context to user space.
1091 // Mask away mode bits, interrupt bits, IL bit, and other reserved bits. 1087 system.Memory().WriteBlock(out_context, context.data(), context.size());
1092 ctx.pstate &= 0xFF0FFE20;
1093 1088
1094 // If 64-bit, we can just write the context registers directly and we're good.
1095 // However, if 32-bit, we have to ensure some registers are zeroed out.
1096 if (!current_process->Is64BitProcess()) {
1097 std::fill(ctx.cpu_registers.begin() + 15, ctx.cpu_registers.end(), 0);
1098 std::fill(ctx.vector_registers.begin() + 16, ctx.vector_registers.end(), u128{});
1099 }
1100
1101 system.Memory().WriteBlock(thread_context, &ctx, sizeof(ctx));
1102 return RESULT_SUCCESS; 1089 return RESULT_SUCCESS;
1103} 1090}
1104 1091
1105static ResultCode GetThreadContext32(Core::System& system, u32 thread_context, Handle handle) { 1092static ResultCode GetThreadContext32(Core::System& system, u32 out_context, Handle thread_handle) {
1106 return GetThreadContext(system, thread_context, handle); 1093 return GetThreadContext(system, out_context, thread_handle);
1107} 1094}
1108 1095
1109/// Gets the priority for the specified thread 1096/// Gets the priority for the specified thread
1110static ResultCode GetThreadPriority(Core::System& system, u32* priority, Handle handle) { 1097static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Handle handle) {
1111 LOG_TRACE(Kernel_SVC, "called"); 1098 LOG_TRACE(Kernel_SVC, "called");
1112 1099
1100 // Get the thread from its handle.
1113 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1101 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1114 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1102 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1115 if (!thread) { 1103 R_UNLESS(thread, Svc::ResultInvalidHandle);
1116 *priority = 0;
1117 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle);
1118 return ERR_INVALID_HANDLE;
1119 }
1120 1104
1121 *priority = thread->GetPriority(); 1105 // Get the thread's priority.
1106 *out_priority = thread->GetPriority();
1122 return RESULT_SUCCESS; 1107 return RESULT_SUCCESS;
1123} 1108}
1124 1109
1125static ResultCode GetThreadPriority32(Core::System& system, u32* priority, Handle handle) { 1110static ResultCode GetThreadPriority32(Core::System& system, u32* out_priority, Handle handle) {
1126 return GetThreadPriority(system, priority, handle); 1111 return GetThreadPriority(system, out_priority, handle);
1127} 1112}
1128 1113
1129/// Sets the priority for the specified thread 1114/// Sets the priority for the specified thread
1130static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) { 1115static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 priority) {
1131 LOG_TRACE(Kernel_SVC, "called"); 1116 LOG_TRACE(Kernel_SVC, "called");
1132 1117
1133 if (priority > Svc::LowestThreadPriority) { 1118 // Validate the priority.
1134 LOG_ERROR(Kernel_SVC, "An invalid priority was specified {} for thread_handle={:08X}", 1119 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority,
1135 priority, handle); 1120 Svc::ResultInvalidPriority);
1136 return ERR_INVALID_THREAD_PRIORITY;
1137 }
1138
1139 const auto* const current_process = system.Kernel().CurrentProcess();
1140 1121
1141 std::shared_ptr<KThread> thread = current_process->GetHandleTable().Get<KThread>(handle); 1122 // Get the thread from its handle.
1142 if (!thread) { 1123 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1143 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, handle=0x{:08X}", handle); 1124 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1144 return ERR_INVALID_HANDLE; 1125 R_UNLESS(thread, Svc::ResultInvalidHandle);
1145 }
1146 1126
1127 // Set the thread priority.
1147 thread->SetBasePriority(priority); 1128 thread->SetBasePriority(priority);
1148
1149 return RESULT_SUCCESS; 1129 return RESULT_SUCCESS;
1150} 1130}
1151 1131
@@ -1436,7 +1416,7 @@ static void ExitProcess(Core::System& system) {
1436 current_process->PrepareForTermination(); 1416 current_process->PrepareForTermination();
1437 1417
1438 // Kill the current thread 1418 // Kill the current thread
1439 system.Kernel().CurrentScheduler()->GetCurrentThread()->Stop(); 1419 system.Kernel().CurrentScheduler()->GetCurrentThread()->Exit();
1440} 1420}
1441 1421
1442static void ExitProcess32(Core::System& system) { 1422static void ExitProcess32(Core::System& system) {
@@ -1500,17 +1480,15 @@ static ResultCode CreateThread32(Core::System& system, Handle* out_handle, u32 p
1500static ResultCode StartThread(Core::System& system, Handle thread_handle) { 1480static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1501 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle); 1481 LOG_DEBUG(Kernel_SVC, "called thread=0x{:08X}", thread_handle);
1502 1482
1483 // Get the thread from its handle.
1503 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1484 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1504 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1485 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1505 if (!thread) { 1486 R_UNLESS(thread, Svc::ResultInvalidHandle);
1506 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1507 thread_handle);
1508 return ERR_INVALID_HANDLE;
1509 }
1510 1487
1511 ASSERT(thread->GetState() == ThreadState::Initialized); 1488 // Try to start the thread.
1489 R_TRY(thread->Run());
1512 1490
1513 return thread->Start(); 1491 return RESULT_SUCCESS;
1514} 1492}
1515 1493
1516static ResultCode StartThread32(Core::System& system, Handle thread_handle) { 1494static ResultCode StartThread32(Core::System& system, Handle thread_handle) {
@@ -1523,7 +1501,7 @@ static void ExitThread(Core::System& system) {
1523 1501
1524 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread(); 1502 auto* const current_thread = system.Kernel().CurrentScheduler()->GetCurrentThread();
1525 system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread)); 1503 system.GlobalSchedulerContext().RemoveThread(SharedFrom(current_thread));
1526 current_thread->Stop(); 1504 current_thread->Exit();
1527} 1505}
1528 1506
1529static void ExitThread32(Core::System& system) { 1507static void ExitThread32(Core::System& system) {
@@ -1532,34 +1510,28 @@ static void ExitThread32(Core::System& system) {
1532 1510
1533/// Sleep the current thread 1511/// Sleep the current thread
1534static void SleepThread(Core::System& system, s64 nanoseconds) { 1512static void SleepThread(Core::System& system, s64 nanoseconds) {
1535 LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds); 1513 auto& kernel = system.Kernel();
1514 const auto yield_type = static_cast<Svc::YieldType>(nanoseconds);
1536 1515
1537 enum class SleepType : s64 { 1516 LOG_TRACE(Kernel_SVC, "called nanoseconds={}", nanoseconds);
1538 YieldWithoutCoreMigration = 0,
1539 YieldWithCoreMigration = -1,
1540 YieldAndWaitForLoadBalancing = -2,
1541 };
1542 1517
1543 auto& scheduler = *system.Kernel().CurrentScheduler(); 1518 // When the input tick is positive, sleep.
1544 if (nanoseconds <= 0) { 1519 if (nanoseconds > 0) {
1545 switch (static_cast<SleepType>(nanoseconds)) { 1520 // Convert the timeout from nanoseconds to ticks.
1546 case SleepType::YieldWithoutCoreMigration: { 1521 // NOTE: Nintendo does not use this conversion logic in WaitSynchronization...
1547 scheduler.YieldWithoutCoreMigration(); 1522
1548 break; 1523 // Sleep.
1549 } 1524 // NOTE: Nintendo does not check the result of this sleep.
1550 case SleepType::YieldWithCoreMigration: { 1525 static_cast<void>(GetCurrentThread(kernel).Sleep(nanoseconds));
1551 scheduler.YieldWithCoreMigration(); 1526 } else if (yield_type == Svc::YieldType::WithoutCoreMigration) {
1552 break; 1527 KScheduler::YieldWithoutCoreMigration(kernel);
1553 } 1528 } else if (yield_type == Svc::YieldType::WithCoreMigration) {
1554 case SleepType::YieldAndWaitForLoadBalancing: { 1529 KScheduler::YieldWithCoreMigration(kernel);
1555 scheduler.YieldToAnyThread(); 1530 } else if (yield_type == Svc::YieldType::ToAnyThread) {
1556 break; 1531 KScheduler::YieldToAnyThread(kernel);
1557 }
1558 default:
1559 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
1560 }
1561 } else { 1532 } else {
1562 scheduler.GetCurrentThread()->Sleep(nanoseconds); 1533 // Nintendo does nothing at all if an otherwise invalid value is passed.
1534 UNREACHABLE_MSG("Unimplemented sleep yield type '{:016X}'!", nanoseconds);
1563 } 1535 }
1564} 1536}
1565 1537
@@ -1822,95 +1794,72 @@ static ResultCode CreateTransferMemory32(Core::System& system, Handle* handle, u
1822 return CreateTransferMemory(system, handle, addr, size, permissions); 1794 return CreateTransferMemory(system, handle, addr, size, permissions);
1823} 1795}
1824 1796
1825static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, u32* core, 1797static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, s32* out_core_id,
1826 u64* mask) { 1798 u64* out_affinity_mask) {
1827 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle); 1799 LOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}", thread_handle);
1828 1800
1801 // Get the thread from its handle.
1829 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1802 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1830 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1803 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1831 if (!thread) { 1804 R_UNLESS(thread, Svc::ResultInvalidHandle);
1832 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1833 thread_handle);
1834 *core = 0;
1835 *mask = 0;
1836 return ERR_INVALID_HANDLE;
1837 }
1838 1805
1839 *core = thread->GetIdealCore(); 1806 // Get the core mask.
1840 *mask = thread->GetAffinityMask().GetAffinityMask(); 1807 R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask));
1841 1808
1842 return RESULT_SUCCESS; 1809 return RESULT_SUCCESS;
1843} 1810}
1844 1811
1845static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, u32* core, 1812static ResultCode GetThreadCoreMask32(Core::System& system, Handle thread_handle, s32* out_core_id,
1846 u32* mask_low, u32* mask_high) { 1813 u32* out_affinity_mask_low, u32* out_affinity_mask_high) {
1847 u64 mask{}; 1814 u64 out_affinity_mask{};
1848 const auto result = GetThreadCoreMask(system, thread_handle, core, &mask); 1815 const auto result = GetThreadCoreMask(system, thread_handle, out_core_id, &out_affinity_mask);
1849 *mask_high = static_cast<u32>(mask >> 32); 1816 *out_affinity_mask_high = static_cast<u32>(out_affinity_mask >> 32);
1850 *mask_low = static_cast<u32>(mask); 1817 *out_affinity_mask_low = static_cast<u32>(out_affinity_mask);
1851 return result; 1818 return result;
1852} 1819}
1853 1820
1854static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, u32 core, 1821static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id,
1855 u64 affinity_mask) { 1822 u64 affinity_mask) {
1856 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core=0x{:X}, affinity_mask=0x{:016X}", 1823 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, core_id=0x{:X}, affinity_mask=0x{:016X}",
1857 thread_handle, core, affinity_mask); 1824 thread_handle, core_id, affinity_mask);
1858
1859 const auto* const current_process = system.Kernel().CurrentProcess();
1860 1825
1861 if (core == static_cast<u32>(Svc::IdealCoreUseProcessValue)) { 1826 const auto& current_process = *system.Kernel().CurrentProcess();
1862 const u8 ideal_cpu_core = current_process->GetIdealCoreId();
1863 1827
1864 ASSERT(ideal_cpu_core != static_cast<u8>(Svc::IdealCoreUseProcessValue)); 1828 // Determine the core id/affinity mask.
1865 1829 if (core_id == Svc::IdealCoreUseProcessValue) {
1866 // Set the target CPU to the ideal core specified by the process. 1830 core_id = current_process.GetIdealCoreId();
1867 core = ideal_cpu_core; 1831 affinity_mask = (1ULL << core_id);
1868 affinity_mask = 1ULL << core;
1869 } else { 1832 } else {
1870 const u64 core_mask = current_process->GetCoreMask(); 1833 // Validate the affinity mask.
1871 1834 const u64 process_core_mask = current_process.GetCoreMask();
1872 if ((core_mask | affinity_mask) != core_mask) { 1835 R_UNLESS((affinity_mask | process_core_mask) == process_core_mask,
1873 LOG_ERROR( 1836 Svc::ResultInvalidCoreId);
1874 Kernel_SVC, 1837 R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination);
1875 "Invalid processor ID specified (core_mask=0x{:08X}, affinity_mask=0x{:016X})", 1838
1876 core_mask, affinity_mask); 1839 // Validate the core id.
1877 return ERR_INVALID_PROCESSOR_ID; 1840 if (IsValidCoreId(core_id)) {
1878 } 1841 R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination);
1879 1842 } else {
1880 if (affinity_mask == 0) { 1843 R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare,
1881 LOG_ERROR(Kernel_SVC, "Specfified affinity mask is zero."); 1844 Svc::ResultInvalidCoreId);
1882 return ERR_INVALID_COMBINATION;
1883 }
1884
1885 if (core < Core::Hardware::NUM_CPU_CORES) {
1886 if ((affinity_mask & (1ULL << core)) == 0) {
1887 LOG_ERROR(Kernel_SVC,
1888 "Core is not enabled for the current mask, core={}, mask={:016X}", core,
1889 affinity_mask);
1890 return ERR_INVALID_COMBINATION;
1891 }
1892 } else if (core != static_cast<u32>(Svc::IdealCoreDontCare) &&
1893 core != static_cast<u32>(Svc::IdealCoreNoUpdate)) {
1894 LOG_ERROR(Kernel_SVC, "Invalid processor ID specified (core={}).", core);
1895 return ERR_INVALID_PROCESSOR_ID;
1896 } 1845 }
1897 } 1846 }
1898 1847
1899 const auto& handle_table = current_process->GetHandleTable(); 1848 // Get the thread from its handle.
1849 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1900 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1850 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1901 if (!thread) { 1851 R_UNLESS(thread, Svc::ResultInvalidHandle);
1902 LOG_ERROR(Kernel_SVC, "Thread handle does not exist, thread_handle=0x{:08X}",
1903 thread_handle);
1904 return ERR_INVALID_HANDLE;
1905 }
1906 1852
1907 return thread->SetCoreAndAffinityMask(core, affinity_mask); 1853 // Set the core mask.
1854 R_TRY(thread->SetCoreMask(core_id, affinity_mask));
1855
1856 return RESULT_SUCCESS;
1908} 1857}
1909 1858
1910static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, u32 core, 1859static ResultCode SetThreadCoreMask32(Core::System& system, Handle thread_handle, s32 core_id,
1911 u32 affinity_mask_low, u32 affinity_mask_high) { 1860 u32 affinity_mask_low, u32 affinity_mask_high) {
1912 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32); 1861 const auto affinity_mask = u64{affinity_mask_low} | (u64{affinity_mask_high} << 32);
1913 return SetThreadCoreMask(system, thread_handle, core, affinity_mask); 1862 return SetThreadCoreMask(system, thread_handle, core_id, affinity_mask);
1914} 1863}
1915 1864
1916static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) { 1865static ResultCode CreateEvent(Core::System& system, Handle* write_handle, Handle* read_handle) {
@@ -2474,7 +2423,7 @@ void Call(Core::System& system, u32 immediate) {
2474 kernel.EnterSVCProfile(); 2423 kernel.EnterSVCProfile();
2475 2424
2476 auto* thread = kernel.CurrentScheduler()->GetCurrentThread(); 2425 auto* thread = kernel.CurrentScheduler()->GetCurrentThread();
2477 thread->SetContinuousOnSVC(true); 2426 thread->SetIsCallingSvc();
2478 2427
2479 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate) 2428 const FunctionDef* info = system.CurrentProcess()->Is64BitProcess() ? GetSVCInfo64(immediate)
2480 : GetSVCInfo32(immediate); 2429 : GetSVCInfo32(immediate);
@@ -2490,7 +2439,7 @@ void Call(Core::System& system, u32 immediate) {
2490 2439
2491 kernel.ExitSVCProfile(); 2440 kernel.ExitSVCProfile();
2492 2441
2493 if (!thread->IsContinuousOnSVC()) { 2442 if (!thread->IsCallingSvc()) {
2494 auto* host_context = thread->GetHostContext().get(); 2443 auto* host_context = thread->GetHostContext().get();
2495 host_context->Rewind(); 2444 host_context->Rewind();
2496 } 2445 }