mirror of
https://git.zaroz.cloud/nintendo-back-up/yuzu/yuzu-mainline.git
synced 2025-12-19 10:42:41 +00:00
core: refactor emulated cpu core activation
This commit is contained in:
@@ -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();
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user