Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 0 additions & 8 deletions src/coreclr/pal/src/arch/arm64/context2.S
Original file line number Diff line number Diff line change
Expand Up @@ -296,11 +296,3 @@ LEAF_END RestoreCompleteContext, _TEXT

#endif // __APPLE__

// Incoming:
// None
//
.arch_extension sve
LEAF_ENTRY CONTEXT_GetSveLengthFromOS, _TEXT
rdvl x0, 1
ret lr
LEAF_END CONTEXT_GetSveLengthFromOS, _TEXT
15 changes: 0 additions & 15 deletions src/coreclr/pal/src/include/pal/context.h
Original file line number Diff line number Diff line change
Expand Up @@ -1622,21 +1622,6 @@ DWORD CONTEXTGetExceptionCodeForSignal(const siginfo_t *siginfo,

#endif // HAVE_MACH_EXCEPTIONS else

#if defined(HOST_ARM64)
/*++
Function :
CONTEXT_GetSveLengthFromOS
Gets the SVE vector length
Parameters :
None
Return value :
The SVE vector length in bytes
--*/
DWORD64
CONTEXT_GetSveLengthFromOS(
);
#endif // HOST_ARM64

#ifdef __cplusplus
}
Expand Down
17 changes: 13 additions & 4 deletions src/coreclr/pal/src/thread/context.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -896,11 +896,17 @@ void CONTEXTToNativeContext(CONST CONTEXT *lpContext, native_context_t *native)
if (sve && sve->head.size >= SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)))
{
//TODO-SVE: This only handles vector lengths of 128bits.
if (CONTEXT_GetSveLengthFromOS() == 16)
// Use sve->vl from the signal frame to avoid SIGILL on platforms that
// provide an SVE context record without supporting SVE instructions
// (e.g. Apple M4 with SME streaming SVE under Virtualization.Framework).
if (sve->vl == 16)
{
_ASSERT((lpContext->XStateFeaturesMask & XSTATE_MASK_ARM64_SVE) == XSTATE_MASK_ARM64_SVE);

Comment on lines +902 to 905
Copy link

Copilot AI Apr 24, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In CONTEXTToNativeContext, the SVE block later derives vq from lpContext->Vl and relies only on an _ASSERTE to ensure lpContext->Vl == sve->vl. Since _ASSERTE is compiled out in non-debug builds, a mismatch in release could make the subsequent offset calculations write to the wrong locations in the signal frame. Consider computing vq from sve->vl (the actual frame layout) and using a non-assert runtime check for equality before writing, otherwise skip updating the SVE region.

Copilot uses AI. Check for mistakes.
uint16_t vq = sve_vq_from_vl(lpContext->Vl);
// Derive vq from the signal frame's vl (the authoritative layout)
// rather than lpContext->Vl, to ensure offset calculations always
// match the actual frame even in non-debug builds.
uint16_t vq = sve_vq_from_vl(sve->vl);

// Vector length should not have changed.
_ASSERTE(lpContext->Vl == sve->vl);
Expand Down Expand Up @@ -1255,9 +1261,12 @@ void CONTEXTFromNativeContext(const native_context_t *native, LPCONTEXT lpContex
if (sve && sve->head.size >= SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(sve->vl)))
{
//TODO-SVE: This only handles vector lengths of 128bits.
if (CONTEXT_GetSveLengthFromOS() == 16)
// Use sve->vl from the signal frame to avoid SIGILL on platforms that
// provide an SVE context record without supporting SVE instructions
// (e.g. Apple M4 with SME streaming SVE under Virtualization.Framework).
if (sve->vl == 16)
{
_ASSERTE((sve->vl > 0) && (sve->vl % 16 == 0));
_ASSERTE(sve->head.size >= SVE_SIG_CONTEXT_SIZE(sve_vq_from_vl(16)));
lpContext->Vl = sve->vl;

uint16_t vq = sve_vq_from_vl(sve->vl);
Expand Down