diff options
| -rw-r--r-- | src/core/hle/kernel/svc.cpp | 247 |
1 files changed, 188 insertions, 59 deletions
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index edf208eff..26650a513 100644 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp | |||
| @@ -368,7 +368,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t | |||
| 368 | // Get the thread from its handle. | 368 | // Get the thread from its handle. |
| 369 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 369 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 370 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 370 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 371 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 371 | if (!thread) { |
| 372 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 373 | return ResultInvalidHandle; | ||
| 374 | } | ||
| 372 | 375 | ||
| 373 | // Get the thread's id. | 376 | // Get the thread's id. |
| 374 | *out_thread_id = thread->GetThreadID(); | 377 | *out_thread_id = thread->GetThreadID(); |
| @@ -478,7 +481,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand | |||
| 478 | // Get the thread from its handle. | 481 | // Get the thread from its handle. |
| 479 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 482 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 480 | std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 483 | std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 481 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 484 | if (!thread) { |
| 485 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 486 | return ResultInvalidHandle; | ||
| 487 | } | ||
| 482 | 488 | ||
| 483 | // Cancel the thread's wait. | 489 | // Cancel the thread's wait. |
| 484 | thread->WaitCancel(); | 490 | thread->WaitCancel(); |
| @@ -496,8 +502,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd | |||
| 496 | thread_handle, address, tag); | 502 | thread_handle, address, tag); |
| 497 | 503 | ||
| 498 | // Validate the input address. | 504 | // Validate the input address. |
| 499 | R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); | 505 | if (Memory::IsKernelAddress(address)) { |
| 500 | R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); | 506 | LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})", |
| 507 | address); | ||
| 508 | return ResultInvalidCurrentMemory; | ||
| 509 | } | ||
| 510 | if (!Common::IsAligned(address, sizeof(u32))) { | ||
| 511 | LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address); | ||
| 512 | return ResultInvalidAddress; | ||
| 513 | } | ||
| 501 | 514 | ||
| 502 | return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); | 515 | return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); |
| 503 | } | 516 | } |
| @@ -512,8 +525,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) { | |||
| 512 | LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); | 525 | LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); |
| 513 | 526 | ||
| 514 | // Validate the input address. | 527 | // Validate the input address. |
| 515 | R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); | 528 | if (Memory::IsKernelAddress(address)) { |
| 516 | R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); | 529 | LOG_ERROR(Kernel_SVC, |
| 530 | "Attempting to arbitrate an unlock on a kernel address (address={:08X})", | ||
| 531 | address); | ||
| 532 | return ResultInvalidCurrentMemory; | ||
| 533 | } | ||
| 534 | if (!Common::IsAligned(address, sizeof(u32))) { | ||
| 535 | LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address); | ||
| 536 | return ResultInvalidAddress; | ||
| 537 | } | ||
| 517 | 538 | ||
| 518 | return system.Kernel().CurrentProcess()->SignalToAddress(address); | 539 | return system.Kernel().CurrentProcess()->SignalToAddress(address); |
| 519 | } | 540 | } |
| @@ -1025,37 +1046,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size | |||
| 1025 | return UnmapPhysicalMemory(system, addr, size); | 1046 | return UnmapPhysicalMemory(system, addr, size); |
| 1026 | } | 1047 | } |
| 1027 | 1048 | ||
| 1028 | constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) { | ||
| 1029 | switch (thread_activity) { | ||
| 1030 | case Svc::ThreadActivity::Runnable: | ||
| 1031 | case Svc::ThreadActivity::Paused: | ||
| 1032 | return true; | ||
| 1033 | default: | ||
| 1034 | return false; | ||
| 1035 | } | ||
| 1036 | } | ||
| 1037 | |||
| 1038 | /// Sets the thread activity | 1049 | /// Sets the thread activity |
| 1039 | static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, | 1050 | static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, |
| 1040 | Svc::ThreadActivity thread_activity) { | 1051 | ThreadActivity thread_activity) { |
| 1041 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, | 1052 | LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, |
| 1042 | thread_activity); | 1053 | thread_activity); |
| 1043 | 1054 | ||
| 1044 | // Validate the activity. | 1055 | // Validate the activity. |
| 1045 | R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue); | 1056 | constexpr auto IsValidThreadActivity = [](ThreadActivity activity) { |
| 1057 | return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused; | ||
| 1058 | }; | ||
| 1059 | if (!IsValidThreadActivity(thread_activity)) { | ||
| 1060 | LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})", | ||
| 1061 | thread_activity); | ||
| 1062 | return ResultInvalidEnumValue; | ||
| 1063 | } | ||
| 1046 | 1064 | ||
| 1047 | // Get the thread from its handle. | 1065 | // Get the thread from its handle. |
| 1048 | auto& kernel = system.Kernel(); | 1066 | auto& kernel = system.Kernel(); |
| 1049 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); | 1067 | const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); |
| 1050 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1068 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 1051 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1069 | if (!thread) { |
| 1070 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 1071 | return ResultInvalidHandle; | ||
| 1072 | } | ||
| 1052 | 1073 | ||
| 1053 | // Check that the activity is being set on a non-current thread for the current process. | 1074 | // Check that the activity is being set on a non-current thread for the current process. |
| 1054 | R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle); | 1075 | if (thread->GetOwnerProcess() != kernel.CurrentProcess()) { |
| 1055 | R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy); | 1076 | LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread."); |
| 1077 | return ResultInvalidHandle; | ||
| 1078 | } | ||
| 1079 | if (thread.get() == GetCurrentThreadPointer(kernel)) { | ||
| 1080 | LOG_ERROR(Kernel_SVC, "Thread is busy"); | ||
| 1081 | return ResultBusy; | ||
| 1082 | } | ||
| 1056 | 1083 | ||
| 1057 | // Set the activity. | 1084 | // Set the activity. |
| 1058 | R_TRY(thread->SetActivity(thread_activity)); | 1085 | const auto set_result = thread->SetActivity(thread_activity); |
| 1086 | if (set_result.IsError()) { | ||
| 1087 | LOG_ERROR(Kernel_SVC, "Failed to set thread activity."); | ||
| 1088 | return set_result; | ||
| 1089 | } | ||
| 1059 | 1090 | ||
| 1060 | return RESULT_SUCCESS; | 1091 | return RESULT_SUCCESS; |
| 1061 | } | 1092 | } |
| @@ -1074,16 +1105,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand | |||
| 1074 | const auto* current_process = system.Kernel().CurrentProcess(); | 1105 | const auto* current_process = system.Kernel().CurrentProcess(); |
| 1075 | const std::shared_ptr<KThread> thread = | 1106 | const std::shared_ptr<KThread> thread = |
| 1076 | current_process->GetHandleTable().Get<KThread>(thread_handle); | 1107 | current_process->GetHandleTable().Get<KThread>(thread_handle); |
| 1077 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1108 | if (!thread) { |
| 1109 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle); | ||
| 1110 | return ResultInvalidHandle; | ||
| 1111 | } | ||
| 1078 | 1112 | ||
| 1079 | // Require the handle be to a non-current thread in the current process. | 1113 | // Require the handle be to a non-current thread in the current process. |
| 1080 | R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle); | 1114 | if (thread->GetOwnerProcess() != current_process) { |
| 1081 | R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(), | 1115 | LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process."); |
| 1082 | Svc::ResultBusy); | 1116 | return ResultInvalidHandle; |
| 1117 | } | ||
| 1118 | if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) { | ||
| 1119 | LOG_ERROR(Kernel_SVC, "Current thread is busy."); | ||
| 1120 | return ResultBusy; | ||
| 1121 | } | ||
| 1083 | 1122 | ||
| 1084 | // Get the thread context. | 1123 | // Get the thread context. |
| 1085 | std::vector<u8> context; | 1124 | std::vector<u8> context; |
| 1086 | R_TRY(thread->GetThreadContext3(context)); | 1125 | const auto context_result = thread->GetThreadContext3(context); |
| 1126 | if (context_result.IsError()) { | ||
| 1127 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})", | ||
| 1128 | context_result.raw); | ||
| 1129 | return context_result; | ||
| 1130 | } | ||
| 1087 | 1131 | ||
| 1088 | // Copy the thread context to user space. | 1132 | // Copy the thread context to user space. |
| 1089 | system.Memory().WriteBlock(out_context, context.data(), context.size()); | 1133 | system.Memory().WriteBlock(out_context, context.data(), context.size()); |
| @@ -1102,7 +1146,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han | |||
| 1102 | // Get the thread from its handle. | 1146 | // Get the thread from its handle. |
| 1103 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1147 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1104 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 1148 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); |
| 1105 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1149 | if (!thread) { |
| 1150 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle); | ||
| 1151 | return ResultInvalidHandle; | ||
| 1152 | } | ||
| 1106 | 1153 | ||
| 1107 | // Get the thread's priority. | 1154 | // Get the thread's priority. |
| 1108 | *out_priority = thread->GetPriority(); | 1155 | *out_priority = thread->GetPriority(); |
| @@ -1118,13 +1165,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri | |||
| 1118 | LOG_TRACE(Kernel_SVC, "called"); | 1165 | LOG_TRACE(Kernel_SVC, "called"); |
| 1119 | 1166 | ||
| 1120 | // Validate the priority. | 1167 | // Validate the priority. |
| 1121 | R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, | 1168 | if (HighestThreadPriority > priority || priority > LowestThreadPriority) { |
| 1122 | Svc::ResultInvalidPriority); | 1169 | LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority); |
| 1170 | return ResultInvalidPriority; | ||
| 1171 | } | ||
| 1123 | 1172 | ||
| 1124 | // Get the thread from its handle. | 1173 | // Get the thread from its handle. |
| 1125 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1174 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1126 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); | 1175 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); |
| 1127 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1176 | if (!thread) { |
| 1177 | LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle); | ||
| 1178 | return ResultInvalidHandle; | ||
| 1179 | } | ||
| 1128 | 1180 | ||
| 1129 | // Set the thread priority. | 1181 | // Set the thread priority. |
| 1130 | thread->SetBasePriority(priority); | 1182 | thread->SetBasePriority(priority); |
| @@ -1440,17 +1492,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e | |||
| 1440 | // Adjust core id, if it's the default magic. | 1492 | // Adjust core id, if it's the default magic. |
| 1441 | auto& kernel = system.Kernel(); | 1493 | auto& kernel = system.Kernel(); |
| 1442 | auto& process = *kernel.CurrentProcess(); | 1494 | auto& process = *kernel.CurrentProcess(); |
| 1443 | if (core_id == Svc::IdealCoreUseProcessValue) { | 1495 | if (core_id == IdealCoreUseProcessValue) { |
| 1444 | core_id = process.GetIdealCoreId(); | 1496 | core_id = process.GetIdealCoreId(); |
| 1445 | } | 1497 | } |
| 1446 | 1498 | ||
| 1447 | // Validate arguments. | 1499 | // Validate arguments. |
| 1448 | R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId); | 1500 | if (!IsValidCoreId(core_id)) { |
| 1449 | R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId); | 1501 | LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id); |
| 1502 | return ResultInvalidCoreId; | ||
| 1503 | } | ||
| 1504 | if (((1ULL << core_id) & process.GetCoreMask()) == 0) { | ||
| 1505 | LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id); | ||
| 1506 | return ResultInvalidCoreId; | ||
| 1507 | } | ||
| 1450 | 1508 | ||
| 1451 | R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, | 1509 | if (HighestThreadPriority > priority || priority > LowestThreadPriority) { |
| 1452 | Svc::ResultInvalidPriority); | 1510 | LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority); |
| 1453 | R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); | 1511 | return ResultInvalidPriority; |
| 1512 | } | ||
| 1513 | if (!process.CheckThreadPriority(priority)) { | ||
| 1514 | LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority); | ||
| 1515 | return ResultInvalidPriority; | ||
| 1516 | } | ||
| 1454 | 1517 | ||
| 1455 | ASSERT(process.GetResourceLimit()->Reserve( | 1518 | ASSERT(process.GetResourceLimit()->Reserve( |
| 1456 | LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); | 1519 | LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); |
| @@ -1489,10 +1552,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) { | |||
| 1489 | // Get the thread from its handle. | 1552 | // Get the thread from its handle. |
| 1490 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1553 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1491 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1554 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 1492 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1555 | if (!thread) { |
| 1556 | LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle); | ||
| 1557 | return ResultInvalidHandle; | ||
| 1558 | } | ||
| 1493 | 1559 | ||
| 1494 | // Try to start the thread. | 1560 | // Try to start the thread. |
| 1495 | R_TRY(thread->Run()); | 1561 | const auto run_result = thread->Run(); |
| 1562 | if (run_result.IsError()) { | ||
| 1563 | LOG_ERROR(Kernel_SVC, | ||
| 1564 | "Unable to successfuly start thread (thread handle={:08X}, result={})", | ||
| 1565 | thread_handle, run_result.raw); | ||
| 1566 | return run_result; | ||
| 1567 | } | ||
| 1496 | 1568 | ||
| 1497 | return RESULT_SUCCESS; | 1569 | return RESULT_SUCCESS; |
| 1498 | } | 1570 | } |
| @@ -1553,8 +1625,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address, | |||
| 1553 | cv_key, tag, timeout_ns); | 1625 | cv_key, tag, timeout_ns); |
| 1554 | 1626 | ||
| 1555 | // Validate input. | 1627 | // Validate input. |
| 1556 | R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); | 1628 | if (Memory::IsKernelAddress(address)) { |
| 1557 | R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); | 1629 | LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address); |
| 1630 | return ResultInvalidCurrentMemory; | ||
| 1631 | } | ||
| 1632 | if (!Common::IsAligned(address, sizeof(s32))) { | ||
| 1633 | LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address); | ||
| 1634 | return ResultInvalidAddress; | ||
| 1635 | } | ||
| 1558 | 1636 | ||
| 1559 | // Convert timeout from nanoseconds to ticks. | 1637 | // Convert timeout from nanoseconds to ticks. |
| 1560 | s64 timeout{}; | 1638 | s64 timeout{}; |
| @@ -1629,9 +1707,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit | |||
| 1629 | address, arb_type, value, timeout_ns); | 1707 | address, arb_type, value, timeout_ns); |
| 1630 | 1708 | ||
| 1631 | // Validate input. | 1709 | // Validate input. |
| 1632 | R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); | 1710 | if (Memory::IsKernelAddress(address)) { |
| 1633 | R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); | 1711 | LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address); |
| 1634 | R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue); | 1712 | return ResultInvalidCurrentMemory; |
| 1713 | } | ||
| 1714 | if (!Common::IsAligned(address, sizeof(s32))) { | ||
| 1715 | LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address); | ||
| 1716 | return ResultInvalidAddress; | ||
| 1717 | } | ||
| 1718 | if (!IsValidArbitrationType(arb_type)) { | ||
| 1719 | LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type); | ||
| 1720 | return ResultInvalidEnumValue; | ||
| 1721 | } | ||
| 1635 | 1722 | ||
| 1636 | // Convert timeout from nanoseconds to ticks. | 1723 | // Convert timeout from nanoseconds to ticks. |
| 1637 | s64 timeout{}; | 1724 | s64 timeout{}; |
| @@ -1665,9 +1752,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign | |||
| 1665 | address, signal_type, value, count); | 1752 | address, signal_type, value, count); |
| 1666 | 1753 | ||
| 1667 | // Validate input. | 1754 | // Validate input. |
| 1668 | R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); | 1755 | if (Memory::IsKernelAddress(address)) { |
| 1669 | R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress); | 1756 | LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address); |
| 1670 | R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue); | 1757 | return ResultInvalidCurrentMemory; |
| 1758 | } | ||
| 1759 | if (!Common::IsAligned(address, sizeof(s32))) { | ||
| 1760 | LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address); | ||
| 1761 | return ResultInvalidAddress; | ||
| 1762 | } | ||
| 1763 | if (!IsValidSignalType(signal_type)) { | ||
| 1764 | LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type); | ||
| 1765 | return ResultInvalidEnumValue; | ||
| 1766 | } | ||
| 1671 | 1767 | ||
| 1672 | return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value, | 1768 | return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value, |
| 1673 | count); | 1769 | count); |
| @@ -1815,10 +1911,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1815 | // Get the thread from its handle. | 1911 | // Get the thread from its handle. |
| 1816 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1912 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1817 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1913 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 1818 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1914 | if (!thread) { |
| 1915 | LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle); | ||
| 1916 | return ResultInvalidHandle; | ||
| 1917 | } | ||
| 1819 | 1918 | ||
| 1820 | // Get the core mask. | 1919 | // Get the core mask. |
| 1821 | R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); | 1920 | const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask); |
| 1921 | if (result.IsError()) { | ||
| 1922 | LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw); | ||
| 1923 | return result; | ||
| 1924 | } | ||
| 1822 | 1925 | ||
| 1823 | return RESULT_SUCCESS; | 1926 | return RESULT_SUCCESS; |
| 1824 | } | 1927 | } |
| @@ -1846,26 +1949,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle, | |||
| 1846 | } else { | 1949 | } else { |
| 1847 | // Validate the affinity mask. | 1950 | // Validate the affinity mask. |
| 1848 | const u64 process_core_mask = current_process.GetCoreMask(); | 1951 | const u64 process_core_mask = current_process.GetCoreMask(); |
| 1849 | R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, | 1952 | if ((affinity_mask | process_core_mask) != process_core_mask) { |
| 1850 | Svc::ResultInvalidCoreId); | 1953 | LOG_ERROR(Kernel_SVC, |
| 1851 | R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination); | 1954 | "Affinity mask does match the process core mask (affinity mask={:016X}, core " |
| 1955 | "mask={:016X})", | ||
| 1956 | affinity_mask, process_core_mask); | ||
| 1957 | return ResultInvalidCoreId; | ||
| 1958 | } | ||
| 1959 | if (affinity_mask == 0) { | ||
| 1960 | LOG_ERROR(Kernel_SVC, "Affinity mask is zero."); | ||
| 1961 | return ResultInvalidCombination; | ||
| 1962 | } | ||
| 1852 | 1963 | ||
| 1853 | // Validate the core id. | 1964 | // Validate the core id. |
| 1854 | if (IsValidCoreId(core_id)) { | 1965 | if (IsValidCoreId(core_id)) { |
| 1855 | R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination); | 1966 | if (((1ULL << core_id) & affinity_mask) == 0) { |
| 1967 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); | ||
| 1968 | return ResultInvalidCombination; | ||
| 1969 | } | ||
| 1856 | } else { | 1970 | } else { |
| 1857 | R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare, | 1971 | if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) { |
| 1858 | Svc::ResultInvalidCoreId); | 1972 | LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id); |
| 1973 | return ResultInvalidCoreId; | ||
| 1974 | } | ||
| 1859 | } | 1975 | } |
| 1860 | } | 1976 | } |
| 1861 | 1977 | ||
| 1862 | // Get the thread from its handle. | 1978 | // Get the thread from its handle. |
| 1863 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); | 1979 | const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); |
| 1864 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); | 1980 | const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); |
| 1865 | R_UNLESS(thread, Svc::ResultInvalidHandle); | 1981 | if (!thread) { |
| 1982 | LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle); | ||
| 1983 | return ResultInvalidHandle; | ||
| 1984 | } | ||
| 1866 | 1985 | ||
| 1867 | // Set the core mask. | 1986 | // Set the core mask. |
| 1868 | R_TRY(thread->SetCoreMask(core_id, affinity_mask)); | 1987 | const auto set_result = thread->SetCoreMask(core_id, affinity_mask); |
| 1988 | if (set_result.IsError()) { | ||
| 1989 | LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw); | ||
| 1990 | return set_result; | ||
| 1991 | } | ||
| 1869 | 1992 | ||
| 1870 | return RESULT_SUCCESS; | 1993 | return RESULT_SUCCESS; |
| 1871 | } | 1994 | } |
| @@ -1884,7 +2007,10 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) { | |||
| 1884 | 2007 | ||
| 1885 | // Get the writable event. | 2008 | // Get the writable event. |
| 1886 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); | 2009 | auto writable_event = handle_table.Get<KWritableEvent>(event_handle); |
| 1887 | R_UNLESS(writable_event, Svc::ResultInvalidHandle); | 2010 | if (!writable_event) { |
| 2011 | LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle); | ||
| 2012 | return ResultInvalidHandle; | ||
| 2013 | } | ||
| 1888 | 2014 | ||
| 1889 | return writable_event->Signal(); | 2015 | return writable_event->Signal(); |
| 1890 | } | 2016 | } |
| @@ -1933,7 +2059,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o | |||
| 1933 | 2059 | ||
| 1934 | // Create a new event. | 2060 | // Create a new event. |
| 1935 | const auto event = KEvent::Create(kernel, "CreateEvent"); | 2061 | const auto event = KEvent::Create(kernel, "CreateEvent"); |
| 1936 | R_UNLESS(event != nullptr, Svc::ResultOutOfResource); | 2062 | if (!event) { |
| 2063 | LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached."); | ||
| 2064 | return ResultOutOfResource; | ||
| 2065 | } | ||
| 1937 | 2066 | ||
| 1938 | // Initialize the event. | 2067 | // Initialize the event. |
| 1939 | event->Initialize(); | 2068 | event->Initialize(); |