ntdll: Only restore the modified parts of the syscall frame on x86-64.

Based on a patch by Jacek Caban.

Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Alexandre Julliard 2021-06-07 13:17:15 +02:00
parent ba5d73d796
commit 32f1bfd0f0
2 changed files with 50 additions and 65 deletions

View File

@ -281,31 +281,31 @@ C_ASSERT( sizeof(struct syscall_xsave) == 0x340 );
struct syscall_frame
{
ULONG64 rax; /* 0000 */
ULONG64 rbx; /* 0008 */
ULONG64 rcx; /* 0010 */
ULONG64 rdx; /* 0018 */
ULONG64 rsi; /* 0020 */
ULONG64 rdi; /* 0028 */
ULONG64 r8; /* 0030 */
ULONG64 r9; /* 0038 */
ULONG64 r10; /* 0040 */
ULONG64 r11; /* 0048 */
ULONG64 r12; /* 0050 */
ULONG64 r13; /* 0058 */
ULONG64 r14; /* 0060 */
ULONG64 r15; /* 0068 */
ULONG64 rip; /* 0070 */
WORD cs; /* 0078 */
WORD ds; /* 007a */
WORD es; /* 007c */
WORD fs; /* 007e */
ULONG64 eflags; /* 0080 */
ULONG64 rsp; /* 0088 */
WORD ss; /* 0090 */
WORD gs; /* 0092 */
WORD pad[2]; /* 0094 */
ULONG64 rbp; /* 0098 */
ULONG64 rax; /* 0000 */
ULONG64 rbx; /* 0008 */
ULONG64 rcx; /* 0010 */
ULONG64 rdx; /* 0018 */
ULONG64 rsi; /* 0020 */
ULONG64 rdi; /* 0028 */
ULONG64 r8; /* 0030 */
ULONG64 r9; /* 0038 */
ULONG64 r10; /* 0040 */
ULONG64 r11; /* 0048 */
ULONG64 r12; /* 0050 */
ULONG64 r13; /* 0058 */
ULONG64 r14; /* 0060 */
ULONG64 r15; /* 0068 */
ULONG64 rip; /* 0070 */
WORD cs; /* 0078 */
WORD ds; /* 007a */
WORD es; /* 007c */
WORD fs; /* 007e */
ULONG64 eflags; /* 0080 */
ULONG64 rsp; /* 0088 */
WORD ss; /* 0090 */
WORD gs; /* 0092 */
DWORD restore_flags; /* 0094 */
ULONG64 rbp; /* 0098 */
};
C_ASSERT( sizeof( struct syscall_frame ) == 0xa0);
@ -1558,34 +1558,6 @@ static void restore_context( const struct xcontext *xcontext, ucontext_t *sigcon
}
/***********************************************************************
* set_full_cpu_context
*
* Set the new CPU context.
*/
extern void set_full_cpu_context(void) DECLSPEC_HIDDEN;
__ASM_GLOBAL_FUNC( set_full_cpu_context,
"movq %gs:0x30,%rdx\n\t"
"movq 0x328(%rdx),%rsp\n\t" /* amd64_thread_data()->syscall_frame */
"movq $0,0x328(%rdx)\n\t"
"movq 0x00(%rsp),%rax\n\t"
"movq 0x08(%rsp),%rbx\n\t"
"movq 0x10(%rsp),%rcx\n\t"
"movq 0x18(%rsp),%rdx\n\t"
"movq 0x20(%rsp),%rsi\n\t"
"movq 0x28(%rsp),%rdi\n\t"
"movq 0x30(%rsp),%r8\n\t"
"movq 0x38(%rsp),%r9\n\t"
"movq 0x40(%rsp),%r10\n\t"
"movq 0x48(%rsp),%r11\n\t"
"movq 0x50(%rsp),%r12\n\t"
"movq 0x58(%rsp),%r13\n\t"
"movq 0x60(%rsp),%r14\n\t"
"movq 0x68(%rsp),%r15\n\t"
"movq 0x98(%rsp),%rbp\n\t"
"leaq 0x70(%rsp),%rsp\n\t"
"iretq" )
/***********************************************************************
* signal_restore_full_cpu_context
*
@ -1593,17 +1565,7 @@ __ASM_GLOBAL_FUNC( set_full_cpu_context,
*/
void signal_restore_full_cpu_context(void)
{
struct syscall_xsave *xsave = get_syscall_xsave( amd64_thread_data()->syscall_frame );
if (cpu_info.ProcessorFeatureBits & CPU_FEATURE_XSAVE)
{
__asm__ volatile( "xrstor64 %0" : : "m"(xsave->xsave), "a" (7), "d" (0) );
}
else
{
__asm__ volatile( "fxrstor64 %0" : : "m"(xsave->xsave) );
}
set_full_cpu_context();
amd64_thread_data()->syscall_frame->restore_flags |= CONTEXT_INTEGER;
}
@ -1708,6 +1670,8 @@ NTSTATUS WINAPI NtSetContextThread( HANDLE handle, const CONTEXT *context )
}
else xsave->xstate.Mask &= ~XSTATE_MASK_GSSE;
}
frame->restore_flags |= flags & ~CONTEXT_INTEGER;
return STATUS_SUCCESS;
}

View File

@ -1614,6 +1614,7 @@ static void output_syscall_dispatcher(void)
output( "\tmovw %%fs,-0x1a(%%rbp)\n" );
output( "\tmovw %%ss,-0x8(%%rbp)\n" );
output( "\tmovw %%gs,-0x6(%%rbp)\n" );
output( "\tmovl $0,-0x4(%%rbp)\n" );
output( "\tmovq %%rsp,%%r12\n" );
output( "\tmovq %%rax,%%r13\n" );
output( "\tmovl %s(%%rip),%%r14d\n", asm_name("__wine_syscall_flags") );
@ -1667,6 +1668,9 @@ static void output_syscall_dispatcher(void)
output( "\tcallq *(%%r10,%%r13,8)\n" );
output( "2:\tmovq %%gs:0x30,%%rcx\n" );
output( "\tmovq $0,0x328(%%rcx)\n" );
output( "\tmovl -4(%%rbp),%%ecx\n" ); /* frame->restore_flags */
output( "\ttestl $0x48,%%ecx\n" ); /* CONTEXT_FLOATING_POINT | CONTEXT_XSTATE */
output( "\tjz 4f\n" );
output( "\ttestl $3,%%r14d\n" ); /* SYSCALL_HAVE_XSAVE | SYSCALL_HAVE_XSAVEC */
output( "\tjz 3f\n" );
output( "\tmovq %%rax,%%r11\n" );
@ -1687,7 +1691,24 @@ static void output_syscall_dispatcher(void)
output_cfi( ".cfi_same_value %%rsi" );
output( "\tmovq -0x90(%%rbp),%%rbx\n" );
output_cfi( ".cfi_same_value %%rbx" );
output( "\tleaq -0x28(%%rbp),%%rsp\n" );
output( "\ttestl $0x3,%%ecx\n" ); /* CONTEXT_CONTROL | CONTEXT_INTEGER */
output( "\tjnz 1f\n" );
output( "\tmovq -0x28(%%rbp),%%rcx\n" ); /* frame->rip */
output( "\tleaq -0x10(%%rbp),%%rsp\n" ); /* frame->rsp */
output( "\tmovq (%%rbp),%%rbp\n" );
output_cfi( ".cfi_same_value %%rbp" );
output( "\tpopq %%rsp\n" );
output( "\tjmpq *%%rcx\n" );
output( "1:\ttestl $0x2,%%ecx\n" ); /* CONTEXT_INTEGER */
output( "\tjz 1f\n" );
output( "\tmovq -0x98(%%rbp),%%rax\n" );
output( "\tmovq -0x88(%%rbp),%%rcx\n" );
output( "\tmovq -0x80(%%rbp),%%rdx\n" );
output( "\tmovq -0x68(%%rbp),%%r8\n" );
output( "\tmovq -0x60(%%rbp),%%r9\n" );
output( "\tmovq -0x58(%%rbp),%%r10\n" );
output( "\tmovq -0x50(%%rbp),%%r11\n" );
output( "1:\tleaq -0x28(%%rbp),%%rsp\n" );
output_cfi( ".cfi_def_cfa_register %%rsp" );
output_cfi( ".cfi_adjust_cfa_offset 40" );
output( "\tmovq (%%rbp),%%rbp\n" );