early-access version 3786

This commit is contained in:
pineappleEA 2023-08-01 12:33:00 +02:00
parent 04f356bb47
commit 2fafeb5013
25 changed files with 187 additions and 215 deletions

View file

@ -1,7 +1,7 @@
yuzu emulator early access yuzu emulator early access
============= =============
This is the source code for early-access 3785. This is the source code for early-access 3786.
## Legal Notice ## Legal Notice

View file

@ -188,7 +188,7 @@ public:
} }
bool IsInterrupted() { bool IsInterrupted() {
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted();
} }
ARM_Dynarmic_32& parent; ARM_Dynarmic_32& parent;

View file

@ -233,7 +233,7 @@ public:
} }
bool IsInterrupted() { bool IsInterrupted() {
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted(); return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted();
} }
ARM_Dynarmic_64& parent; ARM_Dynarmic_64& parent;

View file

@ -14,7 +14,6 @@
#include "common/settings.h" #include "common/settings.h"
#include "common/settings_enums.h" #include "common/settings_enums.h"
#include "common/string_util.h" #include "common/string_util.h"
#include "core/arm/exclusive_monitor.h"
#include "core/core.h" #include "core/core.h"
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/cpu_manager.h" #include "core/cpu_manager.h"
@ -327,7 +326,6 @@ struct System::Impl {
static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result)); static_cast<u32>(SystemResultStatus::ErrorLoader) + static_cast<u32>(load_result));
} }
AddGlueRegistrationForProcess(*app_loader, *main_process); AddGlueRegistrationForProcess(*app_loader, *main_process);
kernel.InitializeCores();
// Initialize cheat engine // Initialize cheat engine
if (cheat_engine) { if (cheat_engine) {
@ -644,10 +642,6 @@ bool System::IsPoweredOn() const {
return impl->is_powered_on.load(std::memory_order::relaxed); 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() { Core::GPUDirtyMemoryManager& System::CurrentGPUDirtyMemoryManager() {
const std::size_t core = impl->kernel.GetCurrentHostThreadID(); const std::size_t core = impl->kernel.GetCurrentHostThreadID();
return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES return impl->gpu_dirty_memory_write_manager[core < Core::Hardware::NUM_CPU_CORES
@ -685,14 +679,6 @@ const TelemetrySession& System::TelemetrySession() const {
return *impl->telemetry_session; 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() { Kernel::PhysicalCore& System::CurrentPhysicalCore() {
return impl->kernel.CurrentPhysicalCore(); return impl->kernel.CurrentPhysicalCore();
} }
@ -701,6 +687,14 @@ const Kernel::PhysicalCore& System::CurrentPhysicalCore() const {
return impl->kernel.CurrentPhysicalCore(); 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 /// Gets the global scheduler
Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() { Kernel::GlobalSchedulerContext& System::GlobalSchedulerContext() {
return impl->kernel.GlobalSchedulerContext(); return impl->kernel.GlobalSchedulerContext();
@ -727,22 +721,6 @@ const Kernel::KProcess* System::ApplicationProcess() const {
return impl->kernel.ApplicationProcess(); 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() { Memory::Memory& System::ApplicationMemory() {
return impl->memory; return impl->memory;
} }

View file

@ -223,9 +223,6 @@ public:
/// Gets a reference to the telemetry session for this emulation session. /// Gets a reference to the telemetry session for this emulation session.
[[nodiscard]] const Core::TelemetrySession& TelemetrySession() const; [[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. /// Provides a reference to the gou dirty memory manager.
[[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager(); [[nodiscard]] Core::GPUDirtyMemoryManager& CurrentGPUDirtyMemoryManager();
@ -239,23 +236,17 @@ public:
/// Gets and resets core performance statistics /// Gets and resets core performance statistics
[[nodiscard]] PerfStatsResults GetAndResetPerfStats(); [[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 /// Gets the physical core for the CPU core that is currently running
[[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore(); [[nodiscard]] Kernel::PhysicalCore& CurrentPhysicalCore();
/// Gets the physical core for the CPU core that is currently running /// Gets the physical core for the CPU core that is currently running
[[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const; [[nodiscard]] const Kernel::PhysicalCore& CurrentPhysicalCore() const;
/// Gets a reference to an ARM interface for the CPU core with the specified index /// Gets the exclusive monitor for the process on the current core
[[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index); Core::ExclusiveMonitor& GetCurrentExclusiveMonitor();
/// Gets a const reference to an ARM interface from the CPU core with the specified index /// Gets the JIT instance for the process on the current core
[[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const; Core::ARM_Interface& GetCurrentArmInterface();
/// Gets a reference to the underlying CPU manager. /// Gets a reference to the underlying CPU manager.
[[nodiscard]] CpuManager& GetCpuManager(); [[nodiscard]] CpuManager& GetCpuManager();
@ -263,12 +254,6 @@ public:
/// Gets a const reference to the underlying CPU manager /// Gets a const reference to the underlying CPU manager
[[nodiscard]] const CpuManager& GetCpuManager() const; [[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. /// Gets a mutable reference to the system memory instance.
[[nodiscard]] Core::Memory::Memory& ApplicationMemory(); [[nodiscard]] Core::Memory::Memory& ApplicationMemory();

View file

@ -9,6 +9,7 @@
#include "core/core_timing.h" #include "core/core_timing.h"
#include "core/cpu_manager.h" #include "core/cpu_manager.h"
#include "core/hle/kernel/k_interrupt_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_scheduler.h"
#include "core/hle/kernel/k_thread.h" #include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
@ -73,13 +74,15 @@ void CpuManager::HandleInterrupt() {
void CpuManager::MultiCoreRunGuestThread() { void CpuManager::MultiCoreRunGuestThread() {
// Similar to UserModeThreadStarter in HOS // Similar to UserModeThreadStarter in HOS
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
auto& process = Kernel::GetCurrentProcess(kernel);
kernel.CurrentScheduler()->OnThreadStart(); kernel.CurrentScheduler()->OnThreadStart();
while (true) { while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore(); auto* physical_core = &kernel.CurrentPhysicalCore();
while (!physical_core->IsInterrupted()) { auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex());
physical_core->Run();
physical_core = &kernel.CurrentPhysicalCore(); if (physical_core->Run(*arm_interface)) {
continue;
} }
HandleInterrupt(); HandleInterrupt();
@ -95,11 +98,7 @@ void CpuManager::MultiCoreRunIdleThread() {
kernel.CurrentScheduler()->OnThreadStart(); kernel.CurrentScheduler()->OnThreadStart();
while (true) { while (true) {
auto& physical_core = kernel.CurrentPhysicalCore(); kernel.CurrentPhysicalCore().WaitForInterrupt();
if (!physical_core.IsInterrupted()) {
physical_core.Idle();
}
HandleInterrupt(); HandleInterrupt();
} }
} }
@ -110,14 +109,13 @@ void CpuManager::MultiCoreRunIdleThread() {
void CpuManager::SingleCoreRunGuestThread() { void CpuManager::SingleCoreRunGuestThread() {
auto& kernel = system.Kernel(); auto& kernel = system.Kernel();
auto& process = Kernel::GetCurrentProcess(kernel);
kernel.CurrentScheduler()->OnThreadStart(); kernel.CurrentScheduler()->OnThreadStart();
while (true) { while (true) {
auto* physical_core = &kernel.CurrentPhysicalCore(); auto* physical_core = &kernel.CurrentPhysicalCore();
if (!physical_core->IsInterrupted()) { auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex());
physical_core->Run(); physical_core->Run(*arm_interface);
physical_core = &kernel.CurrentPhysicalCore();
}
kernel.SetIsPhantomModeForSingleCore(true); kernel.SetIsPhantomModeForSingleCore(true);
system.CoreTiming().Advance(); system.CoreTiming().Advance();

View file

@ -27,7 +27,7 @@ bool ReadFromUser(KernelCore& kernel, s32* out, KProcessAddress address) {
} }
bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) { bool DecrementIfLessThan(Core::System& system, s32* out, KProcessAddress address, s32 value) {
auto& monitor = system.Monitor(); auto& monitor = system.GetCurrentExclusiveMonitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
// NOTE: If scheduler lock is not held here, interrupt disable is required. // 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, bool UpdateIfEqual(Core::System& system, s32* out, KProcessAddress address, s32 value,
s32 new_value) { s32 new_value) {
auto& monitor = system.Monitor(); auto& monitor = system.GetCurrentExclusiveMonitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
// NOTE: If scheduler lock is not held here, interrupt disable is required. // NOTE: If scheduler lock is not held here, interrupt disable is required.

View file

@ -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, bool UpdateLockAtomic(Core::System& system, u32* out, KProcessAddress address, u32 if_zero,
u32 new_orr_mask) { u32 new_orr_mask) {
auto& monitor = system.Monitor(); auto& monitor = system.GetCurrentExclusiveMonitor();
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex(); const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
u32 expected{}; u32 expected{};

View file

@ -11,6 +11,9 @@
#include "common/logging/log.h" #include "common/logging/log.h"
#include "common/scope_exit.h" #include "common/scope_exit.h"
#include "common/settings.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/core.h"
#include "core/file_sys/program_metadata.h" #include "core/file_sys/program_metadata.h"
#include "core/hle/kernel/code_set.h" #include "core/hle/kernel/code_set.h"
@ -427,6 +430,22 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
this->ChangeState(State::Running); this->ChangeState(State::Running);
auto exclusive_monitor = std::make_unique<Core::DynarmicExclusiveMonitor>(
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<Core::ARM_Dynarmic_64>(
m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i);
} else {
m_arm_interfaces[i] = std::make_unique<Core::ARM_Dynarmic_32>(
m_kernel.System(), m_kernel.IsMulticore(), *exclusive_monitor, i);
}
this->GetMemory().SetCurrentPageTable(*this, static_cast<u32>(i));
}
m_exclusive_monitor = std::move(exclusive_monitor);
SetupMainThread(m_kernel.System(), *this, main_thread_priority, m_main_thread_stack_top); SetupMainThread(m_kernel.System(), *this, main_thread_priority, m_main_thread_stack_top);
} }

View file

@ -407,6 +407,14 @@ public:
return name; return name;
} }
Core::ExclusiveMonitor* GetExclusiveMonitor() {
return m_exclusive_monitor.get();
}
Core::ARM_Interface* GetArmInterface(size_t i) {
return m_arm_interfaces[i].get();
}
private: private:
void PinThread(s32 core_id, KThread* thread) { void PinThread(s32 core_id, KThread* thread) {
ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES)); ASSERT(0 <= core_id && core_id < static_cast<s32>(Core::Hardware::NUM_CPU_CORES));
@ -537,6 +545,11 @@ private:
using TLPIterator = TLPTree::iterator; using TLPIterator = TLPTree::iterator;
TLPTree m_fully_used_tlp_tree; TLPTree m_fully_used_tlp_tree;
TLPTree m_partially_used_tlp_tree; TLPTree m_partially_used_tlp_tree;
private:
std::unique_ptr<Core::ExclusiveMonitor> m_exclusive_monitor{};
std::array<std::unique_ptr<Core::ARM_Interface>, Core::Hardware::NUM_CPU_CORES>
m_arm_interfaces{};
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -494,12 +494,15 @@ void KScheduler::ScheduleImplFiber() {
} }
void KScheduler::Unload(KThread* thread) { void KScheduler::Unload(KThread* thread) {
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); 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->GetContext32());
cpu_core.SaveContext(thread->GetContext64()); cpu_core.SaveContext(thread->GetContext64());
// Save the TPIDR_EL0 system register in case it was modified. // Save the TPIDR_EL0 system register in case it was modified.
thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0()); thread->SetTpidrEl0(cpu_core.GetTPIDR_EL0());
cpu_core.ClearExclusiveState(); cpu_core.ClearExclusiveState();
}
// Check if the thread is terminated by checking the DPC flags. // Check if the thread is terminated by checking the DPC flags.
if ((thread->GetStackParameters().dpc_flags & static_cast<u32>(DpcFlag::Terminated)) == 0) { if ((thread->GetStackParameters().dpc_flags & static_cast<u32>(DpcFlag::Terminated)) == 0) {
@ -509,14 +512,16 @@ void KScheduler::Unload(KThread* thread) {
} }
void KScheduler::Reload(KThread* thread) { void KScheduler::Reload(KThread* thread) {
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id); if (thread->GetThreadType() == ThreadType::User) {
auto* process = thread->GetOwnerProcess(); auto* process = thread->GetOwnerProcess();
auto& cpu_core = *process->GetArmInterface(m_core_id);
cpu_core.LoadContext(thread->GetContext32()); cpu_core.LoadContext(thread->GetContext32());
cpu_core.LoadContext(thread->GetContext64()); cpu_core.LoadContext(thread->GetContext64());
cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress())); cpu_core.SetTlsAddress(GetInteger(thread->GetTlsAddress()));
cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0()); cpu_core.SetTPIDR_EL0(thread->GetTpidrEl0());
cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr); cpu_core.LoadWatchpointArray(&process->GetWatchpoints());
cpu_core.ClearExclusiveState(); cpu_core.ClearExclusiveState();
}
} }
void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) { void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) {

View file

@ -823,14 +823,14 @@ void KThread::CloneFpuStatus() {
if (this->GetOwnerProcess()->Is64BitProcess()) { if (this->GetOwnerProcess()->Is64BitProcess()) {
// Clone FPSR and FPCR. // Clone FPSR and FPCR.
ThreadContext64 cur_ctx{}; ThreadContext64 cur_ctx{};
m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx);
this->GetContext64().fpcr = cur_ctx.fpcr; this->GetContext64().fpcr = cur_ctx.fpcr;
this->GetContext64().fpsr = cur_ctx.fpsr; this->GetContext64().fpsr = cur_ctx.fpsr;
} else { } else {
// Clone FPSCR. // Clone FPSCR.
ThreadContext32 cur_ctx{}; ThreadContext32 cur_ctx{};
m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx); m_kernel.GetCurrentArmInterface().SaveContext(cur_ctx);
this->GetContext32().fpscr = cur_ctx.fpscr; this->GetContext32().fpscr = cur_ctx.fpscr;
} }

View file

@ -99,13 +99,6 @@ struct KernelCore::Impl {
RegisterHostThread(nullptr); 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() { void CloseApplicationProcess() {
KProcess* old_process = application_process.exchange(nullptr); KProcess* old_process = application_process.exchange(nullptr);
if (old_process == nullptr) { if (old_process == nullptr) {
@ -137,8 +130,6 @@ struct KernelCore::Impl {
preemption_event = nullptr; preemption_event = nullptr;
exclusive_monitor.reset();
// Cleanup persistent kernel objects // Cleanup persistent kernel objects
auto CleanupObject = [](KAutoObject* obj) { auto CleanupObject = [](KAutoObject* obj) {
if (obj) { if (obj) {
@ -205,13 +196,11 @@ struct KernelCore::Impl {
} }
void InitializePhysicalCores() { void InitializePhysicalCores() {
exclusive_monitor =
Core::MakeExclusiveMonitor(system.ApplicationMemory(), Core::Hardware::NUM_CPU_CORES);
for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { for (u32 i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
const s32 core{static_cast<s32>(i)}; const s32 core{static_cast<s32>(i)};
schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel()); schedulers[i] = std::make_unique<Kernel::KScheduler>(system.Kernel());
cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]); cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system);
auto* main_thread{Kernel::KThread::Create(system.Kernel())}; auto* main_thread{Kernel::KThread::Create(system.Kernel())};
main_thread->SetCurrentCore(core); main_thread->SetCurrentCore(core);
@ -804,7 +793,6 @@ struct KernelCore::Impl {
std::mutex server_lock; std::mutex server_lock;
std::vector<std::unique_ptr<Service::ServerManager>> server_managers; std::vector<std::unique_ptr<Service::ServerManager>> server_managers;
std::unique_ptr<Core::ExclusiveMonitor> exclusive_monitor;
std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores; std::array<std::unique_ptr<Kernel::PhysicalCore>, Core::Hardware::NUM_CPU_CORES> cores;
// Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others // Next host thead ID to use, 0-3 IDs represent core threads, >3 represent others
@ -865,10 +853,6 @@ void KernelCore::Initialize() {
impl->Initialize(*this); impl->Initialize(*this);
} }
void KernelCore::InitializeCores() {
impl->InitializeCores();
}
void KernelCore::Shutdown() { void KernelCore::Shutdown() {
impl->Shutdown(); impl->Shutdown();
} }
@ -966,12 +950,12 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
return *impl->hardware_timer; return *impl->hardware_timer;
} }
Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() { Core::ExclusiveMonitor& KernelCore::GetCurrentExclusiveMonitor() {
return *impl->exclusive_monitor; return *GetCurrentProcess(*this).GetExclusiveMonitor();
} }
const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const { Core::ARM_Interface& KernelCore::GetCurrentArmInterface() {
return *impl->exclusive_monitor; return *GetCurrentProcess(*this).GetArmInterface(this->CurrentPhysicalCoreIndex());
} }
KAutoObjectWithListContainer& KernelCore::ObjectListContainer() { KAutoObjectWithListContainer& KernelCore::ObjectListContainer() {
@ -983,22 +967,33 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
} }
void KernelCore::InvalidateAllInstructionCaches() { void KernelCore::InvalidateAllInstructionCaches() {
for (auto& physical_core : impl->cores) { // TODO: we need to make sure the JIT is not running during this
physical_core->ArmInterface().ClearInstructionCache(); 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();
}
} }
} }
void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) { void KernelCore::InvalidateCpuInstructionCacheRange(KProcessAddress addr, std::size_t size) {
for (auto& physical_core : impl->cores) { // TODO: we need to make sure the JIT is not running during this
if (!physical_core->IsInitialized()) { auto process = this->ApplicationProcess();
continue; if (process == nullptr) {
return;
} }
physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size);
}
}
void KernelCore::PrepareReschedule(std::size_t id) { for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
// TODO: Reimplement, this auto* arm_interface = process->GetArmInterface(i);
if (arm_interface) {
arm_interface->InvalidateCacheRange(GetInteger(addr), size);
}
}
} }
void KernelCore::RegisterKernelObject(KAutoObject* object) { void KernelCore::RegisterKernelObject(KAutoObject* object) {

View file

@ -18,6 +18,7 @@
#include "core/hle/kernel/svc_common.h" #include "core/hle/kernel/svc_common.h"
namespace Core { namespace Core {
class ARM_Interface;
class ExclusiveMonitor; class ExclusiveMonitor;
class System; class System;
} // namespace Core } // namespace Core
@ -104,9 +105,6 @@ public:
/// Resets the kernel to a clean slate for use. /// Resets the kernel to a clean slate for use.
void Initialize(); void Initialize();
/// Initializes the CPU cores.
void InitializeCores();
/// Clears all resources in use by the kernel instance. /// Clears all resources in use by the kernel instance.
void Shutdown(); void Shutdown();
@ -173,12 +171,11 @@ public:
/// Gets the an instance of the hardware timer. /// Gets the an instance of the hardware timer.
Kernel::KHardwareTimer& HardwareTimer(); Kernel::KHardwareTimer& HardwareTimer();
/// Stops execution of 'id' core, in order to reschedule a new thread. /// Gets the exclusive monitor for the process on the current core
void PrepareReschedule(std::size_t id); Core::ExclusiveMonitor& GetCurrentExclusiveMonitor();
Core::ExclusiveMonitor& GetExclusiveMonitor(); /// Gets the JIT instance for the process on the current core
Core::ARM_Interface& GetCurrentArmInterface();
const Core::ExclusiveMonitor& GetExclusiveMonitor() const;
KAutoObjectWithListContainer& ObjectListContainer(); KAutoObjectWithListContainer& ObjectListContainer();

View file

@ -4,69 +4,77 @@
#include "core/arm/dynarmic/arm_dynarmic_32.h" #include "core/arm/dynarmic/arm_dynarmic_32.h"
#include "core/arm/dynarmic/arm_dynarmic_64.h" #include "core/arm/dynarmic/arm_dynarmic_64.h"
#include "core/core.h" #include "core/core.h"
#include "core/hle/kernel/k_scheduler.h" #include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/kernel.h" #include "core/hle/kernel/kernel.h"
#include "core/hle/kernel/physical_core.h" #include "core/hle/kernel/physical_core.h"
namespace Kernel { namespace Kernel {
PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KScheduler& scheduler) PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system)
: m_core_index{core_index}, m_system{system}, m_scheduler{scheduler} { : m_core_index{core_index}, m_system{system} {}
#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<Core::ARM_Dynarmic_64>(
system, kernel.IsMulticore(),
reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
m_core_index);
#else
#error Platform not supported yet.
#endif
}
PhysicalCore::~PhysicalCore() = default; PhysicalCore::~PhysicalCore() = default;
void PhysicalCore::Initialize(bool is_64_bit) { bool PhysicalCore::Run(Core::ARM_Interface& current_arm_interface) {
#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64) // SAFETY: we need to lock around storing the JIT instance member to serialize
auto& kernel = m_system.Kernel(); // access with another thread that wants to send us an interrupt. Otherwise we
if (!is_64_bit) { // may end up sending an interrupt to an instance that is not current.
// We already initialized a 64-bit core, replace with a 32-bit one.
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>( // Mark the instance as current.
m_system, kernel.IsMulticore(), {
reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()), std::scoped_lock lk{m_guard};
m_core_index);
// 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;
} }
#else
#error Platform not supported yet.
#endif
} }
void PhysicalCore::Run() { void PhysicalCore::WaitForInterrupt() {
m_arm_interface->Run(); // Wait for a signal.
m_arm_interface->ClearExclusiveState();
}
void PhysicalCore::Idle() {
std::unique_lock lk{m_guard}; std::unique_lock lk{m_guard};
m_on_interrupt.wait(lk, [this] { return m_is_interrupted; }); m_on_interrupt.wait(lk, [this] { return m_is_interrupted; });
} }
bool PhysicalCore::IsInterrupted() const {
return m_is_interrupted;
}
void PhysicalCore::Interrupt() { void PhysicalCore::Interrupt() {
std::unique_lock lk{m_guard}; {
std::scoped_lock lk{m_guard};
// Mark as interrupted.
m_is_interrupted = true; m_is_interrupted = true;
m_arm_interface->SignalInterrupt();
// If we are currently executing code, interrupt the JIT.
if (m_current_arm_interface) {
m_current_arm_interface->SignalInterrupt();
}
}
// Signal.
m_on_interrupt.notify_all(); m_on_interrupt.notify_all();
} }
void PhysicalCore::ClearInterrupt() { void PhysicalCore::ClearInterrupt() {
std::unique_lock lk{m_guard}; std::scoped_lock lk{m_guard};
// Remove interrupt flag.
m_is_interrupted = false; m_is_interrupted = false;
m_arm_interface->ClearInterrupt();
} }
} // namespace Kernel } // namespace Kernel

View file

@ -23,19 +23,16 @@ namespace Kernel {
class PhysicalCore { class PhysicalCore {
public: public:
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_); PhysicalCore(std::size_t core_index_, Core::System& system_);
~PhysicalCore(); ~PhysicalCore();
YUZU_NON_COPYABLE(PhysicalCore); YUZU_NON_COPYABLE(PhysicalCore);
YUZU_NON_MOVEABLE(PhysicalCore); YUZU_NON_MOVEABLE(PhysicalCore);
/// Initialize the core for the specified parameters. /// Execute JIT and return whether we ran to completion
void Initialize(bool is_64_bit); bool Run(Core::ARM_Interface& current_arm_interface);
/// Execute current jit state void WaitForInterrupt();
void Run();
void Idle();
/// Interrupt this physical core. /// Interrupt this physical core.
void Interrupt(); void Interrupt();
@ -43,42 +40,22 @@ public:
/// Clear this core's interrupt /// Clear this core's interrupt
void ClearInterrupt(); void ClearInterrupt();
/// Check if this core is interrupted bool GetIsInterrupted() const {
bool IsInterrupted() const; return m_is_interrupted;
bool IsInitialized() const {
return m_arm_interface != nullptr;
} }
Core::ARM_Interface& ArmInterface() { std::size_t GetCoreIndex() const {
return *m_arm_interface;
}
const Core::ARM_Interface& ArmInterface() const {
return *m_arm_interface;
}
std::size_t CoreIndex() const {
return m_core_index; return m_core_index;
} }
Kernel::KScheduler& Scheduler() {
return m_scheduler;
}
const Kernel::KScheduler& Scheduler() const {
return m_scheduler;
}
private: private:
const std::size_t m_core_index; const std::size_t m_core_index;
Core::System& m_system; Core::System& m_system;
Kernel::KScheduler& m_scheduler;
std::mutex m_guard; std::mutex m_guard;
std::condition_variable m_on_interrupt; std::condition_variable m_on_interrupt;
std::unique_ptr<Core::ARM_Interface> m_arm_interface;
bool m_is_interrupted{}; bool m_is_interrupted{};
Core::ARM_Interface* m_current_arm_interface{};
}; };
} // namespace Kernel } // namespace Kernel

View file

@ -13,19 +13,19 @@
namespace Kernel::Svc { namespace Kernel::Svc {
static uint32_t GetReg32(Core::System& system, int n) { static uint32_t GetReg32(Core::System& system, int n) {
return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n)); return static_cast<uint32_t>(system.GetCurrentArmInterface().GetReg(n));
} }
static void SetReg32(Core::System& system, int n, uint32_t result) { static void SetReg32(Core::System& system, int n, uint32_t result) {
system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result)); system.GetCurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
} }
static uint64_t GetReg64(Core::System& system, int n) { static uint64_t GetReg64(Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n); return system.GetCurrentArmInterface().GetReg(n);
} }
static void SetReg64(Core::System& system, int n, uint64_t result) { static void SetReg64(Core::System& system, int n, uint64_t result) {
system.CurrentArmInterface().SetReg(n, result); system.GetCurrentArmInterface().SetReg(n, result);
} }
// Like bit_cast, but handles the case when the source and dest // Like bit_cast, but handles the case when the source and dest

View file

@ -102,9 +102,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
handle_debug_buffer(info1, info2); handle_debug_buffer(info1, info2);
auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); system.GetCurrentArmInterface().LogBacktrace();
const auto thread_processor_id = current_thread->GetActiveCore();
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
} }
if (system.DebuggerEnabled()) { if (system.DebuggerEnabled()) {

View file

@ -38,7 +38,7 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle,
template <typename F> template <typename F>
static void SvcWrap_LightIpc(Core::System& system, F&& cb) { static void SvcWrap_LightIpc(Core::System& system, F&& cb) {
auto& core = system.CurrentArmInterface(); auto& core = system.GetCurrentArmInterface();
std::array<u32, 7> arguments{}; std::array<u32, 7> arguments{};
Handle session_handle = static_cast<Handle>(core.GetReg(0)); Handle session_handle = static_cast<Handle>(core.GetReg(0));

View file

@ -11,7 +11,7 @@ namespace Kernel::Svc {
/// Get which CPU core is executing the current thread /// Get which CPU core is executing the current thread
int32_t GetCurrentProcessorNumber(Core::System& system) { int32_t GetCurrentProcessorNumber(Core::System& system) {
LOG_TRACE(Kernel_SVC, "called"); LOG_TRACE(Kernel_SVC, "called");
return static_cast<int32_t>(system.CurrentPhysicalCore().CoreIndex()); return static_cast<int32_t>(system.CurrentPhysicalCore().GetCoreIndex());
} }
int32_t GetCurrentProcessorNumber64(Core::System& system) { int32_t GetCurrentProcessorNumber64(Core::System& system) {

View file

@ -23,7 +23,7 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
// Custom ABI for CallSecureMonitor. // Custom ABI for CallSecureMonitor.
void SvcWrap_CallSecureMonitor64(Core::System& system) { void SvcWrap_CallSecureMonitor64(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface(); auto& core = system.GetCurrentArmInterface();
lp64::SecureMonitorArguments args{}; lp64::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
args.r[i] = core.GetReg(i); args.r[i] = core.GetReg(i);
@ -37,7 +37,7 @@ void SvcWrap_CallSecureMonitor64(Core::System& system) {
} }
void SvcWrap_CallSecureMonitor64From32(Core::System& system) { void SvcWrap_CallSecureMonitor64From32(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface(); auto& core = system.GetCurrentArmInterface();
ilp32::SecureMonitorArguments args{}; ilp32::SecureMonitorArguments args{};
for (int i = 0; i < 8; i++) { for (int i = 0; i < 8; i++) {
args.r[i] = static_cast<u32>(core.GetReg(i)); args.r[i] = static_cast<u32>(core.GetReg(i));

View file

@ -93,8 +93,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
/// Called when a thread exits /// Called when a thread exits
void ExitThread(Core::System& system) { void ExitThread(Core::System& system) {
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
auto* const current_thread = GetCurrentThreadPointer(system.Kernel()); auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
system.GlobalSchedulerContext().RemoveThread(current_thread); system.GlobalSchedulerContext().RemoveThread(current_thread);
current_thread->Exit(); current_thread->Exit();

View file

@ -551,19 +551,19 @@ PROLOGUE_CPP = """
namespace Kernel::Svc { namespace Kernel::Svc {
static uint32_t GetReg32(Core::System& system, int n) { static uint32_t GetReg32(Core::System& system, int n) {
return static_cast<uint32_t>(system.CurrentArmInterface().GetReg(n)); return static_cast<uint32_t>(system.GetCurrentArmInterface().GetReg(n));
} }
static void SetReg32(Core::System& system, int n, uint32_t result) { static void SetReg32(Core::System& system, int n, uint32_t result) {
system.CurrentArmInterface().SetReg(n, static_cast<uint64_t>(result)); system.GetCurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
} }
static uint64_t GetReg64(Core::System& system, int n) { static uint64_t GetReg64(Core::System& system, int n) {
return system.CurrentArmInterface().GetReg(n); return system.GetCurrentArmInterface().GetReg(n);
} }
static void SetReg64(Core::System& system, int n, uint64_t result) { static void SetReg64(Core::System& system, int n, uint64_t result) {
system.CurrentArmInterface().SetReg(n, result); system.GetCurrentArmInterface().SetReg(n, result);
} }
// Like bit_cast, but handles the case when the source and dest // Like bit_cast, but handles the case when the source and dest

View file

@ -46,7 +46,8 @@ struct Memory::Impl {
const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth(); const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width); process.GetArmInterface(core_id)->PageTableChanged(*current_page_table,
address_space_width);
} }
void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size, void MapMemoryRegion(Common::PageTable& page_table, Common::ProcessAddress base, u64 size,

View file

@ -111,7 +111,7 @@ json GetProcessorStateData(const std::string& architecture, u64 entry_point, u64
json GetProcessorStateDataAuto(Core::System& system) { json GetProcessorStateDataAuto(Core::System& system) {
const auto* process{system.ApplicationProcess()}; const auto* process{system.ApplicationProcess()};
auto& arm{system.CurrentArmInterface()}; auto& arm{system.GetCurrentArmInterface()};
Core::ARM_Interface::ThreadContext64 context{}; Core::ARM_Interface::ThreadContext64 context{};
arm.SaveContext(context); arm.SaveContext(context);
@ -123,7 +123,7 @@ json GetProcessorStateDataAuto(Core::System& system) {
json GetBacktraceData(Core::System& system) { json GetBacktraceData(Core::System& system) {
auto out = json::array(); auto out = json::array();
const auto& backtrace{system.CurrentArmInterface().GetBacktrace()}; const auto& backtrace{system.GetCurrentArmInterface().GetBacktrace()};
for (const auto& entry : backtrace) { for (const auto& entry : backtrace) {
out.push_back({ out.push_back({
{"module", entry.module}, {"module", entry.module},