core: hle: kernel: Pin threads on CPU exceptions.

This commit is contained in:
bunnei
2022-07-17 17:10:07 -07:00
parent 72bf844110
commit 3d9542c41f
6 changed files with 109 additions and 5 deletions

View File

@@ -167,6 +167,9 @@ add_library(core STATIC
hle/api_version.h
hle/ipc.h
hle/ipc_helpers.h
hle/kernel/arch/arm64/exception_handlers.cpp
hle/kernel/arch/arm64/exception_handlers.h
hle/kernel/arch/arm64/k_exception_context.h
hle/kernel/board/nintendo/nx/k_memory_layout.h
hle/kernel/board/nintendo/nx/k_system_control.cpp
hle/kernel/board/nintendo/nx/k_system_control.h

View File

@@ -17,6 +17,7 @@
#include "core/core.h"
#include "core/core_timing.h"
#include "core/debugger/debugger.h"
#include "core/hle/kernel/arch/arm64/exception_handlers.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
@@ -104,11 +105,11 @@ public:
case Dynarmic::A32::Exception::NoExecuteFault:
LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#08x}", pc);
ReturnException(pc, ARM_Interface::no_execute);
return;
break;
default:
if (debugger_enabled) {
ReturnException(pc, ARM_Interface::breakpoint);
return;
break;
}
parent.LogBacktrace();
@@ -116,6 +117,21 @@ public:
"ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X}, thumb = {})",
exception, pc, memory.Read32(pc), parent.IsInThumbMode());
}
// Load KExceptionContext
Kernel::Arch::Arm64::KExceptionContext exception_context{};
Core::ARM_Interface::ThreadContext32 thread_context{};
parent.LoadContext(thread_context);
for (size_t index = 0; index < thread_context.cpu_registers.size(); ++index) {
exception_context.x[index] = thread_context.cpu_registers[index];
}
exception_context.sp = thread_context.cpu_registers[13];
exception_context.pc = thread_context.cpu_registers[15];
exception_context.psr = thread_context.cpsr;
exception_context.tpidr = thread_context.tpidr;
// Kernel to handle exception
Kernel::Arch::Arm64::HandleException(parent.system.Kernel(), exception_context);
}
void CallSVC(u32 swi) override {

View File

@@ -16,6 +16,7 @@
#include "core/core_timing.h"
#include "core/debugger/debugger.h"
#include "core/hardware_properties.h"
#include "core/hle/kernel/arch/arm64/exception_handlers.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/svc.h"
#include "core/memory.h"
@@ -142,21 +143,36 @@ public:
case Dynarmic::A64::Exception::SendEvent:
case Dynarmic::A64::Exception::SendEventLocal:
case Dynarmic::A64::Exception::Yield:
return;
break;
case Dynarmic::A64::Exception::NoExecuteFault:
LOG_CRITICAL(Core_ARM, "Cannot execute instruction at unmapped address {:#016x}", pc);
ReturnException(pc, ARM_Interface::no_execute);
return;
break;
default:
if (debugger_enabled) {
ReturnException(pc, ARM_Interface::breakpoint);
return;
break;
}
parent.LogBacktrace();
LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
static_cast<std::size_t>(exception), pc, memory.Read32(pc));
}
// Load KExceptionContext
Kernel::Arch::Arm64::KExceptionContext exception_context{};
Core::ARM_Interface::ThreadContext64 thread_context{};
parent.LoadContext(thread_context);
for (size_t index = 0; index < thread_context.cpu_registers.size(); ++index) {
exception_context.x[index] = thread_context.cpu_registers[index];
}
exception_context.sp = thread_context.sp;
exception_context.pc = thread_context.pc;
exception_context.psr = thread_context.pstate;
exception_context.tpidr = thread_context.tpidr;
// Kernel to handle exception
Kernel::Arch::Arm64::HandleException(parent.system.Kernel(), exception_context);
}
void CallSVC(u32 swi) override {

View File

@@ -0,0 +1,33 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#include "core/hle/kernel/arch/arm64/exception_handlers.h"
#include "core/hle/kernel/k_process.h"
#include "core/hle/kernel/k_thread.h"
#include "core/hle/kernel/kernel.h"
namespace Kernel::Arch::Arm64 {
void HandleException(KernelCore& kernel, const KExceptionContext& context) {
auto* process = kernel.CurrentProcess();
if (!process) {
return;
}
const bool is_user_mode = (context.psr & 0xF) == 0;
if (is_user_mode) {
// If the user disable count is set, we may need to pin the current thread.
if (GetCurrentThread(kernel).GetUserDisableCount() != 0 &&
process->GetPinnedThread(GetCurrentCoreId(kernel)) == nullptr) {
KScopedSchedulerLock sl{kernel};
// Pin the current thread.
process->PinCurrentThread(GetCurrentCoreId(kernel));
// Set the interrupt flag for the thread.
GetCurrentThread(kernel).SetInterruptFlag();
}
}
}
} // namespace Kernel::Arch::Arm64

View File

@@ -0,0 +1,15 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
#include "core/hle/kernel/arch/arm64/k_exception_context.h"
namespace Kernel {
class KernelCore;
}
namespace Kernel::Arch::Arm64 {
void HandleException(KernelCore& kernel, const KExceptionContext& context);
}

View File

@@ -0,0 +1,21 @@
// SPDX-FileCopyrightText: Copyright 2022 yuzu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
#pragma once
#include "common/common_types.h"
namespace Kernel::Arch::Arm64 {
struct KExceptionContext {
u64 x[(30 - 0) + 1];
u64 sp;
u64 pc;
u32 psr;
u32 write;
u64 tpidr;
u64 reserved;
};
static_assert(sizeof(KExceptionContext) == 0x120);
} // namespace Kernel::Arch::Arm64