aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDenys Vlasenko <dvlasenk@redhat.com>2015-03-09 14:39:23 -0400
committerIngo Molnar <mingo@kernel.org>2015-03-10 08:56:10 -0400
commit263042e4630a85e856b4a8cd72f28dab33ef4741 (patch)
tree268f16dc93d2f111ffd484300042df3bb089e050
parent616ab249f1e42f6135642183529f910fcedc2642 (diff)
x86/asm/entry/64: Save user RSP in pt_regs->sp on SYSCALL64 fastpath
Prepare for the removal of 'usersp', by simplifying PER_CPU(old_rsp) usage: - use it only as temp storage - store the userspace stack pointer immediately in pt_regs->sp on syscall entry, instead of using it later, on syscall exit. - change C code to use pt_regs->sp only, instead of PER_CPU(old_rsp) and task->thread.usersp. FIXUP/RESTORE_TOP_OF_STACK are simplified as well. Signed-off-by: Denys Vlasenko <dvlasenk@redhat.com> 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/1425926364-9526-4-git-send-email-dvlasenk@redhat.com Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/include/asm/compat.h2
-rw-r--r--arch/x86/include/asm/ptrace.h8
-rw-r--r--arch/x86/kernel/entry_64.S18
-rw-r--r--arch/x86/kernel/perf_regs.c2
-rw-r--r--arch/x86/kernel/process_64.c3
5 files changed, 12 insertions, 21 deletions
diff --git a/arch/x86/include/asm/compat.h b/arch/x86/include/asm/compat.h
index 59c6c401f79f..acdee09228b3 100644
--- a/arch/x86/include/asm/compat.h
+++ b/arch/x86/include/asm/compat.h
@@ -301,7 +301,7 @@ static inline void __user *arch_compat_alloc_user_space(long len)
301 sp = task_pt_regs(current)->sp; 301 sp = task_pt_regs(current)->sp;
302 } else { 302 } else {
303 /* -128 for the x32 ABI redzone */ 303 /* -128 for the x32 ABI redzone */
304 sp = this_cpu_read(old_rsp) - 128; 304 sp = task_pt_regs(current)->sp - 128;
305 } 305 }
306 306
307 return (void __user *)round_down(sp - len, 16); 307 return (void __user *)round_down(sp - len, 16);
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
index 4077d963a1a0..74bb2e0f3030 100644
--- a/arch/x86/include/asm/ptrace.h
+++ b/arch/x86/include/asm/ptrace.h
@@ -145,12 +145,8 @@ static inline bool user_64bit_mode(struct pt_regs *regs)
145#endif 145#endif
146} 146}
147 147
148#define current_user_stack_pointer() this_cpu_read(old_rsp) 148#define current_user_stack_pointer() current_pt_regs()->sp
149/* ia32 vs. x32 difference */ 149#define compat_user_stack_pointer() current_pt_regs()->sp
150#define compat_user_stack_pointer() \
151 (test_thread_flag(TIF_IA32) \
152 ? current_pt_regs()->sp \
153 : this_cpu_read(old_rsp))
154#endif 150#endif
155 151
156#ifdef CONFIG_X86_32 152#ifdef CONFIG_X86_32
diff --git a/arch/x86/kernel/entry_64.S b/arch/x86/kernel/entry_64.S
index 703ced057199..d86788c3257b 100644
--- a/arch/x86/kernel/entry_64.S
+++ b/arch/x86/kernel/entry_64.S
@@ -128,8 +128,6 @@ ENDPROC(native_usergs_sysret64)
128 * manipulation. 128 * manipulation.
129 */ 129 */
130 .macro FIXUP_TOP_OF_STACK tmp offset=0 130 .macro FIXUP_TOP_OF_STACK tmp offset=0
131 movq PER_CPU_VAR(old_rsp),\tmp
132 movq \tmp,RSP+\offset(%rsp)
133 movq $__USER_DS,SS+\offset(%rsp) 131 movq $__USER_DS,SS+\offset(%rsp)
134 movq $__USER_CS,CS+\offset(%rsp) 132 movq $__USER_CS,CS+\offset(%rsp)
135 movq RIP+\offset(%rsp),\tmp /* get rip */ 133 movq RIP+\offset(%rsp),\tmp /* get rip */
@@ -139,8 +137,7 @@ ENDPROC(native_usergs_sysret64)
139 .endm 137 .endm
140 138
141 .macro RESTORE_TOP_OF_STACK tmp offset=0 139 .macro RESTORE_TOP_OF_STACK tmp offset=0
142 movq RSP+\offset(%rsp),\tmp 140 /* nothing to do */
143 movq \tmp,PER_CPU_VAR(old_rsp)
144 .endm 141 .endm
145 142
146/* 143/*
@@ -222,9 +219,6 @@ ENDPROC(native_usergs_sysret64)
222 * Interrupts are off on entry. 219 * Interrupts are off on entry.
223 * Only called from user space. 220 * Only called from user space.
224 * 221 *
225 * XXX if we had a free scratch register we could save the RSP into the stack frame
226 * and report it properly in ps. Unfortunately we haven't.
227 *
228 * When user can change the frames always force IRET. That is because 222 * When user can change the frames always force IRET. That is because
229 * it deals with uncanonical addresses better. SYSRET has trouble 223 * it deals with uncanonical addresses better. SYSRET has trouble
230 * with them due to bugs in both AMD and Intel CPUs. 224 * with them due to bugs in both AMD and Intel CPUs.
@@ -253,11 +247,13 @@ GLOBAL(system_call_after_swapgs)
253 */ 247 */
254 ENABLE_INTERRUPTS(CLBR_NONE) 248 ENABLE_INTERRUPTS(CLBR_NONE)
255 ALLOC_PT_GPREGS_ON_STACK 8 /* +8: space for orig_ax */ 249 ALLOC_PT_GPREGS_ON_STACK 8 /* +8: space for orig_ax */
250 movq %rcx,RIP(%rsp)
251 movq PER_CPU_VAR(old_rsp),%rcx
252 movq %r11,EFLAGS(%rsp)
253 movq %rcx,RSP(%rsp)
254 movq_cfi rax,ORIG_RAX
256 SAVE_C_REGS_EXCEPT_RAX_RCX_R11 255 SAVE_C_REGS_EXCEPT_RAX_RCX_R11
257 movq $-ENOSYS,RAX(%rsp) 256 movq $-ENOSYS,RAX(%rsp)
258 movq_cfi rax,ORIG_RAX
259 movq %r11,EFLAGS(%rsp)
260 movq %rcx,RIP(%rsp)
261 CFI_REL_OFFSET rip,RIP 257 CFI_REL_OFFSET rip,RIP
262 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP) 258 testl $_TIF_WORK_SYSCALL_ENTRY,TI_flags+THREAD_INFO(%rsp,RIP)
263 jnz tracesys 259 jnz tracesys
@@ -293,7 +289,7 @@ ret_from_sys_call:
293 CFI_REGISTER rip,rcx 289 CFI_REGISTER rip,rcx
294 movq EFLAGS(%rsp),%r11 290 movq EFLAGS(%rsp),%r11
295 /*CFI_REGISTER rflags,r11*/ 291 /*CFI_REGISTER rflags,r11*/
296 movq PER_CPU_VAR(old_rsp), %rsp 292 movq RSP(%rsp),%rsp
297 /* 293 /*
298 * 64bit SYSRET restores rip from rcx, 294 * 64bit SYSRET restores rip from rcx,
299 * rflags from r11 (but RF and VM bits are forced to 0), 295 * rflags from r11 (but RF and VM bits are forced to 0),
diff --git a/arch/x86/kernel/perf_regs.c b/arch/x86/kernel/perf_regs.c
index 781861cc5ee8..02a8720414c0 100644
--- a/arch/x86/kernel/perf_regs.c
+++ b/arch/x86/kernel/perf_regs.c
@@ -177,7 +177,7 @@ void perf_get_regs_user(struct perf_regs *regs_user,
177 * than just blindly copying user_regs. 177 * than just blindly copying user_regs.
178 */ 178 */
179 regs_user->abi = PERF_SAMPLE_REGS_ABI_64; 179 regs_user->abi = PERF_SAMPLE_REGS_ABI_64;
180 regs_user_copy->sp = this_cpu_read(old_rsp); 180 regs_user_copy->sp = user_regs->sp;
181 regs_user_copy->cs = __USER_CS; 181 regs_user_copy->cs = __USER_CS;
182 regs_user_copy->ss = __USER_DS; 182 regs_user_copy->ss = __USER_DS;
183 regs_user_copy->cx = -1; /* usually contains garbage */ 183 regs_user_copy->cx = -1; /* usually contains garbage */
diff --git a/arch/x86/kernel/process_64.c b/arch/x86/kernel/process_64.c
index 1e393d27d701..e8c124a1f885 100644
--- a/arch/x86/kernel/process_64.c
+++ b/arch/x86/kernel/process_64.c
@@ -602,6 +602,5 @@ long sys_arch_prctl(int code, unsigned long addr)
602 602
603unsigned long KSTK_ESP(struct task_struct *task) 603unsigned long KSTK_ESP(struct task_struct *task)
604{ 604{
605 return (test_tsk_thread_flag(task, TIF_IA32)) ? 605 return task_pt_regs(task)->sp;
606 (task_pt_regs(task)->sp) : ((task)->thread.usersp);
607} 606}