x86/asm/entry/32: Do not use R9 in SYSCALL32 entry point
authorDenys Vlasenko <dvlasenk@redhat.com>
Wed, 3 Jun 2015 12:56:09 +0000 (14:56 +0200)
committerIngo Molnar <mingo@kernel.org>
Fri, 5 Jun 2015 11:22:22 +0000 (13:22 +0200)
SYSENTER and SYSCALL 32-bit entry points differ in handling of
arg2 and arg6.

SYSENTER:
 * ecx  arg2
 * ebp  user stack
 * 0(%ebp) arg6

SYSCALL:
 * ebp  arg2
 * esp  user stack
 * 0(%esp) arg6

Sysenter code loads 0(%ebp) to %ebp right away.
(This destroys %ebp. It means we do not preserve it on return.
It's not causing problems since userspace VDSO code does not
depend on it, and SYSENTER insn can't be sanely used outside of
VDSO).

Syscall code loads 0(%ebp) to %r9. This allows to eliminate one
MOV insn (r9 is a register where arg6 should be for 64-bit ABI),
but on audit/ptrace code paths this requires juggling of r9 and
ebp: (1) ptrace expects arg6 to be in pt_regs->bp;
(2) r9 is callee-clobbered register and needs to be
saved/restored     around calls to C functions.

This patch changes syscall code to load 0(%ebp) to %ebp, making
it more similar to sysenter code. It's a bit smaller:

   text    data     bss     dec     hex filename
   1407       0       0    1407     57f ia32entry.o.before
   1391       0       0    1391     56f ia32entry.o

To preserve ABI compat, we restore ebp on exit.

Run-tested.

Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Alexei Starovoitov <ast@plumgrid.com>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Frederic Weisbecker <fweisbec@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Kees Cook <keescook@chromium.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Steven Rostedt <rostedt@goodmis.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Will Drewry <wad@chromium.org>
Link: http://lkml.kernel.org/r/1433336169-18964-1-git-send-email-dvlasenk@redhat.com
Signed-off-by: Ingo Molnar <mingo@kernel.org>
arch/x86/entry/ia32entry.S

index 56f819e99258cf6b5544ea97b8070b951e5fa314..63219154087e5be23ac68cb63b3297eebf2dfcc6 100644 (file)
@@ -323,7 +323,7 @@ ENTRY(ia32_cstar_target)
         * 32bit zero extended
         */
        ASM_STAC
-1:     movl    (%r8),%r9d
+1:     movl    (%r8),%ebp
        _ASM_EXTABLE(1b,ia32_badarg)
        ASM_CLAC
        orl     $TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
@@ -333,7 +333,7 @@ ENTRY(ia32_cstar_target)
 cstar_do_call:
        /* 32bit syscall -> 64bit C ABI argument conversion */
        movl    %edi,%r8d       /* arg5 */
-       /* r9 already loaded */ /* arg6 */
+       movl    %ebp,%r9d       /* arg6 */
        xchg    %ecx,%esi       /* rsi:arg2, rcx:arg4 */
        movl    %ebx,%edi       /* arg1 */
        movl    %edx,%edx       /* arg3 (zero extension) */
@@ -349,6 +349,7 @@ cstar_dispatch:
        jnz sysretl_audit
 sysretl_from_sys_call:
        andl $~TS_COMPAT, ASM_THREAD_INFO(TI_status, %rsp, SIZEOF_PTREGS)
+       movl    RCX(%rsp), %ebp
        RESTORE_RSI_RDI_RDX
        movl RIP(%rsp),%ecx
        movl EFLAGS(%rsp),%r11d
@@ -375,9 +376,8 @@ sysretl_from_sys_call:
 
 #ifdef CONFIG_AUDITSYSCALL
 cstar_auditsys:
-       movl %r9d,R9(%rsp)      /* register to be clobbered by call */
        auditsys_entry_common
-       movl R9(%rsp),%r9d      /* reload 6th syscall arg */
+       movl    %ebp, %r9d      /* reload 6th syscall arg */
        jmp cstar_dispatch
 
 sysretl_audit:
@@ -389,16 +389,14 @@ cstar_tracesys:
        testl $(_TIF_WORK_SYSCALL_ENTRY & ~_TIF_SYSCALL_AUDIT), ASM_THREAD_INFO(TI_flags, %rsp, SIZEOF_PTREGS)
        jz cstar_auditsys
 #endif
-       xchgl %r9d,%ebp
        SAVE_EXTRA_REGS
        xorl    %eax, %eax      /* do not leak kernel information */
        movq    %rax, R11(%rsp)
        movq    %rax, R10(%rsp)
-       movq    %r9,  R9(%rsp)
+       movq    %rax, R9(%rsp)
        movq    %rax, R8(%rsp)
-       movq %rsp,%rdi        /* &pt_regs -> arg1 */
-       call syscall_trace_enter
-       movl    R9(%rsp),%r9d
+       movq    %rsp, %rdi        /* &pt_regs -> arg1 */
+       call    syscall_trace_enter
 
        /* Reload arg registers from stack. (see sysenter_tracesys) */
        movl    RCX(%rsp), %ecx
@@ -408,8 +406,7 @@ cstar_tracesys:
        movl    %eax, %eax      /* zero extension */
 
        RESTORE_EXTRA_REGS
-       xchgl %ebp,%r9d
-       jmp cstar_do_call
+       jmp     cstar_do_call
 END(ia32_cstar_target)
                                
 ia32_badarg: