aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 11:29:20 -0400
committerTakoroka <137927095+Takoroka@users.noreply.github.com>2026-10-28 11:29:20 -0400
commit3b1639daa3650faf1b56906524b75f019f707f00 (patch)
tree6c95deff575a0de9be2768dc5002fcb1117c792b /src
parent12cca280bf750eb7674fd055428f1f7c65deed42 (diff)
core: emulate six CPU cores
Switch 2 applications are given cores 0..5 (title 4's npdm) and start a job worker per core. With four emulated cores, 4 and 5 were folded onto 0 and 1, so two cores ran two workers each. Switch 1 titles keep using cores 0..3; core 3 stays the shared system core.
Diffstat (limited to 'src')
-rw-r--r--src/core/hardware_properties.h7
-rw-r--r--src/core/hle/kernel/global_scheduler_context.cpp5
-rw-r--r--src/core/hle/kernel/kernel.cpp2
-rw-r--r--src/core/hle/kernel/svc/svc_thread.cpp4
-rw-r--r--src/dynarmic/src/dynarmic/interface/exclusive_monitor.h2
5 files changed, 13 insertions, 7 deletions
diff --git a/src/core/hardware_properties.h b/src/core/hardware_properties.h
index 3f870becbf..aeea5f858f 100644
--- a/src/core/hardware_properties.h
+++ b/src/core/hardware_properties.h
@@ -15,11 +15,14 @@ namespace Hardware {
constexpr u64 BASE_CLOCK_RATE = 1'020'000'000; // Default CPU Frequency = 1020 MHz
constexpr u64 CNTFREQ = 19'200'000; // CNTPCT_EL0 Frequency = 19.2 MHz
-constexpr u32 NUM_CPU_CORES = 4; // Number of CPU Cores - sync with dynarmic exclusive_monitor.h
+// Switch 1 applications get cores 0..3. Switch 2 applications ask for 0..5 (title 4's npdm), and
+// its job system starts a worker per core, so emulate six: with four, cores 0 and 1 each ran two
+// of its workers. Switch 1 titles leave cores 4 and 5 idle.
+constexpr u32 NUM_CPU_CORES = 6; // Number of CPU Cores - sync with dynarmic exclusive_monitor.h
// Virtual to Physical core map.
constexpr std::array<s32, Common::BitSize<u64>()> VirtualToPhysicalCoreMap{
- 0, 1, 2, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3,
};
diff --git a/src/core/hle/kernel/global_scheduler_context.cpp b/src/core/hle/kernel/global_scheduler_context.cpp
index 6d1cd030e0..98d14c8549 100644
--- a/src/core/hle/kernel/global_scheduler_context.cpp
+++ b/src/core/hle/kernel/global_scheduler_context.cpp
@@ -40,12 +40,15 @@ void GlobalSchedulerContext::RemoveThread(KThread* thread) noexcept {
/// @note This operation happens every 10ms.
void GlobalSchedulerContext::PreemptThreads(KernelCore& kernel) noexcept {
// The priority levels at which the global scheduler preempts threads every 10 ms. They are
- // ordered from Core 0 to Core 3.
+ // ordered from Core 0 to Core 5; core 3 is shared with the system, 4 and 5 are application
+ // cores like 0..2.
static constexpr std::array<u32, Core::Hardware::NUM_CPU_CORES> per_core{
59,
59,
59,
63,
+ 59,
+ 59,
};
ASSERT(KScheduler::IsSchedulerLockedByCurrentThread(kernel));
for (u32 core_id = 0; core_id < per_core.size(); core_id++)
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 4f1d849209..b437dd4b4e 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -171,7 +171,7 @@ struct KernelCore::Impl {
schedulers[core_id].reset();
}
- // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
+ // Next host thead ID to use, IDs below NUM_CPU_CORES represent core threads, the rest others
next_host_thread_id = Core::Hardware::NUM_CPU_CORES;
// Close kernel objects that were not freed on shutdown
diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp
index 9838e68476..7f6b959256 100644
--- a/src/core/hle/kernel/svc/svc_thread.cpp
+++ b/src/core/hle/kernel/svc/svc_thread.cpp
@@ -20,8 +20,8 @@ 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.
+// Switch 2 hardware has eight cores. Six are emulated (the most an application is given), so
+// fold any id past them back onto the low cores, 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;
diff --git a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h
index 05b067bdd8..46fce86bda 100644
--- a/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h
+++ b/src/dynarmic/src/dynarmic/interface/exclusive_monitor.h
@@ -82,7 +82,7 @@ private:
static constexpr VAddr RESERVATION_GRANULE_MASK = 0xFFFF'FFFF'FFFF'FFFFull;
static constexpr VAddr INVALID_EXCLUSIVE_ADDRESS = 0xDEAD'DEAD'DEAD'DEADull;
- static constexpr size_t MAX_NUM_CPU_CORES = 4; // Sync with src/core/hardware_properties
+ static constexpr size_t MAX_NUM_CPU_CORES = 6; // Sync with src/core/hardware_properties
boost::container::static_vector<VAddr, MAX_NUM_CPU_CORES> exclusive_addresses;
boost::container::static_vector<Vector, MAX_NUM_CPU_CORES> exclusive_values;
SpinLock lock;