early-access version 3790
This commit is contained in:
parent
b8064464d8
commit
a61e0cf970
28 changed files with 270 additions and 190 deletions
|
@ -1,7 +1,7 @@
|
||||||
yuzu emulator early access
|
yuzu emulator early access
|
||||||
=============
|
=============
|
||||||
|
|
||||||
This is the source code for early-access 3789.
|
This is the source code for early-access 3790.
|
||||||
|
|
||||||
## Legal Notice
|
## Legal Notice
|
||||||
|
|
||||||
|
|
|
@ -188,7 +188,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInterrupted() {
|
bool IsInterrupted() {
|
||||||
return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted();
|
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM_Dynarmic_32& parent;
|
ARM_Dynarmic_32& parent;
|
||||||
|
|
|
@ -233,7 +233,7 @@ public:
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsInterrupted() {
|
bool IsInterrupted() {
|
||||||
return parent.system.Kernel().PhysicalCore(parent.core_index).GetIsInterrupted();
|
return parent.system.Kernel().PhysicalCore(parent.core_index).IsInterrupted();
|
||||||
}
|
}
|
||||||
|
|
||||||
ARM_Dynarmic_64& parent;
|
ARM_Dynarmic_64& parent;
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#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"
|
||||||
|
@ -326,6 +327,7 @@ 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) {
|
||||||
|
@ -642,6 +644,10 @@ 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
|
||||||
|
@ -679,6 +685,14 @@ 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();
|
||||||
}
|
}
|
||||||
|
@ -687,14 +701,6 @@ 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();
|
||||||
|
@ -721,6 +727,22 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,6 +223,9 @@ 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();
|
||||||
|
|
||||||
|
@ -236,17 +239,23 @@ 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 the exclusive monitor for the process on the current core
|
/// Gets a reference to an ARM interface for the CPU core with the specified index
|
||||||
Core::ExclusiveMonitor& GetCurrentExclusiveMonitor();
|
[[nodiscard]] ARM_Interface& ArmInterface(std::size_t core_index);
|
||||||
|
|
||||||
/// Gets the JIT instance for the process on the current core
|
/// Gets a const reference to an ARM interface from the CPU core with the specified index
|
||||||
Core::ARM_Interface& GetCurrentArmInterface();
|
[[nodiscard]] const ARM_Interface& ArmInterface(std::size_t core_index) const;
|
||||||
|
|
||||||
/// Gets a reference to the underlying CPU manager.
|
/// Gets a reference to the underlying CPU manager.
|
||||||
[[nodiscard]] CpuManager& GetCpuManager();
|
[[nodiscard]] CpuManager& GetCpuManager();
|
||||||
|
@ -254,6 +263,12 @@ 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();
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@
|
||||||
#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"
|
||||||
|
@ -74,15 +73,13 @@ 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();
|
||||||
auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex());
|
while (!physical_core->IsInterrupted()) {
|
||||||
|
physical_core->Run();
|
||||||
if (physical_core->Run(*arm_interface)) {
|
physical_core = &kernel.CurrentPhysicalCore();
|
||||||
continue;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HandleInterrupt();
|
HandleInterrupt();
|
||||||
|
@ -98,7 +95,11 @@ void CpuManager::MultiCoreRunIdleThread() {
|
||||||
kernel.CurrentScheduler()->OnThreadStart();
|
kernel.CurrentScheduler()->OnThreadStart();
|
||||||
|
|
||||||
while (true) {
|
while (true) {
|
||||||
kernel.CurrentPhysicalCore().WaitForInterrupt();
|
auto& physical_core = kernel.CurrentPhysicalCore();
|
||||||
|
if (!physical_core.IsInterrupted()) {
|
||||||
|
physical_core.Idle();
|
||||||
|
}
|
||||||
|
|
||||||
HandleInterrupt();
|
HandleInterrupt();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -109,13 +110,14 @@ 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();
|
||||||
auto* arm_interface = process.GetArmInterface(physical_core->GetCoreIndex());
|
if (!physical_core->IsInterrupted()) {
|
||||||
physical_core->Run(*arm_interface);
|
physical_core->Run();
|
||||||
|
physical_core = &kernel.CurrentPhysicalCore();
|
||||||
|
}
|
||||||
|
|
||||||
kernel.SetIsPhantomModeForSingleCore(true);
|
kernel.SetIsPhantomModeForSingleCore(true);
|
||||||
system.CoreTiming().Advance();
|
system.CoreTiming().Advance();
|
||||||
|
|
|
@ -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.GetCurrentExclusiveMonitor();
|
auto& monitor = system.Monitor();
|
||||||
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.GetCurrentExclusiveMonitor();
|
auto& monitor = system.Monitor();
|
||||||
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.
|
||||||
|
|
|
@ -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.GetCurrentExclusiveMonitor();
|
auto& monitor = system.Monitor();
|
||||||
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
|
const auto current_core = system.Kernel().CurrentPhysicalCoreIndex();
|
||||||
|
|
||||||
u32 expected{};
|
u32 expected{};
|
||||||
|
|
|
@ -11,9 +11,6 @@
|
||||||
#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"
|
||||||
|
@ -430,22 +427,6 @@ 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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -407,14 +407,6 @@ 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));
|
||||||
|
@ -545,11 +537,6 @@ 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
|
||||||
|
|
|
@ -494,15 +494,12 @@ void KScheduler::ScheduleImplFiber() {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KScheduler::Unload(KThread* thread) {
|
void KScheduler::Unload(KThread* thread) {
|
||||||
if (thread->GetThreadType() == ThreadType::User) {
|
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
|
||||||
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) {
|
||||||
|
@ -512,17 +509,15 @@ void KScheduler::Unload(KThread* thread) {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KScheduler::Reload(KThread* thread) {
|
void KScheduler::Reload(KThread* thread) {
|
||||||
if (thread->GetThreadType() == ThreadType::User) {
|
auto& cpu_core = m_kernel.System().ArmInterface(m_core_id);
|
||||||
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->GetWatchpoints());
|
cpu_core.LoadWatchpointArray(process ? &process->GetWatchpoints() : nullptr);
|
||||||
cpu_core.ClearExclusiveState();
|
cpu_core.ClearExclusiveState();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) {
|
void KScheduler::ClearPreviousThread(KernelCore& kernel, KThread* thread) {
|
||||||
ASSERT(IsSchedulerLockedByCurrentThread(kernel));
|
ASSERT(IsSchedulerLockedByCurrentThread(kernel));
|
||||||
|
|
|
@ -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.GetCurrentArmInterface().SaveContext(cur_ctx);
|
m_kernel.System().CurrentArmInterface().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.GetCurrentArmInterface().SaveContext(cur_ctx);
|
m_kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
|
||||||
|
|
||||||
this->GetContext32().fpscr = cur_ctx.fpscr;
|
this->GetContext32().fpscr = cur_ctx.fpscr;
|
||||||
}
|
}
|
||||||
|
|
|
@ -99,6 +99,13 @@ 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) {
|
||||||
|
@ -130,6 +137,8 @@ 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) {
|
||||||
|
@ -196,11 +205,13 @@ 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);
|
cores[i] = std::make_unique<Kernel::PhysicalCore>(i, system, *schedulers[i]);
|
||||||
|
|
||||||
auto* main_thread{Kernel::KThread::Create(system.Kernel())};
|
auto* main_thread{Kernel::KThread::Create(system.Kernel())};
|
||||||
main_thread->SetCurrentCore(core);
|
main_thread->SetCurrentCore(core);
|
||||||
|
@ -793,6 +804,7 @@ 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
|
||||||
|
@ -853,6 +865,10 @@ void KernelCore::Initialize() {
|
||||||
impl->Initialize(*this);
|
impl->Initialize(*this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void KernelCore::InitializeCores() {
|
||||||
|
impl->InitializeCores();
|
||||||
|
}
|
||||||
|
|
||||||
void KernelCore::Shutdown() {
|
void KernelCore::Shutdown() {
|
||||||
impl->Shutdown();
|
impl->Shutdown();
|
||||||
}
|
}
|
||||||
|
@ -950,12 +966,12 @@ Kernel::KHardwareTimer& KernelCore::HardwareTimer() {
|
||||||
return *impl->hardware_timer;
|
return *impl->hardware_timer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::ExclusiveMonitor& KernelCore::GetCurrentExclusiveMonitor() {
|
Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() {
|
||||||
return *GetCurrentProcess(*this).GetExclusiveMonitor();
|
return *impl->exclusive_monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
Core::ARM_Interface& KernelCore::GetCurrentArmInterface() {
|
const Core::ExclusiveMonitor& KernelCore::GetExclusiveMonitor() const {
|
||||||
return *GetCurrentProcess(*this).GetArmInterface(this->CurrentPhysicalCoreIndex());
|
return *impl->exclusive_monitor;
|
||||||
}
|
}
|
||||||
|
|
||||||
KAutoObjectWithListContainer& KernelCore::ObjectListContainer() {
|
KAutoObjectWithListContainer& KernelCore::ObjectListContainer() {
|
||||||
|
@ -967,33 +983,22 @@ const KAutoObjectWithListContainer& KernelCore::ObjectListContainer() const {
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::InvalidateAllInstructionCaches() {
|
void KernelCore::InvalidateAllInstructionCaches() {
|
||||||
// TODO: we need to make sure the JIT is not running during this
|
for (auto& physical_core : impl->cores) {
|
||||||
auto process = this->ApplicationProcess();
|
physical_core->ArmInterface().ClearInstructionCache();
|
||||||
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) {
|
||||||
// TODO: we need to make sure the JIT is not running during this
|
for (auto& physical_core : impl->cores) {
|
||||||
auto process = this->ApplicationProcess();
|
if (!physical_core->IsInitialized()) {
|
||||||
if (process == nullptr) {
|
continue;
|
||||||
return;
|
}
|
||||||
|
physical_core->ArmInterface().InvalidateCacheRange(GetInteger(addr), size);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
|
void KernelCore::PrepareReschedule(std::size_t id) {
|
||||||
auto* arm_interface = process->GetArmInterface(i);
|
// TODO: Reimplement, this
|
||||||
if (arm_interface) {
|
|
||||||
arm_interface->InvalidateCacheRange(GetInteger(addr), size);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void KernelCore::RegisterKernelObject(KAutoObject* object) {
|
void KernelCore::RegisterKernelObject(KAutoObject* object) {
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
#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
|
||||||
|
@ -105,6 +104,9 @@ 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();
|
||||||
|
|
||||||
|
@ -171,11 +173,12 @@ public:
|
||||||
/// Gets the an instance of the hardware timer.
|
/// Gets the an instance of the hardware timer.
|
||||||
Kernel::KHardwareTimer& HardwareTimer();
|
Kernel::KHardwareTimer& HardwareTimer();
|
||||||
|
|
||||||
/// Gets the exclusive monitor for the process on the current core
|
/// Stops execution of 'id' core, in order to reschedule a new thread.
|
||||||
Core::ExclusiveMonitor& GetCurrentExclusiveMonitor();
|
void PrepareReschedule(std::size_t id);
|
||||||
|
|
||||||
/// Gets the JIT instance for the process on the current core
|
Core::ExclusiveMonitor& GetExclusiveMonitor();
|
||||||
Core::ARM_Interface& GetCurrentArmInterface();
|
|
||||||
|
const Core::ExclusiveMonitor& GetExclusiveMonitor() const;
|
||||||
|
|
||||||
KAutoObjectWithListContainer& ObjectListContainer();
|
KAutoObjectWithListContainer& ObjectListContainer();
|
||||||
|
|
||||||
|
|
|
@ -4,77 +4,69 @@
|
||||||
#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_process.h"
|
#include "core/hle/kernel/k_scheduler.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)
|
PhysicalCore::PhysicalCore(std::size_t core_index, Core::System& system, KScheduler& scheduler)
|
||||||
: m_core_index{core_index}, m_system{system} {}
|
: 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<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;
|
||||||
|
|
||||||
bool PhysicalCore::Run(Core::ARM_Interface& current_arm_interface) {
|
void PhysicalCore::Initialize(bool is_64_bit) {
|
||||||
// SAFETY: we need to lock around storing the JIT instance member to serialize
|
#if defined(ARCHITECTURE_x86_64) || defined(ARCHITECTURE_arm64)
|
||||||
// access with another thread that wants to send us an interrupt. Otherwise we
|
auto& kernel = m_system.Kernel();
|
||||||
// may end up sending an interrupt to an instance that is not current.
|
if (!is_64_bit) {
|
||||||
|
// We already initialized a 64-bit core, replace with a 32-bit one.
|
||||||
// Mark the instance as current.
|
m_arm_interface = std::make_unique<Core::ARM_Dynarmic_32>(
|
||||||
{
|
m_system, kernel.IsMulticore(),
|
||||||
std::scoped_lock lk{m_guard};
|
reinterpret_cast<Core::DynarmicExclusiveMonitor&>(kernel.GetExclusiveMonitor()),
|
||||||
|
m_core_index);
|
||||||
// If this core is already interrupted, return immediately.
|
}
|
||||||
if (m_is_interrupted) {
|
#else
|
||||||
return false;
|
#error Platform not supported yet.
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
m_current_arm_interface = std::addressof(current_arm_interface);
|
void PhysicalCore::Run() {
|
||||||
|
m_arm_interface->Run();
|
||||||
|
m_arm_interface->ClearExclusiveState();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Run the instance.
|
void PhysicalCore::Idle() {
|
||||||
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::WaitForInterrupt() {
|
|
||||||
// Wait for a signal.
|
|
||||||
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::scoped_lock lk{m_guard};
|
std::unique_lock lk{m_guard};
|
||||||
|
|
||||||
// Remove interrupt flag.
|
|
||||||
m_is_interrupted = false;
|
m_is_interrupted = false;
|
||||||
|
m_arm_interface->ClearInterrupt();
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace Kernel
|
} // namespace Kernel
|
||||||
|
|
|
@ -23,16 +23,19 @@ namespace Kernel {
|
||||||
|
|
||||||
class PhysicalCore {
|
class PhysicalCore {
|
||||||
public:
|
public:
|
||||||
PhysicalCore(std::size_t core_index_, Core::System& system_);
|
PhysicalCore(std::size_t core_index_, Core::System& system_, KScheduler& scheduler_);
|
||||||
~PhysicalCore();
|
~PhysicalCore();
|
||||||
|
|
||||||
YUZU_NON_COPYABLE(PhysicalCore);
|
YUZU_NON_COPYABLE(PhysicalCore);
|
||||||
YUZU_NON_MOVEABLE(PhysicalCore);
|
YUZU_NON_MOVEABLE(PhysicalCore);
|
||||||
|
|
||||||
/// Execute JIT and return whether we ran to completion
|
/// Initialize the core for the specified parameters.
|
||||||
bool Run(Core::ARM_Interface& current_arm_interface);
|
void Initialize(bool is_64_bit);
|
||||||
|
|
||||||
void WaitForInterrupt();
|
/// Execute current jit state
|
||||||
|
void Run();
|
||||||
|
|
||||||
|
void Idle();
|
||||||
|
|
||||||
/// Interrupt this physical core.
|
/// Interrupt this physical core.
|
||||||
void Interrupt();
|
void Interrupt();
|
||||||
|
@ -40,22 +43,42 @@ public:
|
||||||
/// Clear this core's interrupt
|
/// Clear this core's interrupt
|
||||||
void ClearInterrupt();
|
void ClearInterrupt();
|
||||||
|
|
||||||
bool GetIsInterrupted() const {
|
/// Check if this core is interrupted
|
||||||
return m_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;
|
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
|
||||||
|
|
|
@ -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.GetCurrentArmInterface().GetReg(n));
|
return static_cast<uint32_t>(system.CurrentArmInterface().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.GetCurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
|
system.CurrentArmInterface().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.GetCurrentArmInterface().GetReg(n);
|
return system.CurrentArmInterface().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.GetCurrentArmInterface().SetReg(n, result);
|
system.CurrentArmInterface().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
|
||||||
|
|
|
@ -102,7 +102,9 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
|
||||||
|
|
||||||
handle_debug_buffer(info1, 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<std::size_t>(thread_processor_id)).LogBacktrace();
|
||||||
}
|
}
|
||||||
|
|
||||||
if (system.DebuggerEnabled()) {
|
if (system.DebuggerEnabled()) {
|
||||||
|
|
|
@ -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.GetCurrentArmInterface();
|
auto& core = system.CurrentArmInterface();
|
||||||
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));
|
||||||
|
|
|
@ -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().GetCoreIndex());
|
return static_cast<int32_t>(system.CurrentPhysicalCore().CoreIndex());
|
||||||
}
|
}
|
||||||
|
|
||||||
int32_t GetCurrentProcessorNumber64(Core::System& system) {
|
int32_t GetCurrentProcessorNumber64(Core::System& system) {
|
||||||
|
|
|
@ -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.GetCurrentArmInterface();
|
auto& core = system.CurrentPhysicalCore().ArmInterface();
|
||||||
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.GetCurrentArmInterface();
|
auto& core = system.CurrentPhysicalCore().ArmInterface();
|
||||||
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));
|
||||||
|
|
|
@ -93,6 +93,8 @@ 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();
|
||||||
|
|
|
@ -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.GetCurrentArmInterface().GetReg(n));
|
return static_cast<uint32_t>(system.CurrentArmInterface().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.GetCurrentArmInterface().SetReg(n, static_cast<uint64_t>(result));
|
system.CurrentArmInterface().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.GetCurrentArmInterface().GetReg(n);
|
return system.CurrentArmInterface().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.GetCurrentArmInterface().SetReg(n, result);
|
system.CurrentArmInterface().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
|
||||||
|
|
|
@ -1317,6 +1317,50 @@ void ILibraryAppletCreator::CreateHandleStorage(HLERequestContext& ctx) {
|
||||||
rb.PushIpcInterface<IStorage>(system, std::move(memory));
|
rb.PushIpcInterface<IStorage>(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_)
|
IApplicationFunctions::IApplicationFunctions(Core::System& system_)
|
||||||
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
: ServiceFramework{system_, "IApplicationFunctions"}, service_context{system,
|
||||||
"IApplicationFunctions"} {
|
"IApplicationFunctions"} {
|
||||||
|
|
|
@ -314,6 +314,12 @@ private:
|
||||||
void CreateHandleStorage(HLERequestContext& ctx);
|
void CreateHandleStorage(HLERequestContext& ctx);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class ILibraryAppletSelfAccessor final : public ServiceFramework<ILibraryAppletSelfAccessor> {
|
||||||
|
public:
|
||||||
|
explicit ILibraryAppletSelfAccessor(Core::System& system_);
|
||||||
|
~ILibraryAppletSelfAccessor() override;
|
||||||
|
};
|
||||||
|
|
||||||
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
class IApplicationFunctions final : public ServiceFramework<IApplicationFunctions> {
|
||||||
public:
|
public:
|
||||||
explicit IApplicationFunctions(Core::System& system_);
|
explicit IApplicationFunctions(Core::System& system_);
|
||||||
|
|
|
@ -26,8 +26,10 @@ public:
|
||||||
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
{4, &ILibraryAppletProxy::GetDisplayController, "GetDisplayController"},
|
||||||
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
{10, &ILibraryAppletProxy::GetProcessWindingController, "GetProcessWindingController"},
|
||||||
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
{11, &ILibraryAppletProxy::GetLibraryAppletCreator, "GetLibraryAppletCreator"},
|
||||||
{20, &ILibraryAppletProxy::GetApplicationFunctions, "GetApplicationFunctions"},
|
{20, &ILibraryAppletProxy::OpenLibraryAppletSelfAccessor, "OpenLibraryAppletSelfAccessor"},
|
||||||
{21, nullptr, "GetAppletCommonFunctions"},
|
{21, nullptr, "GetAppletCommonFunctions"},
|
||||||
|
{22, nullptr, "GetHomeMenuFunctions"},
|
||||||
|
{23, nullptr, "GetGlobalStateController"},
|
||||||
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
{1000, &ILibraryAppletProxy::GetDebugFunctions, "GetDebugFunctions"},
|
||||||
};
|
};
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
@ -100,12 +102,12 @@ private:
|
||||||
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
rb.PushIpcInterface<ILibraryAppletCreator>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetApplicationFunctions(HLERequestContext& ctx) {
|
void OpenLibraryAppletSelfAccessor(HLERequestContext& ctx) {
|
||||||
LOG_DEBUG(Service_AM, "called");
|
LOG_DEBUG(Service_AM, "called");
|
||||||
|
|
||||||
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
IPC::ResponseBuilder rb{ctx, 2, 0, 1};
|
||||||
rb.Push(ResultSuccess);
|
rb.Push(ResultSuccess);
|
||||||
rb.PushIpcInterface<IApplicationFunctions>(system);
|
rb.PushIpcInterface<ILibraryAppletSelfAccessor>(system);
|
||||||
}
|
}
|
||||||
|
|
||||||
Nvnflinger::Nvnflinger& nvnflinger;
|
Nvnflinger::Nvnflinger& nvnflinger;
|
||||||
|
|
|
@ -46,8 +46,7 @@ struct Memory::Impl {
|
||||||
|
|
||||||
const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
|
const std::size_t address_space_width = process.GetPageTable().GetAddressSpaceWidth();
|
||||||
|
|
||||||
process.GetArmInterface(core_id)->PageTableChanged(*current_page_table,
|
system.ArmInterface(core_id).PageTableChanged(*current_page_table, address_space_width);
|
||||||
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,
|
||||||
|
|
|
@ -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.GetCurrentArmInterface()};
|
auto& arm{system.CurrentArmInterface()};
|
||||||
|
|
||||||
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.GetCurrentArmInterface().GetBacktrace()};
|
const auto& backtrace{system.CurrentArmInterface().GetBacktrace()};
|
||||||
for (const auto& entry : backtrace) {
|
for (const auto& entry : backtrace) {
|
||||||
out.push_back({
|
out.push_back({
|
||||||
{"module", entry.module},
|
{"module", entry.module},
|
||||||
|
|
Loading…
Reference in a new issue