From c083ea7d7846ee40cfc889ed1d415f73ec78364c Mon Sep 17 00:00:00 2001 From: bunnei Date: Sun, 1 Mar 2020 23:46:10 -0500 Subject: core: Implement separate A32/A64 ARM interfaces. --- src/core/hle/kernel/kernel.cpp | 4 ++++ src/core/hle/kernel/physical_core.cpp | 19 ++++++++++++++++--- src/core/hle/kernel/physical_core.h | 6 +++++- src/core/hle/kernel/process.cpp | 3 ++- src/core/hle/kernel/scheduler.cpp | 21 ++++++++++++--------- src/core/hle/kernel/scheduler.h | 3 +-- src/core/hle/kernel/thread.cpp | 31 +++++++++++++++++-------------- src/core/hle/kernel/thread.h | 22 ++++++++++++++++------ 8 files changed, 73 insertions(+), 36 deletions(-) (limited to 'src/core/hle/kernel') diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 9232f4d7e..e47f1deed 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp @@ -186,6 +186,10 @@ struct KernelCore::Impl { return; } + for (auto& core : cores) { + core.SetIs64Bit(process->Is64BitProcess()); + } + system.Memory().SetCurrentPageTable(*process); } diff --git a/src/core/hle/kernel/physical_core.cpp b/src/core/hle/kernel/physical_core.cpp index 9303dd273..aa2787467 100644 --- a/src/core/hle/kernel/physical_core.cpp +++ b/src/core/hle/kernel/physical_core.cpp @@ -5,7 +5,8 @@ #include "common/logging/log.h" #include "core/arm/arm_interface.h" #ifdef ARCHITECTURE_x86_64 -#include "core/arm/dynarmic/arm_dynarmic.h" +#include "core/arm/dynarmic/arm_dynarmic_32.h" +#include "core/arm/dynarmic/arm_dynarmic_64.h" #endif #include "core/arm/exclusive_monitor.h" #include "core/arm/unicorn/arm_unicorn.h" @@ -20,13 +21,17 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, Core::ExclusiveMonitor& exclusive_monitor) : core_index{id} { #ifdef ARCHITECTURE_x86_64 - arm_interface = std::make_unique(system, exclusive_monitor, core_index); + arm_interface_32 = + std::make_unique(system, exclusive_monitor, core_index); + arm_interface_64 = + std::make_unique(system, exclusive_monitor, core_index); + #else arm_interface = std::make_shared(system); LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); #endif - scheduler = std::make_unique(system, *arm_interface, core_index); + scheduler = std::make_unique(system, core_index); } PhysicalCore::~PhysicalCore() = default; @@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() { scheduler->Shutdown(); } +void PhysicalCore::SetIs64Bit(bool is_64_bit) { + if (is_64_bit) { + arm_interface = arm_interface_64.get(); + } else { + arm_interface = arm_interface_32.get(); + } +} + } // namespace Kernel diff --git a/src/core/hle/kernel/physical_core.h b/src/core/hle/kernel/physical_core.h index 4c32c0f1b..3269166be 100644 --- a/src/core/hle/kernel/physical_core.h +++ b/src/core/hle/kernel/physical_core.h @@ -68,10 +68,14 @@ public: return *scheduler; } + void SetIs64Bit(bool is_64_bit); + private: std::size_t core_index; - std::unique_ptr arm_interface; + std::unique_ptr arm_interface_32; + std::unique_ptr arm_interface_64; std::unique_ptr scheduler; + Core::ARM_Interface* arm_interface{}; }; } // namespace Kernel diff --git a/src/core/hle/kernel/process.cpp b/src/core/hle/kernel/process.cpp index 2fcb7326c..edc414d69 100644 --- a/src/core/hle/kernel/process.cpp +++ b/src/core/hle/kernel/process.cpp @@ -42,7 +42,8 @@ void SetupMainThread(Process& owner_process, KernelCore& kernel, u32 priority) { // Register 1 must be a handle to the main thread const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); - thread->GetContext().cpu_registers[1] = thread_handle; + thread->GetContext32().cpu_registers[1] = thread_handle; + thread->GetContext64().cpu_registers[1] = thread_handle; // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires thread->ResumeFromWait(); diff --git a/src/core/hle/kernel/scheduler.cpp b/src/core/hle/kernel/scheduler.cpp index c65f82fb7..1140c72a3 100644 --- a/src/core/hle/kernel/scheduler.cpp +++ b/src/core/hle/kernel/scheduler.cpp @@ -383,8 +383,8 @@ void GlobalScheduler::Unlock() { // TODO(Blinkhawk): Setup the interrupts and change context on current core. } -Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) - : system(system), cpu_core(cpu_core), core_id(core_id) {} +Scheduler::Scheduler(Core::System& system, std::size_t core_id) + : system{system}, core_id{core_id} {} Scheduler::~Scheduler() = default; @@ -422,9 +422,10 @@ void Scheduler::UnloadThread() { // Save context for previous thread if (previous_thread) { - cpu_core.SaveContext(previous_thread->GetContext()); + system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); + system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64()); // Save the TPIDR_EL0 system register in case it was modified. - previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); + previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0()); if (previous_thread->GetStatus() == ThreadStatus::Running) { // This is only the case when a reschedule is triggered without the current thread @@ -451,9 +452,10 @@ void Scheduler::SwitchContext() { // Save context for previous thread if (previous_thread) { - cpu_core.SaveContext(previous_thread->GetContext()); + system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); + system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64()); // Save the TPIDR_EL0 system register in case it was modified. - previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); + previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0()); if (previous_thread->GetStatus() == ThreadStatus::Running) { // This is only the case when a reschedule is triggered without the current thread @@ -481,9 +483,10 @@ void Scheduler::SwitchContext() { system.Kernel().MakeCurrentProcess(thread_owner_process); } - cpu_core.LoadContext(new_thread->GetContext()); - cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); - cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); + system.ArmInterface(core_id).LoadContext(new_thread->GetContext32()); + system.ArmInterface(core_id).LoadContext(new_thread->GetContext64()); + system.ArmInterface(core_id).SetTlsAddress(new_thread->GetTLSAddress()); + system.ArmInterface(core_id).SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); } else { current_thread = nullptr; // Note: We do not reset the current process and current page table when idling because diff --git a/src/core/hle/kernel/scheduler.h b/src/core/hle/kernel/scheduler.h index 1c93a838c..07df33f9c 100644 --- a/src/core/hle/kernel/scheduler.h +++ b/src/core/hle/kernel/scheduler.h @@ -181,7 +181,7 @@ private: class Scheduler final { public: - explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id); + explicit Scheduler(Core::System& system, std::size_t core_id); ~Scheduler(); /// Returns whether there are any threads that are ready to run. @@ -235,7 +235,6 @@ private: std::shared_ptr selected_thread = nullptr; Core::System& system; - Core::ARM_Interface& cpu_core; u64 last_context_switch_time = 0; u64 idle_selection_count = 0; const std::size_t core_id; diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp index bf850e0b2..83e956036 100644 --- a/src/core/hle/kernel/thread.cpp +++ b/src/core/hle/kernel/thread.cpp @@ -133,15 +133,16 @@ void Thread::CancelWait() { ResumeFromWait(); } -/** - * Resets a thread context, making it ready to be scheduled and run by the CPU - * @param context Thread context to reset - * @param stack_top Address of the top of the stack - * @param entry_point Address of entry point for execution - * @param arg User argument for thread - */ -static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top, - VAddr entry_point, u64 arg) { +static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, + u32 entry_point, u32 arg) { + context = {}; + context.cpu_registers[0] = arg; + context.cpu_registers[15] = entry_point; + context.cpu_registers[13] = stack_top; +} + +static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, + VAddr entry_point, u64 arg) { context = {}; context.cpu_registers[0] = arg; context.pc = entry_point; @@ -198,9 +199,9 @@ ResultVal> Thread::Create(KernelCore& kernel, std::strin thread->owner_process->RegisterThread(thread.get()); - // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used - // to initialize the context - ResetThreadContext(thread->context, stack_top, entry_point, arg); + ResetThreadContext32(thread->context_32, static_cast(stack_top), + static_cast(entry_point), static_cast(arg)); + ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); return MakeResult>(std::move(thread)); } @@ -213,11 +214,13 @@ void Thread::SetPriority(u32 priority) { } void Thread::SetWaitSynchronizationResult(ResultCode result) { - context.cpu_registers[0] = result.raw; + context_32.cpu_registers[0] = result.raw; + context_64.cpu_registers[0] = result.raw; } void Thread::SetWaitSynchronizationOutput(s32 output) { - context.cpu_registers[1] = output; + context_32.cpu_registers[1] = output; + context_64.cpu_registers[1] = output; } s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr object) const { diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h index 129e7858a..23fdef8a4 100644 --- a/src/core/hle/kernel/thread.h +++ b/src/core/hle/kernel/thread.h @@ -102,7 +102,8 @@ public: using MutexWaitingThreads = std::vector>; - using ThreadContext = Core::ARM_Interface::ThreadContext; + using ThreadContext32 = Core::ARM_Interface::ThreadContext32; + using ThreadContext64 = Core::ARM_Interface::ThreadContext64; using ThreadSynchronizationObjects = std::vector>; @@ -273,12 +274,20 @@ public: return status == ThreadStatus::WaitSynch; } - ThreadContext& GetContext() { - return context; + ThreadContext32& GetContext32() { + return context_32; } - const ThreadContext& GetContext() const { - return context; + const ThreadContext32& GetContext32() const { + return context_32; + } + + ThreadContext64& GetContext64() { + return context_64; + } + + const ThreadContext64& GetContext64() const { + return context_64; } ThreadStatus GetStatus() const { @@ -466,7 +475,8 @@ private: void AdjustSchedulingOnPriority(u32 old_priority); void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); - Core::ARM_Interface::ThreadContext context{}; + ThreadContext32 context_32{}; + ThreadContext64 context_64{}; u64 thread_id = 0; -- cgit v1.2.3