diff options
Diffstat (limited to 'src/core/hle/kernel')
| -rw-r--r-- | src/core/hle/kernel/kernel.cpp | 4 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.cpp | 19 | ||||
| -rw-r--r-- | src/core/hle/kernel/physical_core.h | 6 | ||||
| -rw-r--r-- | src/core/hle/kernel/process.cpp | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.cpp | 21 | ||||
| -rw-r--r-- | src/core/hle/kernel/scheduler.h | 3 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.cpp | 31 | ||||
| -rw-r--r-- | src/core/hle/kernel/thread.h | 22 |
8 files changed, 73 insertions, 36 deletions
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 { | |||
| 186 | return; | 186 | return; |
| 187 | } | 187 | } |
| 188 | 188 | ||
| 189 | for (auto& core : cores) { | ||
| 190 | core.SetIs64Bit(process->Is64BitProcess()); | ||
| 191 | } | ||
| 192 | |||
| 189 | system.Memory().SetCurrentPageTable(*process); | 193 | system.Memory().SetCurrentPageTable(*process); |
| 190 | } | 194 | } |
| 191 | 195 | ||
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 @@ | |||
| 5 | #include "common/logging/log.h" | 5 | #include "common/logging/log.h" |
| 6 | #include "core/arm/arm_interface.h" | 6 | #include "core/arm/arm_interface.h" |
| 7 | #ifdef ARCHITECTURE_x86_64 | 7 | #ifdef ARCHITECTURE_x86_64 |
| 8 | #include "core/arm/dynarmic/arm_dynarmic.h" | 8 | #include "core/arm/dynarmic/arm_dynarmic_32.h" |
| 9 | #include "core/arm/dynarmic/arm_dynarmic_64.h" | ||
| 9 | #endif | 10 | #endif |
| 10 | #include "core/arm/exclusive_monitor.h" | 11 | #include "core/arm/exclusive_monitor.h" |
| 11 | #include "core/arm/unicorn/arm_unicorn.h" | 12 | #include "core/arm/unicorn/arm_unicorn.h" |
| @@ -20,13 +21,17 @@ PhysicalCore::PhysicalCore(Core::System& system, std::size_t id, | |||
| 20 | Core::ExclusiveMonitor& exclusive_monitor) | 21 | Core::ExclusiveMonitor& exclusive_monitor) |
| 21 | : core_index{id} { | 22 | : core_index{id} { |
| 22 | #ifdef ARCHITECTURE_x86_64 | 23 | #ifdef ARCHITECTURE_x86_64 |
| 23 | arm_interface = std::make_unique<Core::ARM_Dynarmic>(system, exclusive_monitor, core_index); | 24 | arm_interface_32 = |
| 25 | std::make_unique<Core::ARM_Dynarmic_32>(system, exclusive_monitor, core_index); | ||
| 26 | arm_interface_64 = | ||
| 27 | std::make_unique<Core::ARM_Dynarmic_64>(system, exclusive_monitor, core_index); | ||
| 28 | |||
| 24 | #else | 29 | #else |
| 25 | arm_interface = std::make_shared<Core::ARM_Unicorn>(system); | 30 | arm_interface = std::make_shared<Core::ARM_Unicorn>(system); |
| 26 | LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); | 31 | LOG_WARNING(Core, "CPU JIT requested, but Dynarmic not available"); |
| 27 | #endif | 32 | #endif |
| 28 | 33 | ||
| 29 | scheduler = std::make_unique<Kernel::Scheduler>(system, *arm_interface, core_index); | 34 | scheduler = std::make_unique<Kernel::Scheduler>(system, core_index); |
| 30 | } | 35 | } |
| 31 | 36 | ||
| 32 | PhysicalCore::~PhysicalCore() = default; | 37 | PhysicalCore::~PhysicalCore() = default; |
| @@ -48,4 +53,12 @@ void PhysicalCore::Shutdown() { | |||
| 48 | scheduler->Shutdown(); | 53 | scheduler->Shutdown(); |
| 49 | } | 54 | } |
| 50 | 55 | ||
| 56 | void PhysicalCore::SetIs64Bit(bool is_64_bit) { | ||
| 57 | if (is_64_bit) { | ||
| 58 | arm_interface = arm_interface_64.get(); | ||
| 59 | } else { | ||
| 60 | arm_interface = arm_interface_32.get(); | ||
| 61 | } | ||
| 62 | } | ||
| 63 | |||
| 51 | } // namespace Kernel | 64 | } // 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: | |||
| 68 | return *scheduler; | 68 | return *scheduler; |
| 69 | } | 69 | } |
| 70 | 70 | ||
| 71 | void SetIs64Bit(bool is_64_bit); | ||
| 72 | |||
| 71 | private: | 73 | private: |
| 72 | std::size_t core_index; | 74 | std::size_t core_index; |
| 73 | std::unique_ptr<Core::ARM_Interface> arm_interface; | 75 | std::unique_ptr<Core::ARM_Interface> arm_interface_32; |
| 76 | std::unique_ptr<Core::ARM_Interface> arm_interface_64; | ||
| 74 | std::unique_ptr<Kernel::Scheduler> scheduler; | 77 | std::unique_ptr<Kernel::Scheduler> scheduler; |
| 78 | Core::ARM_Interface* arm_interface{}; | ||
| 75 | }; | 79 | }; |
| 76 | 80 | ||
| 77 | } // namespace Kernel | 81 | } // 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) { | |||
| 42 | 42 | ||
| 43 | // Register 1 must be a handle to the main thread | 43 | // Register 1 must be a handle to the main thread |
| 44 | const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); | 44 | const Handle thread_handle = owner_process.GetHandleTable().Create(thread).Unwrap(); |
| 45 | thread->GetContext().cpu_registers[1] = thread_handle; | 45 | thread->GetContext32().cpu_registers[1] = thread_handle; |
| 46 | thread->GetContext64().cpu_registers[1] = thread_handle; | ||
| 46 | 47 | ||
| 47 | // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires | 48 | // Threads by default are dormant, wake up the main thread so it runs when the scheduler fires |
| 48 | thread->ResumeFromWait(); | 49 | 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() { | |||
| 383 | // TODO(Blinkhawk): Setup the interrupts and change context on current core. | 383 | // TODO(Blinkhawk): Setup the interrupts and change context on current core. |
| 384 | } | 384 | } |
| 385 | 385 | ||
| 386 | Scheduler::Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id) | 386 | Scheduler::Scheduler(Core::System& system, std::size_t core_id) |
| 387 | : system(system), cpu_core(cpu_core), core_id(core_id) {} | 387 | : system{system}, core_id{core_id} {} |
| 388 | 388 | ||
| 389 | Scheduler::~Scheduler() = default; | 389 | Scheduler::~Scheduler() = default; |
| 390 | 390 | ||
| @@ -422,9 +422,10 @@ void Scheduler::UnloadThread() { | |||
| 422 | 422 | ||
| 423 | // Save context for previous thread | 423 | // Save context for previous thread |
| 424 | if (previous_thread) { | 424 | if (previous_thread) { |
| 425 | cpu_core.SaveContext(previous_thread->GetContext()); | 425 | system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); |
| 426 | system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64()); | ||
| 426 | // Save the TPIDR_EL0 system register in case it was modified. | 427 | // Save the TPIDR_EL0 system register in case it was modified. |
| 427 | previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); | 428 | previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0()); |
| 428 | 429 | ||
| 429 | if (previous_thread->GetStatus() == ThreadStatus::Running) { | 430 | if (previous_thread->GetStatus() == ThreadStatus::Running) { |
| 430 | // This is only the case when a reschedule is triggered without the current thread | 431 | // This is only the case when a reschedule is triggered without the current thread |
| @@ -451,9 +452,10 @@ void Scheduler::SwitchContext() { | |||
| 451 | 452 | ||
| 452 | // Save context for previous thread | 453 | // Save context for previous thread |
| 453 | if (previous_thread) { | 454 | if (previous_thread) { |
| 454 | cpu_core.SaveContext(previous_thread->GetContext()); | 455 | system.ArmInterface(core_id).SaveContext(previous_thread->GetContext32()); |
| 456 | system.ArmInterface(core_id).SaveContext(previous_thread->GetContext64()); | ||
| 455 | // Save the TPIDR_EL0 system register in case it was modified. | 457 | // Save the TPIDR_EL0 system register in case it was modified. |
| 456 | previous_thread->SetTPIDR_EL0(cpu_core.GetTPIDR_EL0()); | 458 | previous_thread->SetTPIDR_EL0(system.ArmInterface(core_id).GetTPIDR_EL0()); |
| 457 | 459 | ||
| 458 | if (previous_thread->GetStatus() == ThreadStatus::Running) { | 460 | if (previous_thread->GetStatus() == ThreadStatus::Running) { |
| 459 | // This is only the case when a reschedule is triggered without the current thread | 461 | // This is only the case when a reschedule is triggered without the current thread |
| @@ -481,9 +483,10 @@ void Scheduler::SwitchContext() { | |||
| 481 | system.Kernel().MakeCurrentProcess(thread_owner_process); | 483 | system.Kernel().MakeCurrentProcess(thread_owner_process); |
| 482 | } | 484 | } |
| 483 | 485 | ||
| 484 | cpu_core.LoadContext(new_thread->GetContext()); | 486 | system.ArmInterface(core_id).LoadContext(new_thread->GetContext32()); |
| 485 | cpu_core.SetTlsAddress(new_thread->GetTLSAddress()); | 487 | system.ArmInterface(core_id).LoadContext(new_thread->GetContext64()); |
| 486 | cpu_core.SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); | 488 | system.ArmInterface(core_id).SetTlsAddress(new_thread->GetTLSAddress()); |
| 489 | system.ArmInterface(core_id).SetTPIDR_EL0(new_thread->GetTPIDR_EL0()); | ||
| 487 | } else { | 490 | } else { |
| 488 | current_thread = nullptr; | 491 | current_thread = nullptr; |
| 489 | // Note: We do not reset the current process and current page table when idling because | 492 | // 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: | |||
| 181 | 181 | ||
| 182 | class Scheduler final { | 182 | class Scheduler final { |
| 183 | public: | 183 | public: |
| 184 | explicit Scheduler(Core::System& system, Core::ARM_Interface& cpu_core, std::size_t core_id); | 184 | explicit Scheduler(Core::System& system, std::size_t core_id); |
| 185 | ~Scheduler(); | 185 | ~Scheduler(); |
| 186 | 186 | ||
| 187 | /// Returns whether there are any threads that are ready to run. | 187 | /// Returns whether there are any threads that are ready to run. |
| @@ -235,7 +235,6 @@ private: | |||
| 235 | std::shared_ptr<Thread> selected_thread = nullptr; | 235 | std::shared_ptr<Thread> selected_thread = nullptr; |
| 236 | 236 | ||
| 237 | Core::System& system; | 237 | Core::System& system; |
| 238 | Core::ARM_Interface& cpu_core; | ||
| 239 | u64 last_context_switch_time = 0; | 238 | u64 last_context_switch_time = 0; |
| 240 | u64 idle_selection_count = 0; | 239 | u64 idle_selection_count = 0; |
| 241 | const std::size_t core_id; | 240 | 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() { | |||
| 133 | ResumeFromWait(); | 133 | ResumeFromWait(); |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | /** | 136 | static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context, u32 stack_top, |
| 137 | * Resets a thread context, making it ready to be scheduled and run by the CPU | 137 | u32 entry_point, u32 arg) { |
| 138 | * @param context Thread context to reset | 138 | context = {}; |
| 139 | * @param stack_top Address of the top of the stack | 139 | context.cpu_registers[0] = arg; |
| 140 | * @param entry_point Address of entry point for execution | 140 | context.cpu_registers[15] = entry_point; |
| 141 | * @param arg User argument for thread | 141 | context.cpu_registers[13] = stack_top; |
| 142 | */ | 142 | } |
| 143 | static void ResetThreadContext(Core::ARM_Interface::ThreadContext& context, VAddr stack_top, | 143 | |
| 144 | VAddr entry_point, u64 arg) { | 144 | static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, |
| 145 | VAddr entry_point, u64 arg) { | ||
| 145 | context = {}; | 146 | context = {}; |
| 146 | context.cpu_registers[0] = arg; | 147 | context.cpu_registers[0] = arg; |
| 147 | context.pc = entry_point; | 148 | context.pc = entry_point; |
| @@ -198,9 +199,9 @@ ResultVal<std::shared_ptr<Thread>> Thread::Create(KernelCore& kernel, std::strin | |||
| 198 | 199 | ||
| 199 | thread->owner_process->RegisterThread(thread.get()); | 200 | thread->owner_process->RegisterThread(thread.get()); |
| 200 | 201 | ||
| 201 | // TODO(peachum): move to ScheduleThread() when scheduler is added so selected core is used | 202 | ResetThreadContext32(thread->context_32, static_cast<u32>(stack_top), |
| 202 | // to initialize the context | 203 | static_cast<u32>(entry_point), static_cast<u32>(arg)); |
| 203 | ResetThreadContext(thread->context, stack_top, entry_point, arg); | 204 | ResetThreadContext64(thread->context_64, stack_top, entry_point, arg); |
| 204 | 205 | ||
| 205 | return MakeResult<std::shared_ptr<Thread>>(std::move(thread)); | 206 | return MakeResult<std::shared_ptr<Thread>>(std::move(thread)); |
| 206 | } | 207 | } |
| @@ -213,11 +214,13 @@ void Thread::SetPriority(u32 priority) { | |||
| 213 | } | 214 | } |
| 214 | 215 | ||
| 215 | void Thread::SetWaitSynchronizationResult(ResultCode result) { | 216 | void Thread::SetWaitSynchronizationResult(ResultCode result) { |
| 216 | context.cpu_registers[0] = result.raw; | 217 | context_32.cpu_registers[0] = result.raw; |
| 218 | context_64.cpu_registers[0] = result.raw; | ||
| 217 | } | 219 | } |
| 218 | 220 | ||
| 219 | void Thread::SetWaitSynchronizationOutput(s32 output) { | 221 | void Thread::SetWaitSynchronizationOutput(s32 output) { |
| 220 | context.cpu_registers[1] = output; | 222 | context_32.cpu_registers[1] = output; |
| 223 | context_64.cpu_registers[1] = output; | ||
| 221 | } | 224 | } |
| 222 | 225 | ||
| 223 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> object) const { | 226 | s32 Thread::GetSynchronizationObjectIndex(std::shared_ptr<SynchronizationObject> 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: | |||
| 102 | 102 | ||
| 103 | using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>; | 103 | using MutexWaitingThreads = std::vector<std::shared_ptr<Thread>>; |
| 104 | 104 | ||
| 105 | using ThreadContext = Core::ARM_Interface::ThreadContext; | 105 | using ThreadContext32 = Core::ARM_Interface::ThreadContext32; |
| 106 | using ThreadContext64 = Core::ARM_Interface::ThreadContext64; | ||
| 106 | 107 | ||
| 107 | using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>; | 108 | using ThreadSynchronizationObjects = std::vector<std::shared_ptr<SynchronizationObject>>; |
| 108 | 109 | ||
| @@ -273,12 +274,20 @@ public: | |||
| 273 | return status == ThreadStatus::WaitSynch; | 274 | return status == ThreadStatus::WaitSynch; |
| 274 | } | 275 | } |
| 275 | 276 | ||
| 276 | ThreadContext& GetContext() { | 277 | ThreadContext32& GetContext32() { |
| 277 | return context; | 278 | return context_32; |
| 278 | } | 279 | } |
| 279 | 280 | ||
| 280 | const ThreadContext& GetContext() const { | 281 | const ThreadContext32& GetContext32() const { |
| 281 | return context; | 282 | return context_32; |
| 283 | } | ||
| 284 | |||
| 285 | ThreadContext64& GetContext64() { | ||
| 286 | return context_64; | ||
| 287 | } | ||
| 288 | |||
| 289 | const ThreadContext64& GetContext64() const { | ||
| 290 | return context_64; | ||
| 282 | } | 291 | } |
| 283 | 292 | ||
| 284 | ThreadStatus GetStatus() const { | 293 | ThreadStatus GetStatus() const { |
| @@ -466,7 +475,8 @@ private: | |||
| 466 | void AdjustSchedulingOnPriority(u32 old_priority); | 475 | void AdjustSchedulingOnPriority(u32 old_priority); |
| 467 | void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); | 476 | void AdjustSchedulingOnAffinity(u64 old_affinity_mask, s32 old_core); |
| 468 | 477 | ||
| 469 | Core::ARM_Interface::ThreadContext context{}; | 478 | ThreadContext32 context_32{}; |
| 479 | ThreadContext64 context_64{}; | ||
| 470 | 480 | ||
| 471 | u64 thread_id = 0; | 481 | u64 thread_id = 0; |
| 472 | 482 | ||