From 641209adb8a1f41d6a29386f8d3d1c3b2324815c Mon Sep 17 00:00:00 2001 From: git Date: Sat, 11 Jul 2026 18:55:04 -0400 Subject: [PATCH] fix nce on linux --- src/core/arm/nce/arm_nce.cpp | 52 +++++++++++++++--------------------- 1 file changed, 21 insertions(+), 31 deletions(-) diff --git a/src/core/arm/nce/arm_nce.cpp b/src/core/arm/nce/arm_nce.cpp index c373b45535..760ae9d7f3 100644 --- a/src/core/arm/nce/arm_nce.cpp +++ b/src/core/arm/nce/arm_nce.cpp @@ -97,21 +97,20 @@ void ArmNce::UnlockThreadParameters(void* tpidr) { static_cast(tpidr)->lock.store(SpinLockUnlocked, std::memory_order_release); } -YUZU_NO_INLINE YUZU_NAKED +YUZU_NO_INLINE HaltReason ArmNce::ReturnToRunCodeByExceptionLevelChange(int tid, void *tpidr) { // x0 - tid // x1 - tpidr - // x19 - callee-saved register and our tpidr storage + // x9 - NativeExecutionParameters* // // uses tkill on linux and pthread_kill on macOS, both have the same signature: /* syscall (u32 tid, u64 signal) */ // tid is already in x0 so we don't have to explicitly pass it asm volatile( - "str x19, [SP, #-0x10]!\n" - "mov x19, x1\n" // move tpidr to x19 so it doesn't get clobbered + "mov x9, x1\n" // move tpidr to x9 so it doesn't get clobbered "mov x1, #%[sig]\n" // set x1 to SIGUSR2 #if defined(__linux__) @@ -141,8 +140,8 @@ void ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void *i #ifndef __APPLE__ // Save old value of TPIDR_EL0, load guest one u64 tpidr_el0; - asm volatile("mrs %0, TPIDR_EL0" - "msr TPIDR_EL0, %1" + asm volatile("mrs %0, TPIDR_EL0\n" + "msr TPIDR_EL0, %1\n" : "=r"(tpidr_el0) : "r"(tpidr)); tpidr->tpidr_el0 = tpidr_el0; @@ -154,8 +153,8 @@ void ArmNce::ReturnToRunCodeByExceptionLevelChangeSignalHandler(int sig, void *i // sigaction restores context and returns to guest } -YUZU_NO_INLINE YUZU_NAKED +YUZU_NO_INLINE HaltReason ArmNce::ReturnToRunCodeByTrampoline(void *tpidr, u64 trampoline_addr) { // x0 - NativeExecutionParameters* // x1 - addr @@ -168,22 +167,22 @@ HaltReason ArmNce::ReturnToRunCodeByTrampoline(void *tpidr, u64 trampoline_addr) asm volatile( "mov x3, SP\n" "ldr x2, [ x0, #%[ctx_off] ]\n" + "add x5, x2, #%[host_ctx] \n" #ifndef __APPLE__ // Load guest tpidr_el0 "mrs x4, TPIDR_EL0\n" "msr TPIDR_EL0, x0\n" // Store host sp and tpidr_el0 - "stp x3, x4, [ x2, #%[host_sp] ]\n" + "stp x3, x4, [x2, #0xE0]\n" #else // is_actually_running = true "mov w4, #1\n" "strb w0, [ x0, #%[is_running_off] ]\n" // Store host sp - "str x3, [ x2, #(%[host_ctx] + 0xE0) ]\n" + "str x3, [x5, #0xE0]\n" #endif - "add x5, x2, #%[host_ctx]\n" // Save callee-saved host GPR registers "stp x19, x20, [x5, #0x0]\n" "stp x21, x22, [x5, #0x10]\n" @@ -214,7 +213,7 @@ HaltReason ArmNce::ReturnToRunCodeByTrampoline(void *tpidr, u64 trampoline_addr) } YUZU_NAKED_END -static_assert(offsetof(HostContext, host_sp) == 0xE0); +static_assert(offsetof(HostContext, host_sp) == 0xE0); // TODO: don't use magic number void ArmNce::BreakFromRunCodeSignalHandler(int sig, void *info, void *raw_context) { NativeExecutionParameters* tpidr = reinterpret_cast(GetGuestParameters()); @@ -224,17 +223,13 @@ void ArmNce::BreakFromRunCodeSignalHandler(int sig, void *info, void *raw_contex #else if (tpidr->magic == Common::MakeMagic('Y', 'U', 'Z', 'U')) { // Load the host's TPIDR_EL0 value - u64 scratch; + void* host_tpidr = reinterpret_cast(&tpidr->native_context)->host_ctx.host_tpidr_el0; asm volatile( - "ldr %[scratch], [ %[tpidr], #[off] ]\n" - "msr TPIDR_EL0, %[scratch]\n" - : [scratch] "=&r"(scratch) - : [tpidr] "r"(nep) - : "memory" - ); + "msr TPIDR_EL0, %[host_tpidr]\n" + :: [host_tpidr] "r"(host_tpidr)); #endif SaveGuestContext(static_cast(tpidr->native_context), raw_context); - // Returning from here will enter host code. + // SaveGuestContext loads host context, returning from here will enter host code. } } @@ -249,14 +244,10 @@ void ArmNce::GuestMemoryFaultSignalHandler(int sig, void* raw_info, void* raw_co #else if (nep->magic == Common::MakeMagic('Y', 'U', 'Z', 'U')) { // Load the host's TPIDR_EL0 value - u64 scratch; + void* host_tpidr = reinterpret_cast(&nep->native_context)->host_ctx.host_tpidr_el0; asm volatile( - "ldr %[scratch], [ %[tpidr], #[off] ]\n" - "msr TPIDR_EL0, %[scratch]\n" - : [scratch] "=&r"(scratch) - : [tpidr] "r"(nep) - : "memory" - ); + "msr TPIDR_EL0, %[host_tpidr]\n" + :: [host_tpidr] "r"(host_tpidr)); #endif auto* info = static_cast(raw_info); @@ -317,19 +308,18 @@ void* ArmNce::RestoreGuestContext(void* raw_context) { // Retrieve the host context. auto host_ctx = KernelContext(&static_cast(raw_context)->uc_mcontext); - // Thread-local parameters will be located in x19. - auto* tpidr = reinterpret_cast(host_ctx.regs()[19]); + // 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. - host_ctx.regs()[19] = *reinterpret_cast(*host_ctx.sp()); // load x19 original value from the stack std::memcpy(guest_ctx->host_ctx.host_saved_vregs.data(), &host_ctx.vregs()[8], sizeof(guest_ctx->host_ctx.host_saved_vregs)); std::memcpy(guest_ctx->host_ctx.host_saved_regs.data(), &host_ctx.regs()[19], sizeof(guest_ctx->host_ctx.host_saved_regs)); // Save stack pointer. - guest_ctx->host_ctx.host_sp = *host_ctx.sp() + 16; // +16 for the space we reserve for x19 + guest_ctx->host_ctx.host_sp = *host_ctx.sp(); // Restore all guest state except tpidr_el0. *host_ctx.sp() = guest_ctx->sp; @@ -649,4 +639,4 @@ void ArmNce::InvalidateCacheRange(u64 addr, std::size_t size) { } // namespace Core -#endif // #ifdef __aarch64__ \ No newline at end of file +#endif // #ifdef __aarch64__