Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Commit 546a881

Browse files
authored
Port to 2.0 - fix detection of YMM regs presence (#16577)
Port #16168 It was found that we incorrectly try to restore YMM registers in RtlRestoreContext when the processor supports xstate, but doesn't have YMM registers. This change fixes that by testing the YMM presence flag too.
1 parent 8e7216b commit 546a881

File tree

2 files changed

+18
-6
lines changed

2 files changed

+18
-6
lines changed

src/pal/src/include/pal/context.h

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,13 @@ using asm_sigcontext::_xstate;
151151

152152
#ifdef XSTATE_SUPPORTED
153153

154+
// The mask for YMM registers presence flag stored in the xstate_bv. On current Linuxes, this definition is
155+
// only in internal headers, so we define it here. The xstate_bv is extracted from the processor xstate bit
156+
// vector register, so the value is OS independent.
157+
#ifndef XSTATE_YMM
158+
#define XSTATE_YMM 4
159+
#endif
160+
154161
inline _fpx_sw_bytes *FPREG_FpxSwBytes(const ucontext_t *uc)
155162
{
156163
// Bytes 464..511 in the FXSAVE format are available for software to use for any purpose. In this case, they are used to
@@ -168,7 +175,7 @@ inline UINT32 FPREG_ExtendedSize(const ucontext_t *uc)
168175
return FPREG_FpxSwBytes(uc)->extended_size;
169176
}
170177

171-
inline bool FPREG_HasExtendedState(const ucontext_t *uc)
178+
inline bool FPREG_HasYmmRegisters(const ucontext_t *uc)
172179
{
173180
// See comments in /usr/include/x86_64-linux-gnu/asm/sigcontext.h for info on how to detect if extended state is present
174181
static_assert_no_msg(FP_XSTATE_MAGIC2_SIZE == sizeof(UINT32));
@@ -185,14 +192,19 @@ inline bool FPREG_HasExtendedState(const ucontext_t *uc)
185192
}
186193

187194
_ASSERTE(extendedSize >= FP_XSTATE_MAGIC2_SIZE);
188-
return *reinterpret_cast<UINT32 *>(reinterpret_cast<UINT8 *>(FPREG_Fpstate(uc)) + (extendedSize - FP_XSTATE_MAGIC2_SIZE))
189-
== FP_XSTATE_MAGIC2;
195+
if (*reinterpret_cast<UINT32 *>(reinterpret_cast<UINT8 *>(FPREG_Fpstate(uc)) + (extendedSize - FP_XSTATE_MAGIC2_SIZE))
196+
!= FP_XSTATE_MAGIC2)
197+
{
198+
return false;
199+
}
200+
201+
return (FPREG_FpxSwBytes(uc)->xstate_bv & XSTATE_YMM) != 0;
190202
}
191203

192204
inline void *FPREG_Xstate_Ymmh(const ucontext_t *uc)
193205
{
194206
static_assert_no_msg(sizeof(reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space) == 16 * 16);
195-
_ASSERTE(FPREG_HasExtendedState(uc));
207+
_ASSERTE(FPREG_HasYmmRegisters(uc));
196208

197209
return reinterpret_cast<_xstate *>(FPREG_Fpstate(uc))->ymmh.ymmh_space;
198210
}

src/pal/src/thread/context.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -470,7 +470,7 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native)
470470
#if defined(_AMD64_) && defined(XSTATE_SUPPORTED)
471471
if ((lpContext->ContextFlags & CONTEXT_XSTATE) == CONTEXT_XSTATE)
472472
{
473-
_ASSERTE(FPREG_HasExtendedState(native));
473+
_ASSERTE(FPREG_HasYmmRegisters(native));
474474
memcpy_s(FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16, lpContext->VectorRegister, sizeof(M128A) * 16);
475475
}
476476
#endif //_AMD64_ && XSTATE_SUPPORTED
@@ -569,7 +569,7 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex
569569
{
570570
// TODO: Enable for all Unix systems
571571
#if XSTATE_SUPPORTED
572-
if (FPREG_HasExtendedState(native))
572+
if (FPREG_HasYmmRegisters(native))
573573
{
574574
memcpy_s(lpContext->VectorRegister, sizeof(M128A) * 16, FPREG_Xstate_Ymmh(native), sizeof(M128A) * 16);
575575
}

0 commit comments

Comments
 (0)