core: refactor emulated cpu core activation

This commit is contained in:
Liam
2023-11-28 14:30:39 -05:00
parent 90e87c40e8
commit 45c87c7e6e
47 changed files with 2984 additions and 3332 deletions

View File

@@ -103,9 +103,7 @@ void Break(Core::System& system, BreakReason reason, u64 info1, u64 info2) {
handle_debug_buffer(info1, info2);
auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
const auto thread_processor_id = current_thread->GetActiveCore();
system.ArmInterface(static_cast<std::size_t>(thread_processor_id)).LogBacktrace();
system.CurrentPhysicalCore().LogBacktrace();
}
const bool is_hbl = GetCurrentProcess(system.Kernel()).IsHbl();

View File

@@ -37,37 +37,36 @@ Result ReplyAndReceiveLight64From32(Core::System& system, Handle session_handle,
// Custom ABI implementation for light IPC.
template <typename F>
static void SvcWrap_LightIpc(Core::System& system, F&& cb) {
auto& core = system.CurrentArmInterface();
std::array<u32, 7> arguments{};
static void SvcWrap_LightIpc(Core::System& system, std::span<uint64_t, 8> args, F&& cb) {
std::array<u32, 7> ipc_args{};
Handle session_handle = static_cast<Handle>(core.GetReg(0));
Handle session_handle = static_cast<Handle>(args[0]);
for (int i = 0; i < 7; i++) {
arguments[i] = static_cast<u32>(core.GetReg(i + 1));
ipc_args[i] = static_cast<u32>(args[i + 1]);
}
Result ret = cb(system, session_handle, arguments.data());
Result ret = cb(system, session_handle, ipc_args.data());
core.SetReg(0, ret.raw);
args[0] = ret.raw;
for (int i = 0; i < 7; i++) {
core.SetReg(i + 1, arguments[i]);
args[i + 1] = ipc_args[i];
}
}
void SvcWrap_SendSyncRequestLight64(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64);
void SvcWrap_SendSyncRequestLight64(Core::System& system, std::span<uint64_t, 8> args) {
SvcWrap_LightIpc(system, args, SendSyncRequestLight64);
}
void SvcWrap_ReplyAndReceiveLight64(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64);
void SvcWrap_ReplyAndReceiveLight64(Core::System& system, std::span<uint64_t, 8> args) {
SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64);
}
void SvcWrap_SendSyncRequestLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, SendSyncRequestLight64From32);
void SvcWrap_SendSyncRequestLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
SvcWrap_LightIpc(system, args, SendSyncRequestLight64From32);
}
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system) {
SvcWrap_LightIpc(system, ReplyAndReceiveLight64From32);
void SvcWrap_ReplyAndReceiveLight64From32(Core::System& system, std::span<uint64_t, 8> args) {
SvcWrap_LightIpc(system, args, ReplyAndReceiveLight64From32);
}
} // namespace Kernel::Svc

View File

@@ -22,31 +22,29 @@ void CallSecureMonitor64From32(Core::System& system, ilp32::SecureMonitorArgumen
// Custom ABI for CallSecureMonitor.
void SvcWrap_CallSecureMonitor64(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
lp64::SecureMonitorArguments args{};
void SvcWrap_CallSecureMonitor64(Core::System& system, std::span<uint64_t, 8> args) {
lp64::SecureMonitorArguments smc_args{};
for (int i = 0; i < 8; i++) {
args.r[i] = core.GetReg(i);
smc_args.r[i] = args[i];
}
CallSecureMonitor64(system, std::addressof(args));
CallSecureMonitor64(system, std::addressof(smc_args));
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
args[i] = smc_args.r[i];
}
}
void SvcWrap_CallSecureMonitor64From32(Core::System& system) {
auto& core = system.CurrentPhysicalCore().ArmInterface();
ilp32::SecureMonitorArguments args{};
void SvcWrap_CallSecureMonitor64From32(Core::System& system, std::span<uint64_t, 8> args) {
ilp32::SecureMonitorArguments smc_args{};
for (int i = 0; i < 8; i++) {
args.r[i] = static_cast<u32>(core.GetReg(i));
smc_args.r[i] = static_cast<u32>(args[i]);
}
CallSecureMonitor64From32(system, std::addressof(args));
CallSecureMonitor64From32(system, std::addressof(smc_args));
for (int i = 0; i < 8; i++) {
core.SetReg(i, args.r[i]);
args[i] = smc_args.r[i];
}
}

View File

@@ -90,8 +90,6 @@ Result StartThread(Core::System& system, Handle thread_handle) {
/// Called when a thread exits
void ExitThread(Core::System& system) {
LOG_DEBUG(Kernel_SVC, "called, pc=0x{:08X}", system.CurrentArmInterface().GetPC());
auto* const current_thread = GetCurrentThreadPointer(system.Kernel());
system.GlobalSchedulerContext().RemoveThread(current_thread);
current_thread->Exit();
@@ -147,47 +145,19 @@ Result GetThreadContext3(Core::System& system, u64 out_context, Handle thread_ha
R_UNLESS(thread.IsNotNull(), ResultInvalidHandle);
// Require the handle be to a non-current thread in the current process.
const auto* current_process = GetCurrentProcessPointer(kernel);
R_UNLESS(current_process == thread->GetOwnerProcess(), ResultInvalidId);
R_UNLESS(thread->GetOwnerProcess() == GetCurrentProcessPointer(kernel), ResultInvalidHandle);
R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultBusy);
// Verify that the thread isn't terminated.
R_UNLESS(thread->GetState() != ThreadState::Terminated, ResultTerminationRequested);
// Get the thread context.
Svc::ThreadContext context{};
R_TRY(thread->GetThreadContext3(std::addressof(context)));
/// Check that the thread is not the current one.
/// NOTE: Nintendo does not check this, and thus the following loop will deadlock.
R_UNLESS(thread.GetPointerUnsafe() != GetCurrentThreadPointer(kernel), ResultInvalidId);
// Copy the thread context to user space.
R_UNLESS(
GetCurrentMemory(kernel).WriteBlock(out_context, std::addressof(context), sizeof(context)),
ResultInvalidPointer);
// Try to get the thread context until the thread isn't current on any core.
while (true) {
KScopedSchedulerLock sl{kernel};
// TODO(bunnei): Enforce that thread is suspended for debug here.
// If the thread's raw state isn't runnable, check if it's current on some core.
if (thread->GetRawState() != ThreadState::Runnable) {
bool current = false;
for (auto i = 0; i < static_cast<s32>(Core::Hardware::NUM_CPU_CORES); ++i) {
if (thread.GetPointerUnsafe() == kernel.Scheduler(i).GetSchedulerCurrentThread()) {
current = true;
break;
}
}
// If the thread is current, retry until it isn't.
if (current) {
continue;
}
}
// Get the thread context.
static thread_local Common::ScratchBuffer<u8> context;
R_TRY(thread->GetThreadContext3(context));
// Copy the thread context to user space.
GetCurrentMemory(kernel).WriteBlock(out_context, context.data(), context.size());
R_SUCCEED();
}
R_SUCCEED();
}
/// Gets the priority for the specified thread