Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1754133AbbGXNr6 (ORCPT ); Fri, 24 Jul 2015 09:47:58 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43233 "EHLO mx1.redhat.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753862AbbGXNry (ORCPT ); Fri, 24 Jul 2015 09:47:54 -0400 From: Denys Vlasenko To: Ingo Molnar Cc: Denys Vlasenko , Linus Torvalds , "Krzysztof A. Sobiecki" , Steven Rostedt , Borislav Petkov , "H. Peter Anvin" , Andy Lutomirski , Oleg Nesterov , Frederic Weisbecker , Alexei Starovoitov , Will Drewry , Kees Cook , x86@kernel.org, linux-kernel@vger.kernel.org Subject: [PATCH 1/3] x86/asm/entry/32: Massage SYSENTER32 fast path to be nearly identical to SYSCALL32 Date: Fri, 24 Jul 2015 15:47:46 +0200 Message-Id: <1437745668-31802-1-git-send-email-dvlasenk@redhat.com> Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 4707 Lines: 136 This change swaps a few instructions in final register restoring/zeroing section of SYSENTER fast path, and adds/deletes a few empty lines. After this, the difference between SYSENTER and SYCALL fast paths (after the prologue which saved pt_regs) is very small: they differ merely in the choice of register to hold arg6 (EBP or R9) and in the value of EDX on exit: SYSENTER ABI doesn't need to preserve it, so it is zeroed. SYSCALL preserves it: |(prologue is different) | orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) | testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) |- jnz sysenter_tracesys |+ jnz cstar_tracesys | |-sysenter_do_call: |+cstar_do_call: | /* 32-bit syscall -> 64-bit C ABI argument conversion */ | movl %edi, %r8d /* arg5 */ |- movl %ebp, %r9d /* arg6 */ |+ /* r9 already loaded */ /* arg6 */ | xchg %ecx, %esi /* rsi:arg2, rcx:arg4 */ | movl %ebx, %edi /* arg1 */ | movl %edx, %edx /* arg3 (zero extension) */ | |-sysenter_dispatch: |+cstar_dispatch: | cmpq $(IA32_NR_syscalls-1), %rax | ja 1f | call *ia32_sys_call_table(, %rax, 8) |@@ -19,15 +19,15 @@ | DISABLE_INTERRUPTS(CLBR_NONE) | TRACE_IRQS_OFF | testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) |- jnz sysexit_audit |+ jnz sysretl_audit | |-sysexit_from_sys_call: |+sysretl_from_sys_call: | andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) |+ movl RDX(%rsp), %edx | movl RSI(%rsp), %esi | movl RDI(%rsp), %edi | movl RIP(%rsp), %ecx | movl EFLAGS(%rsp), %r11d |- xorl %edx, %edx | xorq %r10, %r10 | xorq %r9, %r9 | xorq %r8, %r8 |(the rest of fast path, up to final SYSRET32, is identical) This is a preparatory change which allows to drop most of SYSENTER machinery and make SYSENTER reuse SYSCALL code. Signed-off-by: Denys Vlasenko CC: Ingo Molnar CC: Linus Torvalds CC: Krzysztof A. Sobiecki CC: Steven Rostedt CC: Borislav Petkov CC: "H. Peter Anvin" CC: Andy Lutomirski CC: Oleg Nesterov CC: Frederic Weisbecker CC: Alexei Starovoitov CC: Will Drewry CC: Kees Cook CC: x86@kernel.org CC: linux-kernel@vger.kernel.org --- arch/x86/entry/entry_64_compat.S | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/arch/x86/entry/entry_64_compat.S b/arch/x86/entry/entry_64_compat.S index 8997383..9f9dfa5 100644 --- a/arch/x86/entry/entry_64_compat.S +++ b/arch/x86/entry/entry_64_compat.S @@ -117,6 +117,7 @@ sysenter_do_call: xchg %ecx, %esi /* rsi:arg2, rcx:arg4 */ movl %ebx, %edi /* arg1 */ movl %edx, %edx /* arg3 (zero extension) */ + sysenter_dispatch: cmpq $(IA32_NR_syscalls-1), %rax ja 1f @@ -127,6 +128,7 @@ sysenter_dispatch: TRACE_IRQS_OFF testl $_TIF_ALLWORK_MASK, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) jnz sysexit_audit + sysexit_from_sys_call: /* * NB: SYSEXIT is not obviously safe for 64-bit kernels -- an @@ -139,14 +141,14 @@ sysexit_from_sys_call: * with 'sysenter' and it uses the SYSENTER calling convention. */ andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) - movl RIP(%rsp), %ecx /* User %eip */ movl RSI(%rsp), %esi movl RDI(%rsp), %edi + movl RIP(%rsp), %ecx /* User %eip */ + movl EFLAGS(%rsp), %r11d /* User eflags */ xorl %edx, %edx /* Do not leak kernel information */ - xorq %r8, %r8 - xorq %r9, %r9 xorq %r10, %r10 - movl EFLAGS(%rsp), %r11d /* User eflags */ + xorq %r9, %r9 + xorq %r8, %r8 TRACE_IRQS_ON /* @@ -340,6 +342,7 @@ ENTRY(entry_SYSCALL_compat) 1: movl (%r8), %r9d _ASM_EXTABLE(1b, ia32_badarg) ASM_CLAC + orl $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS) testl $_TIF_WORK_SYSCALL_ENTRY, ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS) jnz cstar_tracesys @@ -355,7 +358,6 @@ cstar_do_call: cstar_dispatch: cmpq $(IA32_NR_syscalls-1), %rax ja 1f - call *ia32_sys_call_table(, %rax, 8) movq %rax, RAX(%rsp) 1: -- 1.8.1.4 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/