[PATCH v2] ntdll: Properly save/restore FPU context in arm64 SIGUSR1 handler.
Jinoh Kang
jinoh.kang.kr at gmail.com
Wed Nov 24 02:33:12 CST 2021
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51996
Signed-off-by: Jinoh Kang <jinoh.kang.kr at gmail.com>
---
Notes:
v1 -> v2: Edit commit message.
dlls/ntdll/unix/signal_arm64.c | 116 +++++++++++++++++++--------------
1 file changed, 66 insertions(+), 50 deletions(-)
diff --git a/dlls/ntdll/unix/signal_arm64.c b/dlls/ntdll/unix/signal_arm64.c
index a52e9bccc49..4e6a0872335 100644
--- a/dlls/ntdll/unix/signal_arm64.c
+++ b/dlls/ntdll/unix/signal_arm64.c
@@ -84,7 +84,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
# define FP_sig(context) REGn_sig(29, context) /* Frame pointer */
# define LR_sig(context) REGn_sig(30, context) /* Link Register */
-static struct _aarch64_ctx *get_extended_sigcontext( ucontext_t *sigcontext, unsigned int magic )
+static struct _aarch64_ctx *get_extended_sigcontext( const ucontext_t *sigcontext, unsigned int magic )
{
struct _aarch64_ctx *ctx = (struct _aarch64_ctx *)sigcontext->uc_mcontext.__reserved;
while ((char *)ctx < (char *)(&sigcontext->uc_mcontext + 1) && ctx->magic && ctx->size)
@@ -95,7 +95,7 @@ static struct _aarch64_ctx *get_extended_sigcontext( ucontext_t *sigcontext, uns
return NULL;
}
-static struct fpsimd_context *get_fpsimd_context( ucontext_t *sigcontext )
+static struct fpsimd_context *get_fpsimd_context( const ucontext_t *sigcontext )
{
return (struct fpsimd_context *)get_extended_sigcontext( sigcontext, FPSIMD_MAGIC );
}
@@ -324,50 +324,12 @@ NTSTATUS CDECL unwind_builtin_dll( ULONG type, DISPATCHER_CONTEXT *dispatch, CON
}
-/***********************************************************************
- * save_context
- *
- * Set the register values from a sigcontext.
- */
-static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
-{
- DWORD i;
-
- context->ContextFlags = (CONTEXT_FULL & ~CONTEXT_FLOATING_POINT) |
- CONTEXT_ARM64;
- context->u.s.Fp = FP_sig(sigcontext); /* Frame pointer */
- context->u.s.Lr = LR_sig(sigcontext); /* Link register */
- context->Sp = SP_sig(sigcontext); /* Stack pointer */
- context->Pc = PC_sig(sigcontext); /* Program Counter */
- context->Cpsr = PSTATE_sig(sigcontext); /* Current State Register */
- for (i = 0; i <= 28; i++) context->u.X[i] = REGn_sig( i, sigcontext );
-}
-
-
-/***********************************************************************
- * restore_context
- *
- * Build a sigcontext from the register values.
- */
-static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
-{
- DWORD i;
-
- FP_sig(sigcontext) = context->u.s.Fp; /* Frame pointer */
- LR_sig(sigcontext) = context->u.s.Lr; /* Link register */
- SP_sig(sigcontext) = context->Sp; /* Stack pointer */
- PC_sig(sigcontext) = context->Pc; /* Program Counter */
- PSTATE_sig(sigcontext) = context->Cpsr; /* Current State Register */
- for (i = 0; i <= 28; i++) REGn_sig( i, sigcontext ) = context->u.X[i];
-}
-
-
/***********************************************************************
* save_fpu
*
* Set the FPU context from a sigcontext.
*/
-static void save_fpu( CONTEXT *context, ucontext_t *sigcontext )
+static void save_fpu( CONTEXT *context, const ucontext_t *sigcontext )
{
#ifdef linux
struct fpsimd_context *fp = get_fpsimd_context( sigcontext );
@@ -391,23 +353,62 @@ static void save_fpu( CONTEXT *context, ucontext_t *sigcontext )
*
* Restore the FPU context to a sigcontext.
*/
-static void restore_fpu( struct syscall_frame *frame, ucontext_t *sigcontext )
+static void restore_fpu( const CONTEXT *context, ucontext_t *sigcontext )
{
#ifdef linux
struct fpsimd_context *fp = get_fpsimd_context( sigcontext );
if (!fp) return;
- fp->fpcr = frame->fpcr;
- fp->fpsr = frame->fpsr;
- memcpy( fp->vregs, frame->v, sizeof(fp->vregs) );
+ fp->fpcr = context->Fpcr;
+ fp->fpsr = context->Fpsr;
+ memcpy( fp->vregs, context->V, sizeof(fp->vregs) );
#elif defined(__APPLE__)
- sigcontext->uc_mcontext->__ns.__fpcr = frame->fpcr;
- sigcontext->uc_mcontext->__ns.__fpsr = frame->fpsr;
- memcpy( sigcontext->uc_mcontext->__ns.__v, frame->v, sizeof(frame->v) );
+ sigcontext->uc_mcontext->__ns.__fpcr = context->Fpcr;
+ sigcontext->uc_mcontext->__ns.__fpsr = context->Fpsr;
+ memcpy( sigcontext->uc_mcontext->__ns.__v, context->V, sizeof(context->v) );
#endif
}
+/***********************************************************************
+ * save_context
+ *
+ * Set the register values from a sigcontext.
+ */
+static void save_context( CONTEXT *context, const ucontext_t *sigcontext )
+{
+ DWORD i;
+
+ context->ContextFlags = CONTEXT_FULL | CONTEXT_ARM64;
+ context->u.s.Fp = FP_sig(sigcontext); /* Frame pointer */
+ context->u.s.Lr = LR_sig(sigcontext); /* Link register */
+ context->Sp = SP_sig(sigcontext); /* Stack pointer */
+ context->Pc = PC_sig(sigcontext); /* Program Counter */
+ context->Cpsr = PSTATE_sig(sigcontext); /* Current State Register */
+ for (i = 0; i <= 28; i++) context->u.X[i] = REGn_sig( i, sigcontext );
+ save_fpu( context, sigcontext );
+}
+
+
+/***********************************************************************
+ * restore_context
+ *
+ * Build a sigcontext from the register values.
+ */
+static void restore_context( const CONTEXT *context, ucontext_t *sigcontext )
+{
+ DWORD i;
+
+ FP_sig(sigcontext) = context->u.s.Fp; /* Frame pointer */
+ LR_sig(sigcontext) = context->u.s.Lr; /* Link register */
+ SP_sig(sigcontext) = context->Sp; /* Stack pointer */
+ PC_sig(sigcontext) = context->Pc; /* Program Counter */
+ PSTATE_sig(sigcontext) = context->Cpsr; /* Current State Register */
+ for (i = 0; i <= 28; i++) REGn_sig( i, sigcontext ) = context->u.X[i];
+ restore_fpu( context, sigcontext );
+}
+
+
/***********************************************************************
* signal_set_full_context
*/
@@ -632,7 +633,6 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
save_context( &context, sigcontext );
- save_fpu( &context, sigcontext );
status = send_debug_event( rec, &context, TRUE );
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
@@ -1047,6 +1047,9 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext )
struct syscall_frame *frame = arm64_thread_data()->syscall_frame;
ucontext_t *context = sigcontext;
DWORD i;
+#ifdef linux
+ struct fpsimd_context *fp;
+#endif
if (!is_inside_syscall( sigcontext )) return;
@@ -1056,7 +1059,20 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext )
PC_sig(context) = frame->pc;
PSTATE_sig(context) = frame->cpsr;
for (i = 0; i <= 28; i++) REGn_sig( i, context ) = frame->x[i];
- restore_fpu( frame, context );
+
+#ifdef linux
+ fp = get_fpsimd_context( sigcontext );
+ if (fp)
+ {
+ fp->fpcr = frame->fpcr;
+ fp->fpsr = frame->fpsr;
+ memcpy( fp->vregs, frame->v, sizeof(fp->vregs) );
+ }
+#elif defined(__APPLE__)
+ sigcontext->uc_mcontext->__ns.__fpcr = frame->fpcr;
+ sigcontext->uc_mcontext->__ns.__fpsr = frame->fpsr;
+ memcpy( sigcontext->uc_mcontext->__ns.__v, frame->v, sizeof(frame->v) );
+#endif
}
--
2.33.1
More information about the wine-devel
mailing list