From 32f1bfd0f0ff5a109042c6ac9a53cf773acdae27 Mon Sep 17 00:00:00 2001 From: Alexandre Julliard Date: Mon, 7 Jun 2021 13:17:15 +0200 Subject: [PATCH] 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 --- dlls/ntdll/unix/signal_x86_64.c | 92 ++++++++++----------------------- tools/winebuild/import.c | 23 ++++++++- 2 files changed, 50 insertions(+), 65 deletions(-) diff --git a/dlls/ntdll/unix/signal_x86_64.c b/dlls/ntdll/unix/signal_x86_64.c index 086bfdfe066..524c9348ec2 100644 --- a/dlls/ntdll/unix/signal_x86_64.c +++ b/dlls/ntdll/unix/signal_x86_64.c @@ -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; } diff --git a/tools/winebuild/import.c b/tools/winebuild/import.c index 3acf720e1c6..3bd139a2b31 100644 --- a/tools/winebuild/import.c +++ b/tools/winebuild/import.c @@ -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" );