[PATCH 1/3] x86/asm/entry/32: Massage SYSENTER32 fast path to be nearly identical to SYSCALL32

From: Denys Vlasenko
Date: Fri Jul 24 2015 - 09:48:01 EST


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 <dvlasenk@xxxxxxxxxx>
CC: Ingo Molnar <mingo@xxxxxxxxxx>
CC: Linus Torvalds <torvalds@xxxxxxxxxxxxxxxxxxxx>
CC: Krzysztof A. Sobiecki <sobkas@xxxxxxxxx>
CC: Steven Rostedt <rostedt@xxxxxxxxxxx>
CC: Borislav Petkov <bp@xxxxxxxxx>
CC: "H. Peter Anvin" <hpa@xxxxxxxxx>
CC: Andy Lutomirski <luto@xxxxxxxxxxxxxx>
CC: Oleg Nesterov <oleg@xxxxxxxxxx>
CC: Frederic Weisbecker <fweisbec@xxxxxxxxx>
CC: Alexei Starovoitov <ast@xxxxxxxxxxxx>
CC: Will Drewry <wad@xxxxxxxxxxxx>
CC: Kees Cook <keescook@xxxxxxxxxxxx>
CC: x86@xxxxxxxxxx
CC: linux-kernel@xxxxxxxxxxxxxxx
---
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@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/