aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-27 12:52:39 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-27 12:52:39 -0400
commit017db199f45384d2889e1a5dcc0ca6f0fff3aa8b (patch)
tree88127792e40461e00fe7987e673391ed73b6c911 /src
parent13699c7328657248fdec8155b3dc68fe96241fa5 (diff)
kernel: fold Switch 2 virtual cores 4/5 onto emulated cores
Switch 2 titles get core mask 0x3f and nn::oe creates a thread on core 5. Eden emulates four cores, so fold virtual cores 4..7 onto 0..3 in CreateThread and SetThreadCoreMask (after validating against the real process mask).
Diffstat (limited to 'src')
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp17
1 files changed, 17 insertions, 0 deletions
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index dbca13dd26..9838e68476 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -20,6 +20,18 @@ constexpr bool IsValidVirtualCoreId(int32_t core_id) {
return (0 <= core_id && core_id < static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES));
}
+// Switch 2 processes may be given virtual cores 4 and 5 (core mask 0x3f). Only four cores are
+// emulated, so fold the extra ones back onto 0..3, both in core ids and in affinity masks.
+constexpr int32_t FoldExtraCoreId(int32_t core_id) {
+ constexpr auto num_cores = static_cast<int32_t>(Core::Hardware::NUM_CPU_CORES);
+ return core_id >= num_cores && core_id < 2 * num_cores ? core_id - num_cores : core_id;
+}
+
+constexpr u64 FoldExtraCoreMask(u64 mask) {
+ constexpr u64 low = (1ULL << Core::Hardware::NUM_CPU_CORES) - 1;
+ return (mask & low) | ((mask >> Core::Hardware::NUM_CPU_CORES) & low);
+}
+
} // Anonymous namespace
/// Creates a new thread
@@ -36,6 +48,7 @@ Result CreateThread(Core::System& system, Handle* out_handle, u64 entry_point, u
if (core_id == IdealCoreUseProcessValue) {
core_id = process.GetIdealCoreId();
}
+ core_id = FoldExtraCoreId(core_id);
// Validate arguments.
R_UNLESS(IsValidVirtualCoreId(core_id), ResultInvalidCoreId);
@@ -261,6 +274,10 @@ Result SetThreadCoreMask(Core::System& system, Handle thread_handle, s32 core_id
R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, ResultInvalidCoreId);
R_UNLESS(affinity_mask != 0, ResultInvalidCombination);
+ // Validated against the real mask above; fold to the emulated cores from here on.
+ affinity_mask = FoldExtraCoreMask(affinity_mask);
+ core_id = FoldExtraCoreId(core_id);
+
// Validate the core id.
if (IsValidVirtualCoreId(core_id)) {
R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, ResultInvalidCombination);