From a61e0cf970f656349fe4cfce7ab9bd8210294d5c Mon Sep 17 00:00:00 2001 From: pineappleEA Date: Thu, 3 Aug 2023 02:08:37 +0200 Subject: [PATCH] early-access version 3790 --- README.md | 2 +- src/core/arm/dynarmic/arm_dynarmic_32.cpp | 2 +- src/core/arm/dynarmic/arm_dynarmic_64.cpp | 2 +- src/core/core.cpp | 38 ++++++-- src/core/core.h | 23 ++++- src/core/cpu_manager.cpp | 22 +++-- src/core/hle/kernel/k_address_arbiter.cpp | 4 +- src/core/hle/kernel/k_condition_variable.cpp | 2 +- src/core/hle/kernel/k_process.cpp | 19 ---- src/core/hle/kernel/k_process.h | 13 --- src/core/hle/kernel/k_scheduler.cpp | 33 +++---- src/core/hle/kernel/k_thread.cpp | 4 +- src/core/hle/kernel/kernel.cpp | 57 ++++++------ src/core/hle/kernel/kernel.h | 13 ++- src/core/hle/kernel/physical_core.cpp | 92 +++++++++---------- src/core/hle/kernel/physical_core.h | 39 ++++++-- src/core/hle/kernel/svc.cpp | 8 +- src/core/hle/kernel/svc/svc_exception.cpp | 4 +- src/core/hle/kernel/svc/svc_light_ipc.cpp | 2 +- src/core/hle/kernel/svc/svc_processor.cpp | 2 +- .../kernel/svc/svc_secure_monitor_call.cpp | 4 +- src/core/hle/kernel/svc/svc_thread.cpp | 2 + src/core/hle/kernel/svc_generator.py | 8 +- src/core/hle/service/am/am.cpp | 44 +++++++++ src/core/hle/service/am/am.h | 6 ++ src/core/hle/service/am/applet_ae.cpp | 8 +- src/core/memory.cpp | 3 +- src/core/reporter.cpp | 4 +- 28 files changed, 270 insertions(+), 190 deletions(-) diff --git a/README.md b/README.md index 23fdce162..32d8b7893 100755 --- a/README.md +++ b/README.md @@ -1,7 +1,7 @@ yuzu emulator early access ============= -This is the source code for early-access 3789. +This is the source code for early-access 3790. ## Legal Notice diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 0bea0f516..0e5359904 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp @@ -188,7 +188,7 @@ public: } bool IsInterrupted() { - return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted(); + return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); } ARM_Dynarmic_32& parent; diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index e24813da7..94521260b 100755 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp @@ -233,7 +233,7 @@ public: } bool IsInterrupted() { - return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted(); + return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); } ARM_Dynarmic_64& parent; diff --git a/src/core/core.cpp b/src/core/core.cpp index 6c65ad53a..af042d808 100755 --- a/src/core/core.cpp +++ b/src/core/core.cpp @@ -14,6 +14,7 @@ #include "common/settings.h" #include "common/settings_enums.h" #include "common/string_util.h" +#include "core/arm/exclusive_monitor.h" #include "core/core.h" #include "core/core_timing.h" #include "core/cpu_manager.h" @@ -326,6 +327,7 @@ struct System::Impl { static_cast(SystemResultStatus::ErrorLoader) + static_cast(load_result)); } AddGlueRegistrationForProcess(*app_loader, *main_process); + kernel.InitializeCores(); // Initialize cheat engine if (cheat_engine) { @@ -642,6 +644,10 @@ bool System::IsPoweredOn() const { return impl->is_powered_on.load(std::memory_order::relaxed); } +void System::PrepareReschedule(const u32 core_index) { + impl->kernel.PrepareReschedule(core_index); +} + Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() { const std::size_t core = impl->kernel.GetCurrentHostThreadID(); return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES @@ -679,6 +685,14 @@ const TelemetrySession& System::TelemetrySession() const { return *impl->telemetry_session; } +ARM_Interface& System::CurrentArmInterface() { + return impl->kernel.CurrentPhysicalCore().ArmInterface(); +} + +const ARM_Interface& System::CurrentArmInterface() const { + return impl->kernel.CurrentPhysicalCore().ArmInterface(); +} + Kernel::PhysicalCore& System::CurrentPhysicalCore() { return impl->kernel.CurrentPhysicalCore(); } @@ -687,14 +701,6 @@ const Kernel::PhysicalCore& System::CurrentPhysicalCore() const { return impl->kernel.CurrentPhysicalCore(); } -Core::ExclusiveMonitor& System::GetCurrentExclusiveMonitor() { - return impl->kernel.GetCurrentExclusiveMonitor(); -} - -Core::ARM_Interface& System::GetCurrentArmInterface() { - return impl->kernel.GetCurrentArmInterface(); -} - /// Gets the global scheduler Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() { return impl->kernel.GlobalSchedulerContext(); @@ -721,6 +727,22 @@ const Kernel::KProcess* System::ApplicationProcess() const { return impl->kernel.ApplicationProcess(); } +ARM_Interface& System::ArmInterface(std::size_t core_index) { + return impl->kernel.PhysicalCore(core_index).ArmInterface(); +} + +const ARM_Interface& System::ArmInterface(std::size_t core_index) const { + return impl->kernel.PhysicalCore(core_index).ArmInterface(); +} + +ExclusiveMonitor& System::Monitor() { + return impl->kernel.GetExclusiveMonitor(); +} + +const ExclusiveMonitor& System::Monitor() const { + return impl->kernel.GetExclusiveMonitor(); +} + Memory::Memory& System::ApplicationMemory() { return impl->memory; } diff --git a/src/core/core.h b/src/core/core.h index b79000344..58fa9ab4e 100755 --- a/src/core/core.h +++ b/src/core/core.h @@ -223,6 +223,9 @@ public: /// Gets a reference to the telemetry session for this emulation session. [[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; + /// Prepare the core emulation for a reschedule + void PrepareReschedule(u32 core_index); + /// Provides a reference to the gou dirty memory manager. [[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager(); @@ -236,17 +239,23 @@ public: /// Gets and resets core performance statistics [[nodiscard]] PerfStatsResults GetAndResetPerfStats(); + /// Gets an ARM interface to the CPU core that is currently running + [[nodiscard]] ARM_Interface& CurrentArmInterface(); + + /// Gets an ARM interface to the CPU core that is currently running + [[nodiscard]] const ARM_Interface& CurrentArmInterface() const; + /// Gets the physical core for the CPU core that is currently running [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); /// Gets the physical core for the CPU core that is currently running [[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const; - /// Gets the exclusive monitor for the process on the current core - Core::ExclusiveMonitor& GetCurrentExclusiveMonitor(); + /// Gets a reference to an ARM interface for the CPU core with the specified index + [[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index); - /// Gets the JIT instance for the process on the current core - Core::ARM_Interface& GetCurrentArmInterface(); + /// Gets a const reference to an ARM interface from the CPU core with the specified index + [[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const; /// Gets a reference to the underlying CPU manager. [[nodiscard]] CpuManager& GetCpuManager(); @@ -254,6 +263,12 @@ public: /// Gets a const reference to the underlying CPU manager [[nodiscard]] const CpuManager& GetCpuManager() const; + /// Gets a reference to the exclusive monitor + [[nodiscard]] ExclusiveMonitor& Monitor(); + + /// Gets a constant reference to the exclusive monitor + [[nodiscard]] const ExclusiveMonitor& Monitor() const; + /// Gets a mutable reference to the system memory instance. [[nodiscard]] Core::Memory::Memory& ApplicationMemory(); diff --git a/src/core/cpu_manager.cpp b/src/core/cpu_manager.cpp index 20f5c3242..60f2566bf 100755 --- a/src/core/cpu_manager.cpp +++ b/src/core/cpu_manager.cpp @@ -9,7 +9,6 @@ #include "core/core_timing.h" #include "core/cpu_manager.h" #include "core/hle/kernel/k_interrupt_manager.h" -#include "core/hle/kernel/k_process.h" #include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/kernel.h" @@ -74,15 +73,13 @@ void CpuManager::HandleInterrupt() { void CpuManager::MultiCoreRunGuestThread() { // Similar to UserModeThreadStarter in HOS auto& kernel = system.Kernel(); - auto& process = Kernel::GetCurrentProcess(kernel); kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex()); - - if (physical_core->Run(*arm_interface)) { - continue; + while (!physical_core->IsInterrupted()) { + physical_core->Run(); + physical_core = &kernel.CurrentPhysicalCore(); } HandleInterrupt(); @@ -98,7 +95,11 @@ void CpuManager::MultiCoreRunIdleThread() { kernel.CurrentScheduler()->OnThreadStart(); while (true) { - kernel.CurrentPhysicalCore().WaitForInterrupt(); + auto& physical_core = kernel.CurrentPhysicalCore(); + if (!physical_core.IsInterrupted()) { + physical_core.Idle(); + } + HandleInterrupt(); } } @@ -109,13 +110,14 @@ void CpuManager::MultiCoreRunIdleThread() { void CpuManager::SingleCoreRunGuestThread() { auto& kernel = system.Kernel(); - auto& process = Kernel::GetCurrentProcess(kernel); kernel.CurrentScheduler()->OnThreadStart(); while (true) { auto* physical_core = &kernel.CurrentPhysicalCore(); - auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex()); - physical_core->Run(*arm_interface); + if (!physical_core->IsInterrupted()) { + physical_core->Run(); + physical_core = &kernel.CurrentPhysicalCore(); + } kernel.SetIsPhantomModeForSingleCore(true); system.CoreTiming().Advance(); diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp index deb98c263..18dd2cb45 100755 --- a/src/core/hle/kernel/k_address_arbiter.cpp +++ b/src/core/hle/kernel/k_address_arbiter.cpp @@ -27,7 +27,7 @@ bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) { } bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) { - auto& monitor = system.GetCurrentExclusiveMonitor(); + auto& monitor = system.Monitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. @@ -68,7 +68,7 @@ bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 value, s32 new_value) { - auto& monitor = system.GetCurrentExclusiveMonitor(); + auto& monitor = system.Monitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); // NOTE: If scheduler lock is not held here, interrupt disable is required. diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp index e4449a948..c848b6093 100755 --- a/src/core/hle/kernel/k_condition_variable.cpp +++ b/src/core/hle/kernel/k_condition_variable.cpp @@ -30,7 +30,7 @@ bool WriteToUser(KernelCore& kernel, KProcessAddress address, const u32* p) { bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u32 if_zero, u32 new_orr_mask) { - auto& monitor = system.GetCurrentExclusiveMonitor(); + auto& monitor = system.Monitor(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); u32 expected{}; diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp index d888bd450..4b96180dd 100755 --- a/src/core/hle/kernel/k_process.cpp +++ b/src/core/hle/kernel/k_process.cpp @@ -11,9 +11,6 @@ #include "common/logging/log.h" #include "common/scope_exit.h" #include "common/settings.h" -#include "core/arm/dynarmic/arm_dynarmic_32.h" -#include "core/arm/dynarmic/arm_dynarmic_64.h" -#include "core/arm/dynarmic/dynarmic_exclusive_monitor.h" #include "core/core.h" #include "core/file_sys/program_metadata.h" #include "core/hle/kernel/code_set.h" @@ -430,22 +427,6 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) { this->ChangeState(State::Running); - auto exclusive_monitor = std::make_unique( - m_kernel.System().ApplicationMemory(), Core::Hardware::NUM_CPU_CORES); - for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { - if (m_is_64bit_process) { - m_arm_interfaces[i] = std::make_unique( - m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i); - } else { - m_arm_interfaces[i] = std::make_unique( - m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i); - } - - this->GetMemory().SetCurrentPageTable(*this, static_cast(i)); - } - - m_exclusive_monitor = std::move(exclusive_monitor); - SetupMainThread(m_kernel.System(), *this, main_thread_priority, m_main_thread_stack_top); } diff --git a/src/core/hle/kernel/k_process.h b/src/core/hle/kernel/k_process.h index 6eaef2445..04d8880fc 100755 --- a/src/core/hle/kernel/k_process.h +++ b/src/core/hle/kernel/k_process.h @@ -407,14 +407,6 @@ public: return name; } - Core::ExclusiveMonitor* GetExclusiveMonitor() { - return m_exclusive_monitor.get(); - } - - Core::ARM_Interface* GetArmInterface(size_t i) { - return m_arm_interfaces[i].get(); - } - private: void PinThread(s32 core_id, KThread* thread) { ASSERT(0 <= core_id && core_id < static_cast(Core::Hardware::NUM_CPU_CORES)); @@ -545,11 +537,6 @@ private: using TLPIterator = TLPTree::iterator; TLPTree m_fully_used_tlp_tree; TLPTree m_partially_used_tlp_tree; - -private: - std::unique_ptr m_exclusive_monitor{}; - std::array, Core::Hardware::NUM_CPU_CORES> - m_arm_interfaces{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/k_scheduler.cpp b/src/core/hle/kernel/k_scheduler.cpp index 23c83cbd7..239f5c6c9 100755 --- a/src/core/hle/kernel/k_scheduler.cpp +++ b/src/core/hle/kernel/k_scheduler.cpp @@ -494,15 +494,12 @@ void KScheduler::ScheduleImplFiber() { } void KScheduler::Unload(KThread* thread) { - if (thread->GetThreadType() == ThreadType::User) { - auto* process = thread->GetOwnerProcess(); - auto& cpu_core = *process->GetArmInterface(m_core_id); - cpu_core.SaveContext(thread->GetContext32()); - cpu_core.SaveContext(thread->GetContext64()); - // Save the TPIDR_EL0 system register in case it was modified. - thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0()); - cpu_core.ClearExclusiveState(); - } + auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); + cpu_core.SaveContext(thread->GetContext32()); + cpu_core.SaveContext(thread->GetContext64()); + // Save the TPIDR_EL0 system register in case it was modified. + thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0()); + cpu_core.ClearExclusiveState(); // Check if the thread is terminated by checking the DPC flags. if ((thread->GetStackParameters().dpc_flags & static_cast(DpcFlag::Terminated)) == 0) { @@ -512,16 +509,14 @@ void KScheduler::Unload(KThread* thread) { } void KScheduler::Reload(KThread* thread) { - if (thread->GetThreadType() == ThreadType::User) { - auto* process = thread->GetOwnerProcess(); - auto& cpu_core = *process->GetArmInterface(m_core_id); - cpu_core.LoadContext(thread->GetContext32()); - cpu_core.LoadContext(thread->GetContext64()); - cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); - cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); - cpu_core.LoadWatchpointArray(&process->GetWatchpoints()); - cpu_core.ClearExclusiveState(); - } + auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); + auto* process = thread->GetOwnerProcess(); + cpu_core.LoadContext(thread->GetContext32()); + cpu_core.LoadContext(thread->GetContext64()); + cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); + cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); + cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr); + cpu_core.ClearExclusiveState(); } void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp index 1eefaf364..a49a0e97f 100755 --- a/src/core/hle/kernel/k_thread.cpp +++ b/src/core/hle/kernel/k_thread.cpp @@ -823,14 +823,14 @@ void KThread::CloneFpuStatus() { if (this->GetOwnerProcess()->Is64BitProcess()) { // Clone FPSR and FPCR. ThreadContext64 cur_ctx{}; - m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx); + m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); this->GetContext64().fpcr = cur_ctx.fpcr; this->GetContext64().fpsr = cur_ctx.fpsr; } else { // Clone FPSCR. ThreadContext32 cur_ctx{}; - m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx); + m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); this->GetContext32().fpscr = cur_ctx.fpscr; } diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 97e18bb23..42c13e7df 100755 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -99,6 +99,13 @@ struct KernelCore::Impl { RegisterHostThread(nullptr); } + void InitializeCores() { + for (u32 core_id = 0; core_id < Core::Hardware::NUM_CPU_CORES; core_id++) { + cores[core_id]->Initialize((*application_process).Is64BitProcess()); + system.ApplicationMemory().SetCurrentPageTable(*application_process, core_id); + } + } + void CloseApplicationProcess() { KProcess* old_process = application_process.exchange(nullptr); if (old_process == nullptr) { @@ -130,6 +137,8 @@ struct KernelCore::Impl { preemption_event = nullptr; + exclusive_monitor.reset(); + // Cleanup persistent kernel objects auto CleanupObject = [](KAutoObject* obj) { if (obj) { @@ -196,11 +205,13 @@ struct KernelCore::Impl { } void InitializePhysicalCores() { + exclusive_monitor = + Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES); for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { const s32 core{static_cast(i)}; schedulers[i] = std::make_unique(system.Kernel()); - cores[i] = std::make_unique(i, system); + cores[i] = std::make_unique(i, system, *schedulers[i]); auto* main_thread{Kernel::KThread::Create(system.Kernel())}; main_thread->SetCurrentCore(core); @@ -793,6 +804,7 @@ struct KernelCore::Impl { std::mutex server_lock; std::vector> server_managers; + std::unique_ptr exclusive_monitor; std::array, Core::Hardware::NUM_CPU_CORES> cores; // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others @@ -853,6 +865,10 @@ void KernelCore::Initialize() { impl->Initialize(*this); } +void KernelCore::InitializeCores() { + impl->InitializeCores(); +} + void KernelCore::Shutdown() { impl->Shutdown(); } @@ -950,12 +966,12 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() { return *impl->hardware_timer; } -Core::ExclusiveMonitor& KernelCore::GetCurrentExclusiveMonitor() { - return *GetCurrentProcess(*this).GetExclusiveMonitor(); +Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { + return *impl->exclusive_monitor; } -Core::ARM_Interface& KernelCore::GetCurrentArmInterface() { - return *GetCurrentProcess(*this).GetArmInterface(this->CurrentPhysicalCoreIndex()); +const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { + return *impl->exclusive_monitor; } KAutoObjectWithListContainer& KernelCore::ObjectListContainer() { @@ -967,35 +983,24 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const { } void KernelCore::InvalidateAllInstructionCaches() { - // TODO: we need to make sure the JIT is not running during this - auto process = this->ApplicationProcess(); - if (process == nullptr) { - return; - } - - for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { - auto* arm_interface = process->GetArmInterface(i); - if (arm_interface) { - arm_interface->ClearInstructionCache(); - } + for (auto& physical_core : impl->cores) { + physical_core->ArmInterface().ClearInstructionCache(); } } void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) { - // TODO: we need to make sure the JIT is not running during this - auto process = this->ApplicationProcess(); - if (process == nullptr) { - return; - } - - for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { - auto* arm_interface = process->GetArmInterface(i); - if (arm_interface) { - arm_interface->InvalidateCacheRange(GetInteger(addr), size); + for (auto& physical_core : impl->cores) { + if (!physical_core->IsInitialized()) { + continue; } + physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size); } } +void KernelCore::PrepareReschedule(std::size_t id) { + // TODO: Reimplement, this +} + void KernelCore::RegisterKernelObject(KAutoObject* object) { std::scoped_lock lk{impl->registered_objects_lock}; impl->registered_objects.insert(object); diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 5636931f2..d035ced10 100755 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -18,7 +18,6 @@ #include "core/hle/kernel/svc_common.h" namespace Core { -class ARM_Interface; class ExclusiveMonitor; class System; } // namespace Core @@ -105,6 +104,9 @@ public: /// Resets the kernel to a clean slate for use. void Initialize(); + /// Initializes the CPU cores. + void InitializeCores(); + /// Clears all resources in use by the kernel instance. void Shutdown(); @@ -171,11 +173,12 @@ public: /// Gets the an instance of the hardware timer. Kernel::KHardwareTimer& HardwareTimer(); - /// Gets the exclusive monitor for the process on the current core - Core::ExclusiveMonitor& GetCurrentExclusiveMonitor(); + /// Stops execution of 'id' core, in order to reschedule a new thread. + void PrepareReschedule(std::size_t id); - /// Gets the JIT instance for the process on the current core - Core::ARM_Interface& GetCurrentArmInterface(); + Core::ExclusiveMonitor& GetExclusiveMonitor(); + + const Core::ExclusiveMonitor& GetExclusiveMonitor() const; KAutoObjectWithListContainer& ObjectListContainer(); diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 527dfcf3a..a8512a061 100755 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -4,77 +4,69 @@ #include "core/arm/dynarmic/arm_dynarmic_32.h" #include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/core.h" -#include "core/hle/kernel/k_process.h" +#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/kernel.h" #include "core/hle/kernel/physical_core.h" namespace Kernel { -PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system) - : m_core_index{core_index}, m_system{system} {} +PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KScheduler& scheduler) + : m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { +#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) + // TODO(bunnei): Initialization relies on a core being available. We may later replace this with + // a 32-bit instance of Dynarmic. This should be abstracted out to a CPU manager. + auto& kernel = system.Kernel(); + m_arm_interface = std::make_unique( + system, kernel.IsMulticore(), + reinterpret_cast(kernel.GetExclusiveMonitor()), + m_core_index); +#else +#error Platform not supported yet. +#endif +} PhysicalCore::~PhysicalCore() = default; -bool PhysicalCore::Run(Core::ARM_Interface& current_arm_interface) { - // SAFETY: we need to lock around storing the JIT instance member to serialize - // access with another thread that wants to send us an interrupt. Otherwise we - // may end up sending an interrupt to an instance that is not current. - - // Mark the instance as current. - { - std::scoped_lock lk{m_guard}; - - // If this core is already interrupted, return immediately. - if (m_is_interrupted) { - return false; - } - - m_current_arm_interface = std::addressof(current_arm_interface); - } - - // Run the instance. - current_arm_interface.Run(); - current_arm_interface.ClearExclusiveState(); - - { - std::scoped_lock lk{m_guard}; - - // Mark the instance as no longer current. - m_current_arm_interface = nullptr; - - // Return whether we ran to completion. - return !m_is_interrupted; +void PhysicalCore::Initialize(bool is_64_bit) { +#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) + auto& kernel = m_system.Kernel(); + if (!is_64_bit) { + // We already initialized a 64-bit core, replace with a 32-bit one. + m_arm_interface = std::make_unique( + m_system, kernel.IsMulticore(), + reinterpret_cast(kernel.GetExclusiveMonitor()), + m_core_index); } +#else +#error Platform not supported yet. +#endif } -void PhysicalCore::WaitForInterrupt() { - // Wait for a signal. +void PhysicalCore::Run() { + m_arm_interface->Run(); + m_arm_interface->ClearExclusiveState(); +} + +void PhysicalCore::Idle() { std::unique_lock lk{m_guard}; m_on_interrupt.wait(lk, [this] { return m_is_interrupted; }); } +bool PhysicalCore::IsInterrupted() const { + return m_is_interrupted; +} + void PhysicalCore::Interrupt() { - { - std::scoped_lock lk{m_guard}; - - // Mark as interrupted. - m_is_interrupted = true; - - // If we are currently executing code, interrupt the JIT. - if (m_current_arm_interface) { - m_current_arm_interface->SignalInterrupt(); - } - } - - // Signal. + std::unique_lock lk{m_guard}; + m_is_interrupted = true; + m_arm_interface->SignalInterrupt(); m_on_interrupt.notify_all(); } void PhysicalCore::ClearInterrupt() { - std::scoped_lock lk{m_guard}; - - // Remove interrupt flag. + std::unique_lock lk{m_guard}; m_is_interrupted = false; + m_arm_interface->ClearInterrupt(); } } // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index eb6ab45c7..18f8891d6 100755 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -23,16 +23,19 @@ namespace Kernel { class PhysicalCore { public: - PhysicalCore(std::size_t core_index_, Core::System& system_); + PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_); ~PhysicalCore(); YUZU_NON_COPYABLE(PhysicalCore); YUZU_NON_MOVEABLE(PhysicalCore); - /// Execute JIT and return whether we ran to completion - bool Run(Core::ARM_Interface& current_arm_interface); + /// Initialize the core for the specified parameters. + void Initialize(bool is_64_bit); - void WaitForInterrupt(); + /// Execute current jit state + void Run(); + + void Idle(); /// Interrupt this physical core. void Interrupt(); @@ -40,22 +43,42 @@ public: /// Clear this core's interrupt void ClearInterrupt(); - bool GetIsInterrupted() const { - return m_is_interrupted; + /// Check if this core is interrupted + bool IsInterrupted() const; + + bool IsInitialized() const { + return m_arm_interface != nullptr; } - std::size_t GetCoreIndex() const { + Core::ARM_Interface& ArmInterface() { + return *m_arm_interface; + } + + const Core::ARM_Interface& ArmInterface() const { + return *m_arm_interface; + } + + std::size_t CoreIndex() const { return m_core_index; } + Kernel::KScheduler& Scheduler() { + return m_scheduler; + } + + const Kernel::KScheduler& Scheduler() const { + return m_scheduler; + } + private: const std::size_t m_core_index; Core::System& m_system; + Kernel::KScheduler& m_scheduler; std::mutex m_guard; std::condition_variable m_on_interrupt; + std::unique_ptr m_arm_interface; bool m_is_interrupted{}; - Core::ARM_Interface* m_current_arm_interface{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp index d48a6304e..0d5f7d0b7 100755 --- a/src/core/hle/kernel/svc.cpp +++ b/src/core/hle/kernel/svc.cpp @@ -13,19 +13,19 @@ namespace Kernel::Svc { static uint32_t GetReg32(Core::System& system, int n) { - return static_cast(system.GetCurrentArmInterface().GetReg(n)); + return static_cast(system.CurrentArmInterface().GetReg(n)); } static void SetReg32(Core::System& system, int n, uint32_t result) { - system.GetCurrentArmInterface().SetReg(n, static_cast(result)); + system.CurrentArmInterface().SetReg(n, static_cast(result)); } static uint64_t GetReg64(Core::System& system, int n) { - return system.GetCurrentArmInterface().GetReg(n); + return system.CurrentArmInterface().GetReg(n); } static void SetReg64(Core::System& system, int n, uint64_t result) { - system.GetCurrentArmInterface().SetReg(n, result); + system.CurrentArmInterface().SetReg(n, result); } // Like bit_cast, but handles the case when the source and dest diff --git a/src/core/hle/kernel/svc/svc_exception.cpp b/src/core/hle/kernel/svc/svc_exception.cpp index cc7c9ce7d..580cf2f75 100755 --- a/src/core/hle/kernel/svc/svc_exception.cpp +++ b/src/core/hle/kernel/svc/svc_exception.cpp @@ -102,7 +102,9 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) { handle_debug_buffer(info1, info2); - system.GetCurrentArmInterface().LogBacktrace(); + auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); + const auto thread_processor_id = current_thread->GetActiveCore(); + system.ArmInterface(static_cast(thread_processor_id)).LogBacktrace(); } if (system.DebuggerEnabled()) { diff --git a/src/core/hle/kernel/svc/svc_light_ipc.cpp b/src/core/hle/kernel/svc/svc_light_ipc.cpp index 9add82d5f..b76ce984c 100755 --- a/src/core/hle/kernel/svc/svc_light_ipc.cpp +++ b/src/core/hle/kernel/svc/svc_light_ipc.cpp @@ -38,7 +38,7 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle, template static void SvcWrap_LightIpc(Core::System& system, F&& cb) { - auto& core = system.GetCurrentArmInterface(); + auto& core = system.CurrentArmInterface(); std::array arguments{}; Handle session_handle = static_cast(core.GetReg(0)); diff --git a/src/core/hle/kernel/svc/svc_processor.cpp b/src/core/hle/kernel/svc/svc_processor.cpp index c795b9a22..7602ce6c0 100755 --- a/src/core/hle/kernel/svc/svc_processor.cpp +++ b/src/core/hle/kernel/svc/svc_processor.cpp @@ -11,7 +11,7 @@ namespace Kernel::Svc { /// Get which CPU core is executing the current thread int32_t GetCurrentProcessorNumber(Core::System& system) { LOG_TRACE(Kernel_SVC, "called"); - return static_cast(system.CurrentPhysicalCore().GetCoreIndex()); + return static_cast(system.CurrentPhysicalCore().CoreIndex()); } int32_t GetCurrentProcessorNumber64(Core::System& system) { diff --git a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp index 0dbc88b80..62c781551 100755 --- a/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp +++ b/src/core/hle/kernel/svc/svc_secure_monitor_call.cpp @@ -23,7 +23,7 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen // Custom ABI for CallSecureMonitor. void SvcWrap_CallSecureMonitor64(Core::System& system) { - auto& core = system.GetCurrentArmInterface(); + auto& core = system.CurrentPhysicalCore().ArmInterface(); lp64::SecureMonitorArguments args{}; for (int i = 0; i < 8; i++) { args.r[i] = core.GetReg(i); @@ -37,7 +37,7 @@ void SvcWrap_CallSecureMonitor64(Core::System& system) { } void SvcWrap_CallSecureMonitor64From32(Core::System& system) { - auto& core = system.GetCurrentArmInterface(); + auto& core = system.CurrentPhysicalCore().ArmInterface(); ilp32::SecureMonitorArguments args{}; for (int i = 0; i < 8; i++) { args.r[i] = static_cast(core.GetReg(i)); diff --git a/src/core/hle/kernel/svc/svc_thread.cpp b/src/core/hle/kernel/svc/svc_thread.cpp index 688d9e817..92bcea72b 100755 --- a/src/core/hle/kernel/svc/svc_thread.cpp +++ b/src/core/hle/kernel/svc/svc_thread.cpp @@ -93,6 +93,8 @@ Result StartThread(Core::System& system, Handle thread_handle) { /// Called when a thread exits void ExitThread(Core::System& system) { + LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC()); + auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GlobalSchedulerContext().RemoveThread(current_thread); current_thread->Exit(); diff --git a/src/core/hle/kernel/svc_generator.py b/src/core/hle/kernel/svc_generator.py index 39640f0fe..7fcbb1ba1 100755 --- a/src/core/hle/kernel/svc_generator.py +++ b/src/core/hle/kernel/svc_generator.py @@ -551,19 +551,19 @@ PROLOGUE_CPP = """ namespace Kernel::Svc { static uint32_t GetReg32(Core::System& system, int n) { - return static_cast(system.GetCurrentArmInterface().GetReg(n)); + return static_cast(system.CurrentArmInterface().GetReg(n)); } static void SetReg32(Core::System& system, int n, uint32_t result) { - system.GetCurrentArmInterface().SetReg(n, static_cast(result)); + system.CurrentArmInterface().SetReg(n, static_cast(result)); } static uint64_t GetReg64(Core::System& system, int n) { - return system.GetCurrentArmInterface().GetReg(n); + return system.CurrentArmInterface().GetReg(n); } static void SetReg64(Core::System& system, int n, uint64_t result) { - system.GetCurrentArmInterface().SetReg(n, result); + system.CurrentArmInterface().SetReg(n, result); } // Like bit_cast, but handles the case when the source and dest diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index b19e12bc8..da077975f 100755 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1317,6 +1317,50 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) { rb.PushIpcInterface(system, std::move(memory)); } +ILibraryAppletSelfAccessor::ILibraryAppletSelfAccessor(Core::System& system_) + : ServiceFramework{system_, "ILibraryAppletSelfAccessor"} { + static const FunctionInfo functions[] = { + {0, nullptr, "PopInData"}, + {1, nullptr, "PushOutData"}, + {2, nullptr, "PopInteractiveInData"}, + {3, nullptr, "PushInteractiveOutData"}, + {5, nullptr, "GetPopInDataEvent"}, + {6, nullptr, "GetPopInteractiveInDataEvent"}, + {10, nullptr, "ExitProcessAndReturn"}, + {11, nullptr, "GetLibraryAppletInfo"}, + {12, nullptr, "GetMainAppletIdentityInfo"}, + {13, nullptr, "CanUseApplicationCore"}, + {14, nullptr, "GetCallerAppletIdentityInfo"}, + {15, nullptr, "GetMainAppletApplicationControlProperty"}, + {16, nullptr, "GetMainAppletStorageId"}, + {17, nullptr, "GetCallerAppletIdentityInfoStack"}, + {18, nullptr, "GetNextReturnDestinationAppletIdentityInfo"}, + {19, nullptr, "GetDesirableKeyboardLayout"}, + {20, nullptr, "PopExtraStorage"}, + {25, nullptr, "GetPopExtraStorageEvent"}, + {30, nullptr, "UnpopInData"}, + {31, nullptr, "UnpopExtraStorage"}, + {40, nullptr, "GetIndirectLayerProducerHandle"}, + {50, nullptr, "ReportVisibleError"}, + {51, nullptr, "ReportVisibleErrorWithErrorContext"}, + {60, nullptr, "GetMainAppletApplicationDesiredLanguage"}, + {70, nullptr, "GetCurrentApplicationId"}, + {80, nullptr, "RequestExitToSelf"}, + {90, nullptr, "CreateApplicationAndPushAndRequestToLaunch"}, + {100, nullptr, "CreateGameMovieTrimmer"}, + {101, nullptr, "ReserveResourceForMovieOperation"}, + {102, nullptr, "UnreserveResourceForMovieOperation"}, + {110, nullptr, "GetMainAppletAvailableUsers"}, + {120, nullptr, "GetLaunchStorageInfoForDebug"}, + {130, nullptr, "GetGpuErrorDetectedSystemEvent"}, + {140, nullptr, "SetApplicationMemoryReservation"}, + {150, nullptr, "ShouldSetGpuTimeSliceManually"}, + }; + RegisterHandlers(functions); +} + +ILibraryAppletSelfAccessor::~ILibraryAppletSelfAccessor() = default; + IApplicationFunctions::IApplicationFunctions(Core::System& system_) : ServiceFramework{system_, "IApplicationFunctions"}, service_context{system, "IApplicationFunctions"} { diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 790ded76b..bcc823587 100755 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -314,6 +314,12 @@ private: void CreateHandleStorage(HLERequestContext& ctx); }; +class ILibraryAppletSelfAccessor final : public ServiceFramework { +public: + explicit ILibraryAppletSelfAccessor(Core::System& system_); + ~ILibraryAppletSelfAccessor() override; +}; + class IApplicationFunctions final : public ServiceFramework { public: explicit IApplicationFunctions(Core::System& system_); diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp index 13c29a507..97dcee0bf 100755 --- a/src/core/hle/service/am/applet_ae.cpp +++ b/src/core/hle/service/am/applet_ae.cpp @@ -26,8 +26,10 @@ public: {4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"}, {10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"}, {11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"}, - {20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"}, + {20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"}, {21, nullptr, "GetAppletCommonFunctions"}, + {22, nullptr, "GetHomeMenuFunctions"}, + {23, nullptr, "GetGlobalStateController"}, {1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"}, }; // clang-format on @@ -100,12 +102,12 @@ private: rb.PushIpcInterface(system); } - void GetApplicationFunctions(HLERequestContext& ctx) { + void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); IPC::ResponseBuilder rb{ctx, 2, 0, 1}; rb.Push(ResultSuccess); - rb.PushIpcInterface(system); + rb.PushIpcInterface(system); } Nvnflinger::Nvnflinger& nvnflinger; diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 6b58c5ba6..28eb4cd0e 100755 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp @@ -46,8 +46,7 @@ struct Memory::Impl { const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth(); - process.GetArmInterface(core_id)->PageTableChanged(*current_page_table, - address_space_width); + system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); } void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index dc601b1cd..d2e05fa43 100755 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp @@ -111,7 +111,7 @@ json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64 json GetProcessorStateDataAuto(Core::System& system) { const auto* process{system.ApplicationProcess()}; - auto& arm{system.GetCurrentArmInterface()}; + auto& arm{system.CurrentArmInterface()}; Core::ARM_Interface::ThreadContext64 context{}; arm.SaveContext(context); @@ -123,7 +123,7 @@ json GetProcessorStateDataAuto(Core::System& system) { json GetBacktraceData(Core::System& system) { auto out = json::array(); - const auto& backtrace{system.GetCurrentArmInterface().GetBacktrace()}; + const auto& backtrace{system.CurrentArmInterface().GetBacktrace()}; for (const auto& entry : backtrace) { out.push_back({ {"module", entry.module},