ntdll: Save/restore FPU context in arm64 signal handlers.
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=51996 Signed-off-by: Jinoh Kang <jinoh.kang.kr@gmail.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
6747ecdefd
commit
9f0df41a6c
|
@ -84,7 +84,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(seh);
|
||||||
# define FP_sig(context) REGn_sig(29, context) /* Frame pointer */
|
# define FP_sig(context) REGn_sig(29, context) /* Frame pointer */
|
||||||
# define LR_sig(context) REGn_sig(30, context) /* Link Register */
|
# 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;
|
struct _aarch64_ctx *ctx = (struct _aarch64_ctx *)sigcontext->uc_mcontext.__reserved;
|
||||||
while ((char *)ctx < (char *)(&sigcontext->uc_mcontext + 1) && ctx->magic && ctx->size)
|
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;
|
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 );
|
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
|
* save_fpu
|
||||||
*
|
*
|
||||||
* Set the FPU context from a sigcontext.
|
* 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
|
#ifdef linux
|
||||||
struct fpsimd_context *fp = get_fpsimd_context( sigcontext );
|
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.
|
* 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
|
#ifdef linux
|
||||||
struct fpsimd_context *fp = get_fpsimd_context( sigcontext );
|
struct fpsimd_context *fp = get_fpsimd_context( sigcontext );
|
||||||
|
|
||||||
if (!fp) return;
|
if (!fp) return;
|
||||||
fp->fpcr = frame->fpcr;
|
fp->fpcr = context->Fpcr;
|
||||||
fp->fpsr = frame->fpsr;
|
fp->fpsr = context->Fpsr;
|
||||||
memcpy( fp->vregs, frame->v, sizeof(fp->vregs) );
|
memcpy( fp->vregs, context->V, sizeof(fp->vregs) );
|
||||||
#elif defined(__APPLE__)
|
#elif defined(__APPLE__)
|
||||||
sigcontext->uc_mcontext->__ns.__fpcr = frame->fpcr;
|
sigcontext->uc_mcontext->__ns.__fpcr = context->Fpcr;
|
||||||
sigcontext->uc_mcontext->__ns.__fpsr = frame->fpsr;
|
sigcontext->uc_mcontext->__ns.__fpsr = context->Fpsr;
|
||||||
memcpy( sigcontext->uc_mcontext->__ns.__v, frame->v, sizeof(frame->v) );
|
memcpy( sigcontext->uc_mcontext->__ns.__v, context->V, sizeof(context->v) );
|
||||||
#endif
|
#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->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
|
* signal_set_full_context
|
||||||
*/
|
*/
|
||||||
|
@ -632,7 +633,6 @@ static void setup_exception( ucontext_t *sigcontext, EXCEPTION_RECORD *rec )
|
||||||
|
|
||||||
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
|
rec->ExceptionAddress = (void *)PC_sig(sigcontext);
|
||||||
save_context( &context, sigcontext );
|
save_context( &context, sigcontext );
|
||||||
save_fpu( &context, sigcontext );
|
|
||||||
|
|
||||||
status = send_debug_event( rec, &context, TRUE );
|
status = send_debug_event( rec, &context, TRUE );
|
||||||
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
if (status == DBG_CONTINUE || status == DBG_EXCEPTION_HANDLED)
|
||||||
|
@ -1056,7 +1056,22 @@ static void usr2_handler( int signal, siginfo_t *siginfo, void *sigcontext )
|
||||||
PC_sig(context) = frame->pc;
|
PC_sig(context) = frame->pc;
|
||||||
PSTATE_sig(context) = frame->cpsr;
|
PSTATE_sig(context) = frame->cpsr;
|
||||||
for (i = 0; i <= 28; i++) REGn_sig( i, context ) = frame->x[i];
|
for (i = 0; i <= 28; i++) REGn_sig( i, context ) = frame->x[i];
|
||||||
restore_fpu( frame, context );
|
|
||||||
|
#ifdef linux
|
||||||
|
{
|
||||||
|
struct fpsimd_context *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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue