Merge pull request #9916 from liamwhite/fpu

kernel: clone fpu status on CreateThread
This commit is contained in:
liamwhite 2023-03-09 09:19:15 -05:00 committed by GitHub
commit ec4e2d1fab
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 1 deletions

View File

@ -49,6 +49,7 @@ static void ResetThreadContext32(Core::ARM_Interface::ThreadContext32& context,
context.cpu_registers[0] = arg; context.cpu_registers[0] = arg;
context.cpu_registers[15] = entry_point; context.cpu_registers[15] = entry_point;
context.cpu_registers[13] = stack_top; context.cpu_registers[13] = stack_top;
context.fpscr = 0;
} }
static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top, static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context, VAddr stack_top,
@ -58,8 +59,8 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1; context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
context.pc = entry_point; context.pc = entry_point;
context.sp = stack_top; context.sp = stack_top;
// TODO(merry): Perform a hardware test to determine the below value.
context.fpcr = 0; context.fpcr = 0;
context.fpsr = 0;
} }
} // namespace } // namespace
@ -815,6 +816,27 @@ void KThread::Continue() {
KScheduler::OnThreadStateChanged(kernel, this, old_state); KScheduler::OnThreadStateChanged(kernel, this, old_state);
} }
void KThread::CloneFpuStatus() {
// We shouldn't reach here when starting kernel threads.
ASSERT(this->GetOwnerProcess() != nullptr);
ASSERT(this->GetOwnerProcess() == GetCurrentProcessPointer(kernel));
if (this->GetOwnerProcess()->Is64BitProcess()) {
// Clone FPSR and FPCR.
ThreadContext64 cur_ctx{};
kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
this->GetContext64().fpcr = cur_ctx.fpcr;
this->GetContext64().fpsr = cur_ctx.fpsr;
} else {
// Clone FPSCR.
ThreadContext32 cur_ctx{};
kernel.System().CurrentArmInterface().SaveContext(cur_ctx);
this->GetContext32().fpscr = cur_ctx.fpscr;
}
}
Result KThread::SetActivity(Svc::ThreadActivity activity) { Result KThread::SetActivity(Svc::ThreadActivity activity) {
// Lock ourselves. // Lock ourselves.
KScopedLightLock lk(activity_pause_lock); KScopedLightLock lk(activity_pause_lock);

View File

@ -254,6 +254,8 @@ public:
thread_context_32.tpidr = static_cast<u32>(value); thread_context_32.tpidr = static_cast<u32>(value);
} }
void CloneFpuStatus();
[[nodiscard]] ThreadContext32& GetContext32() { [[nodiscard]] ThreadContext32& GetContext32() {
return thread_context_32; return thread_context_32;
} }

View File

@ -82,6 +82,9 @@ Result CreateThread(Core::System& system, Handle* out_handle, VAddr entry_point,
// Commit the thread reservation. // Commit the thread reservation.
thread_reservation.Commit(); thread_reservation.Commit();
// Clone the current fpu status to the new thread.
thread->CloneFpuStatus();
// Register the new thread. // Register the new thread.
KThread::Register(kernel, thread); KThread::Register(kernel, thread);