Commit 6bc2c092 authored by Paul Gofman's avatar Paul Gofman Committed by Alexandre Julliard

ntdll: Support generic xstate in Unix-side manipulation functions.

parent a10da8a4
......@@ -1139,6 +1139,8 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
return STATUS_BUFFER_OVERFLOW;
copy_xstate( xstate, &frame->xstate, xstate->Mask );
/* copy_xstate may use avx in memcpy, restore xstate not to break the tests. */
frame->restore_flags |= CONTEXT_XSTATE;
}
}
/* update the cached version of the debug registers */
......
......@@ -1172,6 +1172,8 @@ NTSTATUS WINAPI NtGetContextThread( HANDLE handle, CONTEXT *context )
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
return STATUS_BUFFER_OVERFLOW;
copy_xstate( xstate, &frame->xstate, xstate->Mask );
/* copy_xstate may use avx in memcpy, restore xstate not to break the tests. */
frame->restore_flags |= CONTEXT_XSTATE;
}
}
/* update the cached version of the debug registers */
......@@ -1382,6 +1384,8 @@ NTSTATUS get_thread_wow64_context( HANDLE handle, void *ctx, ULONG size )
if (context_ex->XState.Length < xstate_get_size( xstate->CompactionMask, xstate->Mask ))
return STATUS_BUFFER_OVERFLOW;
copy_xstate( xstate, &frame->xstate, xstate->Mask );
/* copy_xstate may use avx in memcpy, restore xstate not to break the tests. */
frame->restore_flags |= CONTEXT_XSTATE;
}
}
return STATUS_SUCCESS;
......
......@@ -250,20 +250,60 @@ BOOL xstate_compaction_enabled = FALSE;
UINT64 xstate_supported_features_mask;
UINT64 xstate_features_size;
static int xstate_feature_offset[64] = {0, 0, 576};
static int xstate_feature_size[64] = {0, 0, 256};
static UINT64 xstate_aligned_features;
static int next_xstate_offset( int off, UINT64 compaction_mask, int feature_idx )
{
const UINT64 feature_mask = (UINT64)1 << feature_idx;
if (!compaction_mask) return xstate_feature_offset[feature_idx + 1] - sizeof(XSAVE_FORMAT);
if (compaction_mask & feature_mask) off += xstate_feature_size[feature_idx];
if (xstate_aligned_features & (feature_mask << 1))
off = (off + 63) & ~63;
return off;
}
unsigned int xstate_get_size( UINT64 compaction_mask, UINT64 mask )
{
if (!(mask & ((UINT64)1 << XSTATE_AVX))) return sizeof(XSAVE_AREA_HEADER);
return sizeof(XSAVE_AREA_HEADER) + sizeof(YMMCONTEXT);
unsigned int i;
int off;
mask >>= 2;
off = sizeof(XSAVE_AREA_HEADER);
i = 2;
while (mask)
{
if (mask == 1) return off + xstate_feature_size[i];
off = next_xstate_offset( off, compaction_mask, i );
mask >>= 1;
++i;
}
return off;
}
void copy_xstate( XSAVE_AREA_HEADER *dst, XSAVE_AREA_HEADER *src, UINT64 mask )
{
unsigned int i;
int src_off, dst_off;
mask &= xstate_extended_features() & src->Mask;
if (src->CompactionMask) mask &= src->CompactionMask;
if (dst->CompactionMask) mask &= dst->CompactionMask;
dst->Mask = (dst->Mask & ~xstate_extended_features()) | mask;
if (mask & ((UINT64)1 << XSTATE_AVX))
*(YMMCONTEXT *)(dst + 1) = *(YMMCONTEXT *)(src + 1);
mask >>= 2;
src_off = dst_off = sizeof(XSAVE_AREA_HEADER);
i = 2;
while (1)
{
if (mask & 1) memcpy( (char *)dst + dst_off, (char *)src + src_off, xstate_feature_size[i] );
if (!(mask >>= 1)) break;
src_off = next_xstate_offset( src_off, src->CompactionMask, i );
dst_off = next_xstate_offset( dst_off, dst->CompactionMask, i );
++i;
}
}
#define AUTH 0x68747541 /* "Auth" */
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment