|
|
@ -119,10 +119,9 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { |
|
|
|
|
|
|
|
|
// Since scheduling may occur here, we cannot use any cached
|
|
|
// Since scheduling may occur here, we cannot use any cached
|
|
|
// state after returning from calls we make.
|
|
|
// state after returning from calls we make.
|
|
|
|
|
|
|
|
|
|
|
|
if (breakpoint || (prefetch_abort && may_abort)) { |
|
|
// Notify the debugger and go to sleep if a breakpoint was hit,
|
|
|
// Notify the debugger and go to sleep if a breakpoint was hit,
|
|
|
// or if the thread is unable to continue for any reason.
|
|
|
// or if the thread is unable to continue for any reason.
|
|
|
if (breakpoint || (prefetch_abort && may_abort)) { |
|
|
|
|
|
if (breakpoint) { |
|
|
if (breakpoint) { |
|
|
interface->RewindBreakpointInstruction(); |
|
|
interface->RewindBreakpointInstruction(); |
|
|
} |
|
|
} |
|
|
@ -133,26 +132,19 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { |
|
|
} |
|
|
} |
|
|
thread->RequestSuspend(SuspendType::Debug); |
|
|
thread->RequestSuspend(SuspendType::Debug); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (data_abort) { |
|
|
// Notify the debugger and go to sleep on data abort.
|
|
|
// Notify the debugger and go to sleep on data abort.
|
|
|
if (data_abort) { |
|
|
|
|
|
if (system.DebuggerEnabled()) { |
|
|
if (system.DebuggerEnabled()) { |
|
|
system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); |
|
|
system.GetDebugger().NotifyThreadWatchpoint(thread, *interface->HaltedWatchpoint()); |
|
|
} |
|
|
} |
|
|
thread->RequestSuspend(SuspendType::Debug); |
|
|
thread->RequestSuspend(SuspendType::Debug); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
// Handle system calls.
|
|
|
|
|
|
if (supervisor_call) { |
|
|
|
|
|
// Perform call.
|
|
|
|
|
|
|
|
|
} else if (supervisor_call) { |
|
|
|
|
|
// Handle system calls: Perform call.
|
|
|
Svc::Call(system, interface->GetSvcNumber()); |
|
|
Svc::Call(system, interface->GetSvcNumber()); |
|
|
return; |
|
|
return; |
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
} else if (interrupt || m_is_single_core) { |
|
|
// Handle external interrupt sources.
|
|
|
// Handle external interrupt sources.
|
|
|
if (interrupt || m_is_single_core) { |
|
|
|
|
|
return; |
|
|
return; |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
@ -160,11 +152,8 @@ void PhysicalCore::RunThread(Kernel::KThread* thread) { |
|
|
|
|
|
|
|
|
void PhysicalCore::LoadContext(const KThread* thread) { |
|
|
void PhysicalCore::LoadContext(const KThread* thread) { |
|
|
auto* const process = thread->GetOwnerProcess(); |
|
|
auto* const process = thread->GetOwnerProcess(); |
|
|
if (!process) { |
|
|
|
|
|
|
|
|
if (process) { |
|
|
// Kernel threads do not run on emulated CPU cores.
|
|
|
// Kernel threads do not run on emulated CPU cores.
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
if (interface) { |
|
|
if (interface) { |
|
|
interface->SetContext(thread->GetContext()); |
|
|
interface->SetContext(thread->GetContext()); |
|
|
@ -172,6 +161,7 @@ void PhysicalCore::LoadContext(const KThread* thread) { |
|
|
interface->SetWatchpointArray(&process->GetWatchpoints()); |
|
|
interface->SetWatchpointArray(&process->GetWatchpoints()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void PhysicalCore::LoadSvcArguments(const KProcess& process, std::span<const uint64_t, 8> args) { |
|
|
void PhysicalCore::LoadSvcArguments(const KProcess& process, std::span<const uint64_t, 8> args) { |
|
|
process.GetArmInterface(m_core_index)->SetSvcArguments(args); |
|
|
process.GetArmInterface(m_core_index)->SetSvcArguments(args); |
|
|
@ -179,16 +169,14 @@ void PhysicalCore::LoadSvcArguments(const KProcess& process, std::span<const uin |
|
|
|
|
|
|
|
|
void PhysicalCore::SaveContext(KThread* thread) const { |
|
|
void PhysicalCore::SaveContext(KThread* thread) const { |
|
|
auto* const process = thread->GetOwnerProcess(); |
|
|
auto* const process = thread->GetOwnerProcess(); |
|
|
if (!process) { |
|
|
|
|
|
|
|
|
if (process) { |
|
|
// Kernel threads do not run on emulated CPU cores.
|
|
|
// Kernel threads do not run on emulated CPU cores.
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
if (interface) { |
|
|
if (interface) { |
|
|
interface->GetContext(thread->GetContext()); |
|
|
interface->GetContext(thread->GetContext()); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void PhysicalCore::SaveSvcArguments(KProcess& process, std::span<uint64_t, 8> args) const { |
|
|
void PhysicalCore::SaveSvcArguments(KProcess& process, std::span<uint64_t, 8> args) const { |
|
|
process.GetArmInterface(m_core_index)->GetSvcArguments(args); |
|
|
process.GetArmInterface(m_core_index)->GetSvcArguments(args); |
|
|
@ -206,15 +194,13 @@ void PhysicalCore::CloneFpuStatus(KThread* dst) const { |
|
|
|
|
|
|
|
|
void PhysicalCore::LogBacktrace() { |
|
|
void PhysicalCore::LogBacktrace() { |
|
|
auto* process = GetCurrentProcessPointer(m_kernel); |
|
|
auto* process = GetCurrentProcessPointer(m_kernel); |
|
|
if (!process) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (process) { |
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
auto* interface = process->GetArmInterface(m_core_index); |
|
|
if (interface) { |
|
|
if (interface) { |
|
|
interface->LogBacktrace(process); |
|
|
interface->LogBacktrace(process); |
|
|
} |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void PhysicalCore::Idle() { |
|
|
void PhysicalCore::Idle() { |
|
|
std::unique_lock lk{m_guard}; |
|
|
std::unique_lock lk{m_guard}; |
|
|
@ -240,13 +226,11 @@ void PhysicalCore::Interrupt() { |
|
|
m_on_interrupt.notify_one(); |
|
|
m_on_interrupt.notify_one(); |
|
|
|
|
|
|
|
|
// If there is no thread running, we are done.
|
|
|
// If there is no thread running, we are done.
|
|
|
if (arm_interface == nullptr) { |
|
|
|
|
|
return; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
if (arm_interface != nullptr) { |
|
|
// Interrupt the CPU.
|
|
|
// Interrupt the CPU.
|
|
|
arm_interface->SignalInterrupt(thread); |
|
|
arm_interface->SignalInterrupt(thread); |
|
|
} |
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
void PhysicalCore::ClearInterrupt() { |
|
|
void PhysicalCore::ClearInterrupt() { |
|
|
std::scoped_lock lk{m_guard}; |
|
|
std::scoped_lock lk{m_guard}; |
|
|
|