From 3957b0c34e3060277a182c9ade3f4b69c0b7061c Mon Sep 17 00:00:00 2001
From: Subv <subv2112@gmail.com>
Date: Wed, 30 May 2018 12:03:19 -0500
Subject: [PATCH] Kernel/SVC: Support special core values -2 and -3 in
 svcSetThreadCoreMask.

Also added some proper error handling.
---
 src/core/hle/kernel/errors.h |  2 ++
 src/core/hle/kernel/svc.cpp  | 27 ++++++++++++++++++++++++++-
 2 files changed, 28 insertions(+), 1 deletion(-)

diff --git a/src/core/hle/kernel/errors.h b/src/core/hle/kernel/errors.h
index 5be20c8781..e1b5430bfd 100644
--- a/src/core/hle/kernel/errors.h
+++ b/src/core/hle/kernel/errors.h
@@ -21,7 +21,9 @@ enum {
 
     // Confirmed Switch OS error codes
     MisalignedAddress = 102,
+    InvalidProcessorId = 113,
     InvalidHandle = 114,
+    InvalidCombination = 116,
     Timeout = 117,
     SynchronizationCanceled = 118,
     TooLarge = 119,
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 0811a16b80..ec3601e8b6 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -732,7 +732,7 @@ static ResultCode GetThreadCoreMask(Handle thread_handle, u32* core, u64* mask)
 }
 
 static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
-    NGLOG_TRACE(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:08X}, core=0x{:X}", thread_handle,
+    NGLOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, mask=0x{:16X}, core=0x{:X}", thread_handle,
                 mask, core);
 
     const SharedPtr<Thread> thread = g_handle_table.Get<Thread>(thread_handle);
@@ -740,6 +740,31 @@ static ResultCode SetThreadCoreMask(Handle thread_handle, u32 core, u64 mask) {
         return ERR_INVALID_HANDLE;
     }
 
+    if (core == THREADPROCESSORID_DEFAULT) {
+        ASSERT(thread->owner_process->ideal_processor != THREADPROCESSORID_DEFAULT);
+        // Set the target CPU to the one specified in the process' exheader.
+        core = thread->owner_process->ideal_processor;
+        mask = 1 << core;
+    }
+
+    if (mask == 0) {
+        return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+    }
+
+    /// This value is used to only change the affinity mask without changing the current ideal core.
+    static constexpr u32 OnlyChangeMask = static_cast<u32>(-3);
+
+    if (core == OnlyChangeMask) {
+        core = thread->ideal_core;
+    } else if (core >= Core::NUM_CPU_CORES && core != -1) {
+        return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidProcessorId);
+    }
+
+    // Error out if the input core isn't enabled in the input mask.
+    if (core < Core::NUM_CPU_CORES && (mask & (1 << core)) == 0) {
+        return ResultCode(ErrorModule::Kernel, ErrCodes::InvalidCombination);
+    }
+
     thread->ChangeCore(core, mask);
 
     return RESULT_SUCCESS;
-- 
GitLab