From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/signal_i386.c | 17 ++--------------- dlls/ntdll/unix/signal_x86_64.c | 5 ----- dlls/ntdll/unix/thread.c | 8 ++++---- 3 files changed, 6 insertions(+), 24 deletions(-)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 93bcf607f41..1439ee7df97 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -607,7 +607,6 @@ struct xcontext { CONTEXT c; CONTEXT_EX c_ex; - ULONG64 host_compaction_mask; };
static inline XSAVE_AREA_HEADER *xstate_from_context( const CONTEXT *context ) @@ -831,11 +830,7 @@ static inline void save_context( struct xcontext *xcontext, const ucontext_t *si context->ContextFlags |= CONTEXT_FLOATING_POINT | CONTEXT_EXTENDED_REGISTERS; memcpy( context->ExtendedRegisters, fpux, sizeof(*fpux) ); if (!fpu) fpux_to_fpu( &context->FloatSave, fpux ); - if (xstate_extended_features() && (xs = XState_sig(fpux))) - { - context_init_xstate( context, xs ); - xcontext->host_compaction_mask = xs->CompactionMask; - } + if (xstate_extended_features() && (xs = XState_sig(fpux))) context_init_xstate( context, xs ); } if (!fpu && !fpux) save_fpu( context ); } @@ -876,15 +871,7 @@ static inline void restore_context( const struct xcontext *xcontext, ucontext_t SS_sig(sigcontext) = context->SegSs;
if (fpu) *fpu = context->FloatSave; - if (fpux) - { - XSAVE_AREA_HEADER *xs; - - memcpy( fpux, context->ExtendedRegisters, sizeof(*fpux) ); - - if (xstate_extended_features() && (xs = XState_sig(fpux))) - xs->CompactionMask = xcontext->host_compaction_mask; - } + if (fpux) memcpy( fpux, context->ExtendedRegisters, sizeof(*fpux) ); if (!fpu && !fpux) restore_fpu( context ); }
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 501ae14cae5..fc5add7c432 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -479,7 +479,6 @@ struct xcontext { CONTEXT c; CONTEXT_EX c_ex; - ULONG64 host_compaction_mask; };
static inline XSAVE_AREA_HEADER *xstate_from_context( const CONTEXT *context ) @@ -907,7 +906,6 @@ static void save_context( struct xcontext *xcontext, const ucontext_t *sigcontex * just reference sigcontext without overflowing 32 bit XState.Offset */ context_init_xstate( context, xs ); assert( xcontext->c_ex.XState.Offset == (BYTE *)xs - (BYTE *)&xcontext->c_ex ); - xcontext->host_compaction_mask = xs->CompactionMask; } } } @@ -921,7 +919,6 @@ static void save_context( struct xcontext *xcontext, const ucontext_t *sigcontex static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcontext ) { const CONTEXT *context = &xcontext->c; - XSAVE_AREA_HEADER *xs;
amd64_thread_data()->dr0 = context->Dr0; amd64_thread_data()->dr1 = context->Dr1; @@ -931,8 +928,6 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon amd64_thread_data()->dr7 = context->Dr7; set_sigcontext( context, sigcontext ); if (FPU_sig(sigcontext)) *FPU_sig(sigcontext) = context->FltSave; - if (xstate_extended_features() && (xs = XState_sig(FPU_sig(sigcontext)))) - xs->CompactionMask = xcontext->host_compaction_mask; leave_handler( sigcontext ); }
diff --git a/dlls/ntdll/unix/thread.c b/dlls/ntdll/unix/thread.c index 52cb0f26e97..bd1fbcdbfc2 100644 --- a/dlls/ntdll/unix/thread.c +++ b/dlls/ntdll/unix/thread.c @@ -688,7 +688,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma XSTATE *xs = (XSTATE *)((char *)xctx + xctx->XState.Offset);
xs->Mask &= ~4; - if (user_shared_data->XState.CompactionEnabled) xs->CompactionMask = 0x8000000000000004; + if (xs->CompactionMask) xs->CompactionMask = 0x8000000000000004; for (i = 0; i < ARRAY_SIZE( from->ymm.regs.ymm_high); i++) { if (!from->ymm.regs.ymm_high[i].low && !from->ymm.regs.ymm_high[i].high) continue; @@ -762,7 +762,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma XSTATE *xs = (XSTATE *)((char *)xctx + xctx->XState.Offset);
xs->Mask &= ~4; - if (user_shared_data->XState.CompactionEnabled) xs->CompactionMask = 0x8000000000000004; + if (xs->CompactionMask) xs->CompactionMask = 0x8000000000000004; for (i = 0; i < ARRAY_SIZE( from->ymm.regs.ymm_high); i++) { if (!from->ymm.regs.ymm_high[i].low && !from->ymm.regs.ymm_high[i].high) continue; @@ -837,7 +837,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma XSTATE *xs = (XSTATE *)((char *)xctx + xctx->XState.Offset);
xs->Mask &= ~4; - if (user_shared_data->XState.CompactionEnabled) xs->CompactionMask = 0x8000000000000004; + if (xs->CompactionMask) xs->CompactionMask = 0x8000000000000004; for (i = 0; i < ARRAY_SIZE( from->ymm.regs.ymm_high); i++) { if (!from->ymm.regs.ymm_high[i].low && !from->ymm.regs.ymm_high[i].high) continue; @@ -919,7 +919,7 @@ static NTSTATUS context_from_server( void *dst, const context_t *from, USHORT ma XSTATE *xs = (XSTATE *)((char *)xctx + xctx->XState.Offset);
xs->Mask &= ~4; - if (user_shared_data->XState.CompactionEnabled) xs->CompactionMask = 0x8000000000000004; + if (xs->CompactionMask) xs->CompactionMask = 0x8000000000000004; for (i = 0; i < ARRAY_SIZE( from->ymm.regs.ymm_high); i++) { if (!from->ymm.regs.ymm_high[i].low && !from->ymm.regs.ymm_high[i].high) continue;
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/unix/signal_i386.c | 44 ++++++++++++++++++++++++--------- dlls/ntdll/unix/signal_x86_64.c | 34 +++++++++++++++++++------ 2 files changed, 60 insertions(+), 18 deletions(-)
diff --git a/dlls/ntdll/unix/signal_i386.c b/dlls/ntdll/unix/signal_i386.c index 1439ee7df97..2a89798c7ec 100644 --- a/dlls/ntdll/unix/signal_i386.c +++ b/dlls/ntdll/unix/signal_i386.c @@ -2107,24 +2107,46 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) */ static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { - struct xcontext xcontext; + ucontext_t *ucontext = sigcontext;
init_handler( sigcontext ); - if (is_inside_syscall( sigcontext )) + + if (is_inside_syscall( ucontext )) { - DECLSPEC_ALIGN(64) XSTATE xs; - xcontext.c.ContextFlags = CONTEXT_FULL; - context_init_xstate( &xcontext.c, &xs ); + struct syscall_frame *frame = x86_thread_data()->syscall_frame; + ULONG64 saved_compaction = 0; + struct xcontext *context;
- NtGetContextThread( GetCurrentThread(), &xcontext.c ); - wait_suspend( &xcontext.c ); - NtSetContextThread( GetCurrentThread(), &xcontext.c ); + context = (struct xcontext *)(((ULONG_PTR)ESP_sig(ucontext) - sizeof(*context)) & ~15); + if ((char *)context < (char *)ntdll_get_thread_data()->kernel_stack) + { + ERR_(seh)( "kernel stack overflow.\n" ); + return; + } + context->c.ContextFlags = CONTEXT_FULL; + NtGetContextThread( GetCurrentThread(), &context->c ); + if (xstate_extended_features()) + { + context_init_xstate( &context->c, &frame->xstate ); + saved_compaction = frame->xstate.CompactionMask; + } + wait_suspend( &context->c ); + if (xstate_extended_features()) frame->xstate.CompactionMask = saved_compaction; + if (context->c.ContextFlags & 0x40) + { + /* xstate is updated directly in frame's xstate */ + context->c.ContextFlags &= ~0x40; + frame->restore_flags |= 0x40; + } + NtSetContextThread( GetCurrentThread(), &context->c ); } else { - save_context( &xcontext, sigcontext ); - wait_suspend( &xcontext.c ); - restore_context( &xcontext, sigcontext ); + struct xcontext context; + + save_context( &context, ucontext ); + wait_suspend( &context.c ); + restore_context( &context, ucontext ); } }
diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index fc5add7c432..0da0006b216 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -2155,20 +2155,40 @@ static void quit_handler( int signal, siginfo_t *siginfo, void *sigcontext ) static void usr1_handler( int signal, siginfo_t *siginfo, void *sigcontext ) { ucontext_t *ucontext = init_handler( sigcontext ); - struct xcontext context;
if (is_inside_syscall( ucontext )) { - DECLSPEC_ALIGN(64) XSTATE xs; - context.c.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; - context_init_xstate( &context.c, &xs ); + struct syscall_frame *frame = amd64_thread_data()->syscall_frame; + ULONG64 saved_compaction = 0; + struct xcontext *context;
- NtGetContextThread( GetCurrentThread(), &context.c ); - wait_suspend( &context.c ); - NtSetContextThread( GetCurrentThread(), &context.c ); + context = (struct xcontext *)(((ULONG_PTR)RSP_sig(ucontext) - sizeof(*context)) & ~15); + if ((char *)context < (char *)ntdll_get_thread_data()->kernel_stack) + { + ERR_(seh)( "kernel stack overflow.\n" ); + return; + } + context->c.ContextFlags = CONTEXT_FULL | CONTEXT_SEGMENTS; + NtGetContextThread( GetCurrentThread(), &context->c ); + if (xstate_extended_features()) + { + context_init_xstate( &context->c, &frame->xstate ); + saved_compaction = frame->xstate.CompactionMask; + } + wait_suspend( &context->c ); + if (xstate_extended_features()) frame->xstate.CompactionMask = saved_compaction; + if (context->c.ContextFlags & 0x40) + { + /* xstate is updated directly in frame's xstate */ + context->c.ContextFlags &= ~0x40; + frame->restore_flags |= 0x40; + } + NtSetContextThread( GetCurrentThread(), &context->c ); } else { + struct xcontext context; + save_context( &context, ucontext ); wait_suspend( &context.c ); restore_context( &context, ucontext );
From: Paul Gofman pgofman@codeweavers.com
--- dlls/ntdll/exception.c | 121 ++++++++++++++++++++++++++++++++++------- 1 file changed, 102 insertions(+), 19 deletions(-)
diff --git a/dlls/ntdll/exception.c b/dlls/ntdll/exception.c index a4c5a770b05..1f5c0a7eca6 100644 --- a/dlls/ntdll/exception.c +++ b/dlls/ntdll/exception.c @@ -514,6 +514,52 @@ static const struct context_parameters *context_get_parameters( ULONG context_fl return NULL; }
+/* offset is from the start of XSAVE_AREA_HEADER. */ +static int next_compacted_xstate_offset( int off, UINT64 compaction_mask, int feature_idx ) +{ + const UINT64 feature_mask = (UINT64)1 << feature_idx; + + if (compaction_mask & feature_mask) off += user_shared_data->XState.Features[feature_idx].Size; + if (user_shared_data->XState.AlignedFeatures & (feature_mask << 1)) + off = (off + 63) & ~63; + return off; +} + +/* size includes XSAVE_AREA_HEADER but not XSAVE_FORMAT (legacy save area). */ +static int xstate_get_compacted_size( UINT64 mask ) +{ + UINT64 compaction_mask; + unsigned int i; + int off; + + compaction_mask = ((UINT64)1 << 63) | mask; + mask >>= 2; + off = sizeof(XSAVE_AREA_HEADER); + i = 2; + while (mask) + { + if (mask == 1) return off + user_shared_data->XState.Features[i].Size; + off = next_compacted_xstate_offset( off, compaction_mask, i ); + mask >>= 1; + ++i; + } + return off; +} + +static int xstate_get_size( UINT64 mask ) +{ + unsigned int i; + + mask >>= 2; + if (!mask) return sizeof(XSAVE_AREA_HEADER); + i = 2; + while (mask != 1) + { + mask >>= 1; + ++i; + } + return user_shared_data->XState.Features[i].Offset + user_shared_data->XState.Features[i].Size - sizeof(XSAVE_FORMAT); +}
/********************************************************************** * RtlGetExtendedContextLength2 (NTDLL.@) @@ -539,12 +585,12 @@ NTSTATUS WINAPI RtlGetExtendedContextLength2( ULONG context_flags, ULONG *length if (!(supported_mask = RtlGetEnabledExtendedFeatures( ~(ULONG64)0) )) return STATUS_NOT_SUPPORTED;
- compaction_mask &= supported_mask; - - size = p->context_size + p->context_ex_size + offsetof(XSTATE, YmmContext) + 63; + size = p->context_size + p->context_ex_size + 63;
- if (compaction_mask & supported_mask & (1 << XSTATE_AVX)) - size += sizeof(YMMCONTEXT); + compaction_mask &= supported_mask & ~(ULONG64)3; + if (user_shared_data->XState.CompactionEnabled) size += xstate_get_compacted_size( compaction_mask ); + else if (compaction_mask) size += xstate_get_size( compaction_mask ); + else size += sizeof(XSAVE_AREA_HEADER);
*length = size; return STATUS_SUCCESS; @@ -595,11 +641,11 @@ NTSTATUS WINAPI RtlInitializeExtendedContext2( void *context, ULONG context_flag xs = (XSTATE *)(((ULONG_PTR)c_ex + p->context_ex_size + 63) & ~(ULONG_PTR)63);
c_ex->XState.Offset = (ULONG_PTR)xs - (ULONG_PTR)c_ex; - c_ex->XState.Length = offsetof(XSTATE, YmmContext); compaction_mask &= supported_mask;
- if (compaction_mask & (1 << XSTATE_AVX)) - c_ex->XState.Length += sizeof(YMMCONTEXT); + if (user_shared_data->XState.CompactionEnabled) c_ex->XState.Length = xstate_get_compacted_size( compaction_mask ); + else if (compaction_mask & ~(ULONG64)3) c_ex->XState.Length = xstate_get_size( compaction_mask ); + else c_ex->XState.Length = sizeof(XSAVE_AREA_HEADER);
memset( xs, 0, c_ex->XState.Length ); if (user_shared_data->XState.CompactionEnabled) @@ -633,6 +679,10 @@ NTSTATUS WINAPI RtlInitializeExtendedContext( void *context, ULONG context_flags void * WINAPI RtlLocateExtendedFeature2( CONTEXT_EX *context_ex, ULONG feature_id, XSTATE_CONFIGURATION *xstate_config, ULONG *length ) { + UINT64 feature_mask = (ULONG64)1 << feature_id; + XSAVE_AREA_HEADER *xs; + unsigned int offset, i; + TRACE( "context_ex %p, feature_id %lu, xstate_config %p, length %p.\n", context_ex, feature_id, xstate_config, length );
@@ -648,16 +698,31 @@ void * WINAPI RtlLocateExtendedFeature2( CONTEXT_EX *context_ex, ULONG feature_i return NULL; }
- if (feature_id != XSTATE_AVX) + if (feature_id < 2 || feature_id >= 64) return NULL;
+ xs = (XSAVE_AREA_HEADER *)((BYTE *)context_ex + context_ex->XState.Offset); + if (length) - *length = sizeof(YMMCONTEXT); + *length = xstate_config->Features[feature_id].Size; + + if (xstate_config->CompactionEnabled) + { + if (!(xs->CompactionMask & feature_mask)) return NULL; + offset = sizeof(XSAVE_AREA_HEADER); + for (i = 2; i < feature_id; ++i) + offset = next_compacted_xstate_offset( offset, xs->CompactionMask, i ); + } + else + { + if (!(feature_mask & xstate_config->EnabledFeatures)) return NULL; + offset = xstate_config->Features[feature_id].Offset - sizeof(XSAVE_FORMAT); + }
- if (context_ex->XState.Length < sizeof(XSTATE)) + if (context_ex->XState.Length < offset + xstate_config->Features[feature_id].Size) return NULL;
- return (BYTE *)context_ex + context_ex->XState.Offset + offsetof(XSTATE, YmmContext); + return (BYTE *)xs + offset; }
@@ -787,8 +852,9 @@ NTSTATUS WINAPI RtlCopyContext( CONTEXT *dst, DWORD context_flags, CONTEXT *src NTSTATUS WINAPI RtlCopyExtendedContext( CONTEXT_EX *dst, ULONG context_flags, CONTEXT_EX *src ) { const struct context_parameters *p; - XSTATE *dst_xs, *src_xs; + XSAVE_AREA_HEADER *dst_xs, *src_xs; ULONG64 feature_mask; + unsigned int i, off, size;
TRACE( "dst %p, context_flags %#lx, src %p.\n", dst, context_flags, src );
@@ -803,18 +869,35 @@ NTSTATUS WINAPI RtlCopyExtendedContext( CONTEXT_EX *dst, ULONG context_flags, CO if (!(context_flags & 0x40)) return STATUS_SUCCESS;
- if (dst->XState.Length < offsetof(XSTATE, YmmContext)) + if (dst->XState.Length < sizeof(XSAVE_AREA_HEADER)) return STATUS_BUFFER_OVERFLOW;
- dst_xs = (XSTATE *)((BYTE *)dst + dst->XState.Offset); - src_xs = (XSTATE *)((BYTE *)src + src->XState.Offset); + dst_xs = (XSAVE_AREA_HEADER *)((BYTE *)dst + dst->XState.Offset); + src_xs = (XSAVE_AREA_HEADER *)((BYTE *)src + src->XState.Offset);
- memset(dst_xs, 0, offsetof(XSTATE, YmmContext)); + memset(dst_xs, 0, sizeof(XSAVE_AREA_HEADER)); dst_xs->Mask = (src_xs->Mask & ~(ULONG64)3) & feature_mask; dst_xs->CompactionMask = user_shared_data->XState.CompactionEnabled ? ((ULONG64)1 << 63) | (src_xs->CompactionMask & feature_mask) : 0;
- if (dst_xs->Mask & 4 && src->XState.Length >= sizeof(XSTATE) && dst->XState.Length >= sizeof(XSTATE)) - memcpy( &dst_xs->YmmContext, &src_xs->YmmContext, sizeof(dst_xs->YmmContext) ); + + if (dst_xs->CompactionMask) feature_mask &= dst_xs->CompactionMask; + feature_mask = dst_xs->Mask >> 2; + + i = 2; + off = sizeof(XSAVE_AREA_HEADER); + while (1) + { + if (feature_mask & 1) + { + if (!dst_xs->CompactionMask) off = user_shared_data->XState.Features[i].Offset - sizeof(XSAVE_FORMAT); + size = user_shared_data->XState.Features[i].Size; + if (src->XState.Length < off + size || dst->XState.Length < off + size) break; + memcpy( (BYTE *)dst_xs + off, (BYTE *)src_xs + off, size ); + } + if (!(feature_mask >>= 1)) break; + if (dst_xs->CompactionMask) off = next_compacted_xstate_offset( off, dst_xs->CompactionMask, i); + ++i; + } return STATUS_SUCCESS; }
Hi,
It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated.
The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=143162
Your paranoid android.
=== debian11 (build log) ===
error: patch failed: dlls/ntdll/unix/signal_i386.c:607 error: patch failed: dlls/ntdll/unix/signal_x86_64.c:479 Task: Patch failed to apply
=== debian11b (build log) ===
error: patch failed: dlls/ntdll/unix/signal_i386.c:607 error: patch failed: dlls/ntdll/unix/signal_x86_64.c:479 Task: Patch failed to apply