diff options
| author | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 12:52:39 -0400 |
|---|---|---|
| committer | Takoroka <137927095+Takoroka@users.noreply.github.com> | 2026-10-27 12:52:39 -0400 |
| commit | 017db199f45384d2889e1a5dcc0ca6f0fff3aa8b (patch) | |
| tree | 88127792e40461e00fe7987e673391ed73b6c911 /src/core/hle/kernel | |
| parent | 13699c7328657248fdec8155b3dc68fe96241fa5 (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/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/svc/svc_thread.cpp | 17 |
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); |
