From c44b3423f3b19834cd5957e33fe698d086e302af Mon Sep 17 00:00:00 2001 From: lizzie Date: Sat, 30 Aug 2025 19:40:25 +0000 Subject: [PATCH] [nce] common ctx Signed-off-by: lizzie --- src/core/arm/nce/arm_nce.cpp | 100 ++++------------ src/core/arm/nce/interpreter_visitor.cpp | 30 +---- src/core/arm/nce/interpreter_visitor.h | 8 +- .../backend/exception_handler_posix.cpp | 107 +----------------- src/dynarmic/src/dynarmic/common/context.h | 106 +++++++++++++++++ 5 files changed, 140 insertions(+), 211 deletions(-) create mode 100644 src/dynarmic/src/dynarmic/common/context.h diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index b43ece9dd5..9bca5724ce 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -13,9 +13,10 @@ #include "core/arm/nce/patcher.h" #include "core/core.h" #include "core/memory.h" - #include "core/hle/kernel/k_process.h" +#include "dynarmic/common/context.h" + #include #include #include @@ -33,20 +34,6 @@ static_assert(offsetof(NativeExecutionParameters, native_context) == TpidrEl0Nat static_assert(offsetof(NativeExecutionParameters, lock) == TpidrEl0Lock); static_assert(offsetof(NativeExecutionParameters, magic) == TpidrEl0TlsMagic); -#ifdef __APPLE__ -_STRUCT_ARM_NEON_STATE64* GetFloatingPointState(mcontext_t& host_ctx) { - return &(host_ctx.__ns); -} -#else -fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) { - _aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved); - while (header->magic != FPSIMD_MAGIC) { - header = reinterpret_cast<_aarch64_ctx*>(reinterpret_cast(header) + header->size); - } - return reinterpret_cast(header); -} -#endif - using namespace Common::Literals; constexpr u32 StackSize = 128_KiB; @@ -59,38 +46,21 @@ void* ArmNce::RestoreGuestContext(void* raw_context) { auto* fpctx = GetFloatingPointState(host_ctx); // Restore all guest state except tpidr_el0. -#ifdef __APPLE__ // Thread-local parameters will be located in x9. - auto* tpidr = reinterpret_cast(host_ctx->__ss.__r[9]); + auto* tpidr = reinterpret_cast(CTX_X(9)); auto* guest_ctx = static_cast(tpidr->native_context); // Save host callee-saved registers. - std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &fpctx->__v[8], + std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &CTX_Q(8), sizeof(guest_ctx->host_ctx.host_saved_vregs)); // Save stack pointer. - guest_ctx->host_ctx.host_sp = host_ctx->__ss.__sp; - host_ctx->__ss.__pc = guest_ctx->sp; - host_ctx->__ss.__sp = guest_ctx->pc; - host_ctx->__ss.__pstate = guest_ctx->pstate; - fpctx->__fpcr = guest_ctx->fpcr; - fpctx->__fpsr = guest_ctx->fpsr; - std::memcpy(fpctx->__v, guest_ctx->vector_registers.data(), sizeof(fpctx->__v)); -#else - // Thread-local parameters will be located in x9. - auto* tpidr = reinterpret_cast(host_ctx.regs[9]); - auto* guest_ctx = static_cast(tpidr->native_context); - // Save host callee-saved registers. - std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &fpctx->vregs[8], - sizeof(guest_ctx->host_ctx.host_saved_vregs)); - // Save stack pointer. - guest_ctx->host_ctx.host_sp = host_ctx.sp; - host_ctx.sp = guest_ctx->sp; - host_ctx.pc = guest_ctx->pc; - host_ctx.pstate = guest_ctx->pstate; - fpctx->fpcr = guest_ctx->fpcr; - fpctx->fpsr = guest_ctx->fpsr; - std::memcpy(fpctx->vregs, guest_ctx->vector_registers.data(), sizeof(fpctx->vregs)); -#endif - std::memcpy(host_ctx.regs, guest_ctx->cpu_registers.data(), sizeof(host_ctx.regs)); + guest_ctx->host_ctx.host_sp = CTX_SP; + CTX_PC = guest_ctx->sp; + CTX_SP = guest_ctx->pc; + CTX_PSTATE = guest_ctx->pstate; + CTX_FPCR = guest_ctx->fpcr; + CTX_FPSR = guest_ctx->fpsr; + std::memcpy(&CTX_X(0), guest_ctx->cpu_registers.data(), sizeof(guest_ctx->cpu_registers)); + std::memcpy(&CTX_Q(0), guest_ctx->vector_registers.data(), sizeof(guest_ctx->vector_registers)); // Return the new thread-local storage pointer. return tpidr; } @@ -103,47 +73,25 @@ void ArmNce::SaveGuestContext(GuestContext* guest_ctx, void* raw_context) { auto* fpctx = GetFloatingPointState(host_ctx); // Save all guest registers except tpidr_el0. -#ifdef __APPLE__ - std::memcpy(guest_ctx->cpu_registers.data(), host_ctx->__ss.__r, sizeof(host_ctx->__ss.__r)); - std::memcpy(guest_ctx->vector_registers.data(), fpctx->__v, sizeof(fpctx->__v)); - guest_ctx->fpsr = fpctx->__fpsr; - guest_ctx->fpcr = fpctx->__fpcr; - guest_ctx->pstate = static_cast(host_ctx->__ss.__pstate); - guest_ctx->pc = host_ctx->__ss.__pc; - guest_ctx->sp = host_ctx->__ss.__sp; + std::memcpy(guest_ctx->cpu_registers.data(), &CTX_X(0), sizeof(guest_ctx->cpu_registers)); + std::memcpy(guest_ctx->vector_registers.data(), &CTX_Q(0), sizeof(guest_ctx->vector_registers)); + guest_ctx->fpsr = CTX_FPSR; + guest_ctx->fpcr = CTX_FPCR; + guest_ctx->pc = CTX_PC; + guest_ctx->sp = CTX_SP; + guest_ctx->pstate = u32(CTX_PSTATE); // Restore stack pointer. - host_ctx->__ss.__sp = guest_ctx->host_ctx.host_sp; - // Restore host callee-saved registers. - std::memcpy(&host_ctx->__ss.__r[19], guest_ctx->host_ctx.host_saved_regs.data(), - sizeof(guest_ctx->host_ctx.host_saved_regs)); - std::memcpy(&fpctx->__v[8], guest_ctx->host_ctx.host_saved_vregs.data(), - sizeof(guest_ctx->host_ctx.host_saved_vregs)); - // Return from the call on exit by setting pc to x30. - host_ctx->__ss.__pc = guest_ctx->host_ctx.host_saved_regs[11]; - // Clear esr_el1 and return it. - host_ctx->__ss.__r[0] = guest_ctx->esr_el1.exchange(0); -#else - std::memcpy(guest_ctx->cpu_registers.data(), host_ctx.regs, sizeof(host_ctx.regs)); - std::memcpy(guest_ctx->vector_registers.data(), fpctx->vregs, sizeof(fpctx->vregs)); - guest_ctx->fpsr = fpctx->fpsr; - guest_ctx->fpcr = fpctx->fpcr; - guest_ctx->pstate = static_cast(host_ctx.pstate); - guest_ctx->pc = host_ctx.pc; - guest_ctx->sp = host_ctx.sp; - - // Restore stack pointer. - host_ctx.sp = guest_ctx->host_ctx.host_sp; + CTX_SP = guest_ctx->host_ctx.host_sp; // Restore host callee-saved registers. - std::memcpy(&host_ctx.regs[19], guest_ctx->host_ctx.host_saved_regs.data(), + std::memcpy(&CTX_X(19), guest_ctx->host_ctx.host_saved_regs.data(), sizeof(guest_ctx->host_ctx.host_saved_regs)); std::memcpy(&fpctx->vregs[8], guest_ctx->host_ctx.host_saved_vregs.data(), sizeof(guest_ctx->host_ctx.host_saved_vregs)); // Return from the call on exit by setting pc to x30. - host_ctx.pc = guest_ctx->host_ctx.host_saved_regs[11]; + CTX_PC = guest_ctx->host_ctx.host_saved_regs[11]; // Clear esr_el1 and return it. - host_ctx.regs[0] = guest_ctx->esr_el1.exchange(0); -#endif + CTX_X(0) = guest_ctx->esr_el1.exchange(0); } bool ArmNce::HandleFailedGuestFault(GuestContext* guest_ctx, void* raw_info, void* raw_context) { @@ -182,7 +130,7 @@ bool ArmNce::HandleGuestAlignmentFault(GuestContext* guest_ctx, void* raw_info, auto& memory = guest_ctx->system->ApplicationMemory(); // Match and execute an instruction. - auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx, fpctx); + auto next_pc = MatchAndExecuteOneInstruction(memory, &host_ctx); if (next_pc) { host_ctx.pc = *next_pc; return true; diff --git a/src/core/arm/nce/interpreter_visitor.cpp b/src/core/arm/nce/interpreter_visitor.cpp index 93a710aead..2edd3f1120 100644 --- a/src/core/arm/nce/interpreter_visitor.cpp +++ b/src/core/arm/nce/interpreter_visitor.cpp @@ -790,13 +790,11 @@ bool InterpreterVisitor::LDR_reg_fpsimd(Imm<2> size, Imm<1> opc_1, Reg Rm, Imm<3 return this->SIMDOffset(scale, shift, opc_0, Rm, option, Rn, Vt); } -#ifdef __APPLE__ -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - _STRUCT_ARM_NEON_STATE64* fpctx) { - std::span regs(reinterpret_cast(context->regs), 31); - std::span vregs(reinterpret_cast(fpctx->__v), 32); - u64& sp = *reinterpret_cast(&context->sp); - const u64& pc = *reinterpret_cast(&context->pc); +std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context) { + std::span regs(reinterpret_cast(&CTX_X(0)), 31); + std::span vregs(reinterpret_cast(&CTX_Q(0)), 32); + u64& sp = *reinterpret_cast(&CTX_SP); + const u64& pc = *reinterpret_cast(&CTX_PC); InterpreterVisitor visitor(memory, regs, vregs, sp, pc); u32 instruction = memory.Read32(pc); bool was_executed = false; @@ -807,23 +805,5 @@ std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, m } return was_executed ? std::optional(pc + 4) : std::nullopt; } -#else -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - fpsimd_context* fpctx) { - std::span regs(reinterpret_cast(context->regs), 31); - std::span vregs(reinterpret_cast(fpctx->vregs), 32); - u64& sp = *reinterpret_cast(&context->sp); - const u64& pc = *reinterpret_cast(&context->pc); - InterpreterVisitor visitor(memory, regs, vregs, sp, pc); - u32 instruction = memory.Read32(pc); - bool was_executed = false; - if (auto decoder = Dynarmic::A64::Decode(instruction)) { - was_executed = decoder->get().call(visitor, instruction); - } else { - LOG_ERROR(Core_ARM, "Unallocated encoding: {:#x}", instruction); - } - return was_executed ? std::optional(pc + 4) : std::nullopt; -} -#endif } // namespace Core diff --git a/src/core/arm/nce/interpreter_visitor.h b/src/core/arm/nce/interpreter_visitor.h index 3f3eb8ce11..797cf858a1 100644 --- a/src/core/arm/nce/interpreter_visitor.h +++ b/src/core/arm/nce/interpreter_visitor.h @@ -97,12 +97,6 @@ private: const u64& m_pc; }; -#ifdef __APPLE__ -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - _STRUCT_ARM_NEON_STATE64* fpctx); -#else -std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context, - fpsimd_context* fpctx); -#endif +std::optional MatchAndExecuteOneInstruction(Core::Memory::Memory& memory, mcontext_t* context); } // namespace Core diff --git a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp index 7695df57d2..6e5472b9a0 100644 --- a/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp +++ b/src/dynarmic/src/dynarmic/backend/exception_handler_posix.cpp @@ -8,19 +8,6 @@ #include "dynarmic/backend/exception_handler.h" -#ifdef __APPLE__ -# include -# include -#else -# include -# ifndef __OpenBSD__ -# include -# endif -# ifdef __sun__ -# include -# endif -#endif - #include #include #include @@ -29,6 +16,7 @@ #include #include "dynarmic/common/assert.h" +#include "dynarmic/common/context.h" #include #include "dynarmic/common/common_types.h" @@ -148,122 +136,35 @@ void SigHandler::RemoveCodeBlock(u64 host_pc) { void SigHandler::SigAction(int sig, siginfo_t* info, void* raw_context) { ASSERT(sig == SIGSEGV || sig == SIGBUS); - -#ifndef MCL_ARCHITECTURE_RISCV - ucontext_t* ucontext = reinterpret_cast(raw_context); -#ifndef __OpenBSD__ - auto& mctx = ucontext->uc_mcontext; -#endif -#endif - -#if defined(MCL_ARCHITECTURE_X86_64) - -# if defined(__APPLE__) -# define CTX_RIP (mctx->__ss.__rip) -# define CTX_RSP (mctx->__ss.__rsp) -# elif defined(__linux__) -# define CTX_RIP (mctx.gregs[REG_RIP]) -# define CTX_RSP (mctx.gregs[REG_RSP]) -# elif defined(__FreeBSD__) -# define CTX_RIP (mctx.mc_rip) -# define CTX_RSP (mctx.mc_rsp) -# elif defined(__NetBSD__) -# define CTX_RIP (mctx.__gregs[_REG_RIP]) -# define CTX_RSP (mctx.__gregs[_REG_RSP]) -# elif defined(__OpenBSD__) -# define CTX_RIP (ucontext->sc_rip) -# define CTX_RSP (ucontext->sc_rsp) -# elif defined(__sun__) -# define CTX_RIP (mctx.gregs[REG_RIP]) -# define CTX_RSP (mctx.gregs[REG_RSP]) -# else -# error "Unknown platform" -# endif - + CTX_DECLARE(raw_context); +#ifdef ARCHITECTURE_x86_64 { std::lock_guard guard(sig_handler->code_block_infos_mutex); - const auto iter = sig_handler->FindCodeBlockInfo(CTX_RIP); if (iter != sig_handler->code_block_infos.end()) { FakeCall fc = iter->cb(CTX_RIP); - CTX_RSP -= sizeof(u64); *mcl::bit_cast(CTX_RSP) = fc.ret_rip; CTX_RIP = fc.call_rip; - return; } } - fmt::print(stderr, "Unhandled {} at rip {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_RIP); - -#elif defined(MCL_ARCHITECTURE_ARM64) - -# if defined(__APPLE__) -# define CTX_PC (mctx->__ss.__pc) -# define CTX_SP (mctx->__ss.__sp) -# define CTX_LR (mctx->__ss.__lr) -# define CTX_X(i) (mctx->__ss.__x[i]) -# define CTX_Q(i) (mctx->__ns.__v[i]) -# elif defined(__linux__) -# define CTX_PC (mctx.pc) -# define CTX_SP (mctx.sp) -# define CTX_LR (mctx.regs[30]) -# define CTX_X(i) (mctx.regs[i]) -# define CTX_Q(i) (fpctx->vregs[i]) - [[maybe_unused]] const auto fpctx = [&mctx] { - _aarch64_ctx* header = (_aarch64_ctx*)&mctx.__reserved; - while (header->magic != FPSIMD_MAGIC) { - ASSERT(header->magic && header->size); - header = (_aarch64_ctx*)((char*)header + header->size); - } - return (fpsimd_context*)header; - }(); -# elif defined(__FreeBSD__) -# define CTX_PC (mctx.mc_gpregs.gp_elr) -# define CTX_SP (mctx.mc_gpregs.gp_sp) -# define CTX_LR (mctx.mc_gpregs.gp_lr) -# define CTX_X(i) (mctx.mc_gpregs.gp_x[i]) -# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i]) -# elif defined(__NetBSD__) -# define CTX_PC (mctx.mc_gpregs.gp_elr) -# define CTX_SP (mctx.mc_gpregs.gp_sp) -# define CTX_LR (mctx.mc_gpregs.gp_lr) -# define CTX_X(i) (mctx.mc_gpregs.gp_x[i]) -# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i]) -# elif defined(__OpenBSD__) -# define CTX_PC (ucontext->sc_elr) -# define CTX_SP (ucontext->sc_sp) -# define CTX_LR (ucontext->sc_lr) -# define CTX_X(i) (ucontext->sc_x[i]) -# define CTX_Q(i) (ucontext->sc_q[i]) -# else -# error "Unknown platform" -# endif - +#elif defined(ARCHITECTURE_arm64) { std::lock_guard guard(sig_handler->code_block_infos_mutex); - const auto iter = sig_handler->FindCodeBlockInfo(CTX_PC); if (iter != sig_handler->code_block_infos.end()) { FakeCall fc = iter->cb(CTX_PC); - CTX_PC = fc.call_pc; - return; } } - fmt::print(stderr, "Unhandled {} at pc {:#018x}\n", sig == SIGSEGV ? "SIGSEGV" : "SIGBUS", CTX_PC); - #elif defined(MCL_ARCHITECTURE_RISCV) - ASSERT_FALSE("Unimplemented"); - #else - # error "Invalid architecture" - #endif struct sigaction* retry_sa = sig == SIGSEGV ? &sig_handler->old_sa_segv : &sig_handler->old_sa_bus; diff --git a/src/dynarmic/src/dynarmic/common/context.h b/src/dynarmic/src/dynarmic/common/context.h new file mode 100644 index 0000000000..6f68d61e23 --- /dev/null +++ b/src/dynarmic/src/dynarmic/common/context.h @@ -0,0 +1,106 @@ +// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + +#pragma once + +#ifdef __APPLE__ +# include +# include +#else +# include +# ifndef __OpenBSD__ +# include +# endif +# ifdef __sun__ +# include +# endif +#endif + +#ifndef MCL_ARCHITECTURE_RISCV +# ifndef __OpenBSD__ +# define CTX_DECLARE(raw_context) \ + ucontext_t* ucontext = reinterpret_cast(raw_context); \ + auto& mctx = reinterpret_cast(raw_context)->uc_mcontext; \ + [[maybe_unused]] const auto fpctx = GetFloatingPointState(mctx); +# else +# define CTX_DECLARE(raw_context) ucontext_t* ucontext = reinterpret_cast(raw_context); +# endif +#endif + +#if defined(ARCHITECTURE_x86_64) +# if defined(__APPLE__) +# define CTX_RIP (mctx->__ss.__rip) +# define CTX_RSP (mctx->__ss.__rsp) +# elif defined(__linux__) +# define CTX_RIP (mctx.gregs[REG_RIP]) +# define CTX_RSP (mctx.gregs[REG_RSP]) +# elif defined(__FreeBSD__) +# define CTX_RIP (mctx.mc_rip) +# define CTX_RSP (mctx.mc_rsp) +# elif defined(__NetBSD__) +# define CTX_RIP (mctx.__gregs[_REG_RIP]) +# define CTX_RSP (mctx.__gregs[_REG_RSP]) +# elif defined(__OpenBSD__) +# define CTX_RIP (ucontext->sc_rip) +# define CTX_RSP (ucontext->sc_rsp) +# elif defined(__sun__) +# define CTX_RIP (mctx.gregs[REG_RIP]) +# define CTX_RSP (mctx.gregs[REG_RSP]) +# else +# error "Unknown platform" +# endif +#elif defined(ARCHITECTURE_arm64) +# if defined(__APPLE__) +# define CTX_PC (mctx->__ss.__pc) +# define CTX_SP (mctx->__ss.__sp) +# define CTX_LR (mctx->__ss.__lr) +# define CTX_LR (mctx->__ss.__pstate) +# define CTX_X(i) (mctx->__ss.__x[i]) +# define CTX_Q(i) (mctx->__ns.__v[i]) +# define CTX_FPSR(i) (mctx->__ns.__fpsr) +# define CTX_FPCR(i) (mctx->__ns.__fpcr) +# elif defined(__linux__) +# define CTX_PC (mctx.pc) +# define CTX_SP (mctx.sp) +# define CTX_LR (mctx.regs[30]) +# define CTX_SP (mctx.pstate) +# define CTX_X(i) (mctx.regs[i]) +# define CTX_Q(i) (fpctx->vregs[i]) +# elif defined(__FreeBSD__) +# define CTX_PC (mctx.mc_gpregs.gp_elr) +# define CTX_SP (mctx.mc_gpregs.gp_sp) +# define CTX_LR (mctx.mc_gpregs.gp_lr) +# define CTX_X(i) (mctx.mc_gpregs.gp_x[i]) +# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i]) +# elif defined(__NetBSD__) +# define CTX_PC (mctx.mc_gpregs.gp_elr) +# define CTX_SP (mctx.mc_gpregs.gp_sp) +# define CTX_LR (mctx.mc_gpregs.gp_lr) +# define CTX_X(i) (mctx.mc_gpregs.gp_x[i]) +# define CTX_Q(i) (mctx.mc_fpregs.fp_q[i]) +# elif defined(__OpenBSD__) +# define CTX_PC (ucontext->sc_elr) +# define CTX_SP (ucontext->sc_sp) +# define CTX_LR (ucontext->sc_lr) +# define CTX_X(i) (ucontext->sc_x[i]) +# define CTX_Q(i) (ucontext->sc_q[i]) +# else +# error "Unknown platform" +# endif +#else +# error "unimplemented" +#endif + +#ifdef __APPLE__ +inline _STRUCT_ARM_NEON_STATE64* GetFloatingPointState(mcontext_t& host_ctx) { + return &(host_ctx.__ns); +} +#else +inline fpsimd_context* GetFloatingPointState(mcontext_t& host_ctx) { + _aarch64_ctx* header = reinterpret_cast<_aarch64_ctx*>(&host_ctx.__reserved); + while (header->magic != FPSIMD_MAGIC) { + header = reinterpret_cast<_aarch64_ctx*>(reinterpret_cast(header) + header->size); + } + return reinterpret_cast(header); +} +#endif