| From 196bd485ee4f03ce4c690bfcf38138abfcd0a4bc Mon Sep 17 00:00:00 2001 |
| From: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| Date: Fri, 29 Sep 2017 17:15:36 +0300 |
| Subject: x86/asm: Use register variable to get stack pointer value |
| |
| From: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| |
| commit 196bd485ee4f03ce4c690bfcf38138abfcd0a4bc upstream. |
| |
| Currently we use current_stack_pointer() function to get the value |
| of the stack pointer register. Since commit: |
| |
| f5caf621ee35 ("x86/asm: Fix inline asm call constraints for Clang") |
| |
| ... we have a stack register variable declared. It can be used instead of |
| current_stack_pointer() function which allows to optimize away some |
| excessive "mov %rsp, %<dst>" instructions: |
| |
| -mov %rsp,%rdx |
| -sub %rdx,%rax |
| -cmp $0x3fff,%rax |
| -ja ffffffff810722fd <ist_begin_non_atomic+0x2d> |
| |
| +sub %rsp,%rax |
| +cmp $0x3fff,%rax |
| +ja ffffffff810722fa <ist_begin_non_atomic+0x2a> |
| |
| Remove current_stack_pointer(), rename __asm_call_sp to current_stack_pointer |
| and use it instead of the removed function. |
| |
| Signed-off-by: Andrey Ryabinin <aryabinin@virtuozzo.com> |
| Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com> |
| Cc: Andy Lutomirski <luto@kernel.org> |
| Cc: Linus Torvalds <torvalds@linux-foundation.org> |
| Cc: Peter Zijlstra <peterz@infradead.org> |
| Cc: Thomas Gleixner <tglx@linutronix.de> |
| Link: http://lkml.kernel.org/r/20170929141537.29167-1-aryabinin@virtuozzo.com |
| Signed-off-by: Ingo Molnar <mingo@kernel.org> |
| [dwmw2: We want ASM_CALL_CONSTRAINT for retpoline] |
| Signed-off-by: David Woodhouse <dwmw@amazon.co.ku> |
| Signed-off-by: Razvan Ghitulete <rga@amazon.de> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| arch/x86/include/asm/asm.h | 11 +++++++++++ |
| arch/x86/include/asm/thread_info.h | 11 ----------- |
| arch/x86/kernel/irq_32.c | 6 +++--- |
| arch/x86/kernel/traps.c | 2 +- |
| 4 files changed, 15 insertions(+), 15 deletions(-) |
| |
| --- a/arch/x86/include/asm/asm.h |
| +++ b/arch/x86/include/asm/asm.h |
| @@ -105,4 +105,15 @@ |
| /* For C file, we already have NOKPROBE_SYMBOL macro */ |
| #endif |
| |
| +#ifndef __ASSEMBLY__ |
| +/* |
| + * This output constraint should be used for any inline asm which has a "call" |
| + * instruction. Otherwise the asm may be inserted before the frame pointer |
| + * gets set up by the containing function. If you forget to do this, objtool |
| + * may print a "call without frame pointer save/setup" warning. |
| + */ |
| +register unsigned long current_stack_pointer asm(_ASM_SP); |
| +#define ASM_CALL_CONSTRAINT "+r" (current_stack_pointer) |
| +#endif |
| + |
| #endif /* _ASM_X86_ASM_H */ |
| --- a/arch/x86/include/asm/thread_info.h |
| +++ b/arch/x86/include/asm/thread_info.h |
| @@ -166,17 +166,6 @@ static inline struct thread_info *curren |
| return (struct thread_info *)(current_top_of_stack() - THREAD_SIZE); |
| } |
| |
| -static inline unsigned long current_stack_pointer(void) |
| -{ |
| - unsigned long sp; |
| -#ifdef CONFIG_X86_64 |
| - asm("mov %%rsp,%0" : "=g" (sp)); |
| -#else |
| - asm("mov %%esp,%0" : "=g" (sp)); |
| -#endif |
| - return sp; |
| -} |
| - |
| #else /* !__ASSEMBLY__ */ |
| |
| #ifdef CONFIG_X86_64 |
| --- a/arch/x86/kernel/irq_32.c |
| +++ b/arch/x86/kernel/irq_32.c |
| @@ -65,7 +65,7 @@ static void call_on_stack(void *func, vo |
| |
| static inline void *current_stack(void) |
| { |
| - return (void *)(current_stack_pointer() & ~(THREAD_SIZE - 1)); |
| + return (void *)(current_stack_pointer & ~(THREAD_SIZE - 1)); |
| } |
| |
| static inline int execute_on_irq_stack(int overflow, struct irq_desc *desc) |
| @@ -89,7 +89,7 @@ static inline int execute_on_irq_stack(i |
| |
| /* Save the next esp at the bottom of the stack */ |
| prev_esp = (u32 *)irqstk; |
| - *prev_esp = current_stack_pointer(); |
| + *prev_esp = current_stack_pointer; |
| |
| if (unlikely(overflow)) |
| call_on_stack(print_stack_overflow, isp); |
| @@ -142,7 +142,7 @@ void do_softirq_own_stack(void) |
| |
| /* Push the previous esp onto the stack */ |
| prev_esp = (u32 *)irqstk; |
| - *prev_esp = current_stack_pointer(); |
| + *prev_esp = current_stack_pointer; |
| |
| call_on_stack(__do_softirq, isp); |
| } |
| --- a/arch/x86/kernel/traps.c |
| +++ b/arch/x86/kernel/traps.c |
| @@ -166,7 +166,7 @@ void ist_begin_non_atomic(struct pt_regs |
| * from double_fault. |
| */ |
| BUG_ON((unsigned long)(current_top_of_stack() - |
| - current_stack_pointer()) >= THREAD_SIZE); |
| + current_stack_pointer) >= THREAD_SIZE); |
| |
| preempt_enable_no_resched(); |
| } |