aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2015-03-19 13:17:46 -0400
committerIngo Molnar <mingo@kernel.org>2015-03-24 14:42:38 -0400
commitef593260f0cae2699874f098fb5b19fb46502cb3 (patch)
tree68b114f2e6ad9413dc030a0e0960e6fd934f9942
parentb3fe8ba320ace38cee6859b4c015d81627254ddb (diff)
x86/asm/entry: Get rid of KERNEL_STACK_OFFSET
PER_CPU_VAR(kernel_stack) was set up in a way where it points five stack slots below the top of stack. Presumably, it was done to avoid one "sub $5*8,%rsp" in syscall/sysenter code paths, where iret frame needs to be created by hand. Ironically, none of them benefits from this optimization, since all of them need to allocate additional data on stack (struct pt_regs), so they still have to perform subtraction. This patch eliminates KERNEL_STACK_OFFSET. PER_CPU_VAR(kernel_stack) now points directly to top of stack. pt_regs allocations are adjusted to allocate iret frame as well. Hopefully we can merge it later with 32-bit specific PER_CPU_VAR(cpu_current_top_of_stack) variable... Net result in generated code is that constants in several insns are changed. This change is necessary for changing struct pt_regs creation in SYSCALL64 code path from MOV to PUSH instructions. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> Acked-by: Borislav Petkov <bp@suse.de> Acked-by: Andy Lutomirski <luto@kernel.org> Cc: Alexei Starovoitov <ast@plumgrid.com> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> 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: Steven Rostedt <rostedt@goodmis.org> Cc: Will Drewry <wad@chromium.org> Link: http://lkml.kernel.org/r/1426785469-15125-2-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/ia32/ia32entry.S4
-rw-r--r--arch/x86/include/asm/thread_info.h5
-rw-r--r--arch/x86/kernel/cpu/common.c2
-rw-r--r--arch/x86/kernel/entry_64.S5
-rw-r--r--arch/x86/kernel/process_32.c2
-rw-r--r--arch/x86/kernel/process_64.c3
-rw-r--r--arch/x86/kernel/smpboot.c3
-rw-r--r--arch/x86/xen/smp.c3
8 files changed, 11 insertions, 16 deletions
diff --git a/arch/x86/ia32/ia32entry.S b/arch/x86/ia32/ia32entry.S
index 50190e15c1b6..acbff3fb96a1 100644
--- a/arch/x86/ia32/ia32entry.S
+++ b/arch/x86/ia32/ia32entry.S
@@ -311,7 +311,7 @@ ENDPROC(ia32_sysenter_target)
311ENTRY(ia32_cstar_target) 311ENTRY(ia32_cstar_target)
312 CFI_STARTPROC32 simple 312 CFI_STARTPROC32 simple
313 CFI_SIGNAL_FRAME 313 CFI_SIGNAL_FRAME
314 CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET 314 CFI_DEF_CFA rsp,0
315 CFI_REGISTER rip,rcx 315 CFI_REGISTER rip,rcx
316 /*CFI_REGISTER rflags,r11*/ 316 /*CFI_REGISTER rflags,r11*/
317 SWAPGS_UNSAFE_STACK 317 SWAPGS_UNSAFE_STACK
@@ -323,7 +323,7 @@ ENTRY(ia32_cstar_target)
323 * disabled irqs and here we enable it straight after entry: 323 * disabled irqs and here we enable it straight after entry:
324 */ 324 */
325 ENABLE_INTERRUPTS(CLBR_NONE) 325 ENABLE_INTERRUPTS(CLBR_NONE)
326 ALLOC_PT_GPREGS_ON_STACK 8 /* +8: space for orig_ax */ 326 ALLOC_PT_GPREGS_ON_STACK 6*8 /* 6*8: space for orig_ax and iret frame */
327 SAVE_C_REGS_EXCEPT_RCX_R891011 327 SAVE_C_REGS_EXCEPT_RCX_R891011
328 movl %eax,%eax /* zero extension */ 328 movl %eax,%eax /* zero extension */
329 movq %rax,ORIG_RAX(%rsp) 329 movq %rax,ORIG_RAX(%rsp)
diff --git a/arch/x86/include/asm/thread_info.h b/arch/x86/include/asm/thread_info.h
index ae9c2f13b476..ad0ee3423da5 100644
--- a/arch/x86/include/asm/thread_info.h
+++ b/arch/x86/include/asm/thread_info.h
@@ -172,7 +172,6 @@ struct thread_info {
172#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW) 172#define _TIF_WORK_CTXSW_NEXT (_TIF_WORK_CTXSW)
173 173
174#define STACK_WARN (THREAD_SIZE/8) 174#define STACK_WARN (THREAD_SIZE/8)
175#define KERNEL_STACK_OFFSET (5*(BITS_PER_LONG/8))
176 175
177/* 176/*
178 * macros/functions for gaining access to the thread information structure 177 * macros/functions for gaining access to the thread information structure
@@ -201,10 +200,10 @@ static inline unsigned long current_stack_pointer(void)
201 200
202#else /* !__ASSEMBLY__ */ 201#else /* !__ASSEMBLY__ */
203 202
204/* how to get the thread information struct from ASM */ 203/* Load thread_info address into "reg" */
205#define GET_THREAD_INFO(reg) \ 204#define GET_THREAD_INFO(reg) \
206 _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \ 205 _ASM_MOV PER_CPU_VAR(kernel_stack),reg ; \
207 _ASM_SUB $(THREAD_SIZE-KERNEL_STACK_OFFSET),reg ; 206 _ASM_SUB $(THREAD_SIZE),reg ;
208 207
209/* 208/*
210 * ASM operand which evaluates to thread_info address 209 * ASM operand which evaluates to thread_info address
diff --git a/arch/x86/kernel/cpu/common.c b/arch/x86/kernel/cpu/common.c
index 66d62aef7214..002216ab9145 100644
--- a/arch/x86/kernel/cpu/common.c
+++ b/arch/x86/kernel/cpu/common.c
@@ -1116,7 +1116,7 @@ static __init int setup_disablecpuid(char *arg)
1116__setup("clearcpuid=", setup_disablecpuid); 1116__setup("clearcpuid=", setup_disablecpuid);
1117 1117
1118DEFINE_PER_CPU(unsigned long, kernel_stack) = 1118DEFINE_PER_CPU(unsigned long, kernel_stack) =
1119 (unsigned long)&init_thread_union - KERNEL_STACK_OFFSET + THREAD_SIZE; 1119 (unsigned long)&init_thread_union + THREAD_SIZE;
1120EXPORT_PER_CPU_SYMBOL(kernel_stack); 1120EXPORT_PER_CPU_SYMBOL(kernel_stack);
1121 1121
1122#ifdef CONFIG_X86_64 1122#ifdef CONFIG_X86_64
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 8076df982a18..eae69bba3a2c 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -225,7 +225,7 @@ ENDPROC(native_usergs_sysret64)
225ENTRY(system_call) 225ENTRY(system_call)
226 CFI_STARTPROC simple 226 CFI_STARTPROC simple
227 CFI_SIGNAL_FRAME 227 CFI_SIGNAL_FRAME
228 CFI_DEF_CFA rsp,KERNEL_STACK_OFFSET 228 CFI_DEF_CFA rsp,0
229 CFI_REGISTER rip,rcx 229 CFI_REGISTER rip,rcx
230 /*CFI_REGISTER rflags,r11*/ 230 /*CFI_REGISTER rflags,r11*/
231 SWAPGS_UNSAFE_STACK 231 SWAPGS_UNSAFE_STACK
@@ -242,9 +242,8 @@ GLOBAL(system_call_after_swapgs)
242 * so we can enable interrupts only after we're done with using rsp_scratch: 242 * so we can enable interrupts only after we're done with using rsp_scratch:
243 */ 243 */
244 movq %rsp,PER_CPU_VAR(rsp_scratch) 244 movq %rsp,PER_CPU_VAR(rsp_scratch)
245 /* kernel_stack is set so that 5 slots (iret frame) are preallocated */
246 movq PER_CPU_VAR(kernel_stack),%rsp 245 movq PER_CPU_VAR(kernel_stack),%rsp
247 ALLOC_PT_GPREGS_ON_STACK 8 /* +8: space for orig_ax */ 246 ALLOC_PT_GPREGS_ON_STACK 6*8 /* 6*8: space for orig_ax and iret frame */
248 movq %rcx,RIP(%rsp) 247 movq %rcx,RIP(%rsp)
249 movq PER_CPU_VAR(rsp_scratch),%rcx 248 movq PER_CPU_VAR(rsp_scratch),%rcx
250 movq %r11,EFLAGS(%rsp) 249 movq %r11,EFLAGS(%rsp)
diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c
index c5e987022ca0..8ed2106b06da 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -308,7 +308,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
308 load_sp0(tss, next); 308 load_sp0(tss, next);
309 this_cpu_write(kernel_stack, 309 this_cpu_write(kernel_stack,
310 (unsigned long)task_stack_page(next_p) + 310 (unsigned long)task_stack_page(next_p) +
311 THREAD_SIZE - KERNEL_STACK_OFFSET); 311 THREAD_SIZE);
312 this_cpu_write(cpu_current_top_of_stack, 312 this_cpu_write(cpu_current_top_of_stack,
313 (unsigned long)task_stack_page(next_p) + 313 (unsigned long)task_stack_page(next_p) +
314 THREAD_SIZE); 314 THREAD_SIZE);
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index da8b74598d90..4baaa972f52a 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -410,8 +410,7 @@ __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
410 load_sp0(tss, next); 410 load_sp0(tss, next);
411 411
412 this_cpu_write(kernel_stack, 412 this_cpu_write(kernel_stack,
413 (unsigned long)task_stack_page(next_p) + 413 (unsigned long)task_stack_page(next_p) + THREAD_SIZE);
414 THREAD_SIZE - KERNEL_STACK_OFFSET);
415 414
416 /* 415 /*
417 * Now maybe reload the debug registers and handle I/O bitmaps 416 * Now maybe reload the debug registers and handle I/O bitmaps
diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index 759388c538cf..7b20ffd2fffc 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -813,8 +813,7 @@ static int do_boot_cpu(int apicid, int cpu, struct task_struct *idle)
813 initial_gs = per_cpu_offset(cpu); 813 initial_gs = per_cpu_offset(cpu);
814#endif 814#endif
815 per_cpu(kernel_stack, cpu) = 815 per_cpu(kernel_stack, cpu) =
816 (unsigned long)task_stack_page(idle) - 816 (unsigned long)task_stack_page(idle) + THREAD_SIZE;
817 KERNEL_STACK_OFFSET + THREAD_SIZE;
818 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu); 817 early_gdt_descr.address = (unsigned long)get_cpu_gdt_table(cpu);
819 initial_code = (unsigned long)start_secondary; 818 initial_code = (unsigned long)start_secondary;
820 stack_start = idle->thread.sp; 819 stack_start = idle->thread.sp;
diff --git a/arch/x86/xen/smp.c b/arch/x86/xen/smp.c
index 08e8489c47f1..765b7684f858 100644
--- a/arch/x86/xen/smp.c
+++ b/arch/x86/xen/smp.c
@@ -452,8 +452,7 @@ static int xen_cpu_up(unsigned int cpu, struct task_struct *idle)
452 clear_tsk_thread_flag(idle, TIF_FORK); 452 clear_tsk_thread_flag(idle, TIF_FORK);
453#endif 453#endif
454 per_cpu(kernel_stack, cpu) = 454 per_cpu(kernel_stack, cpu) =
455 (unsigned long)task_stack_page(idle) - 455 (unsigned long)task_stack_page(idle) + THREAD_SIZE;
456 KERNEL_STACK_OFFSET + THREAD_SIZE;
457 456
458 xen_setup_runstate_info(cpu); 457 xen_setup_runstate_info(cpu);
459 xen_setup_timer(cpu); 458 xen_setup_timer(cpu);