From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1755877AbcHXNKY (ORCPT ); Wed, 24 Aug 2016 09:10:24 -0400 Received: from terminus.zytor.com ([198.137.202.10]:49194 "EHLO terminus.zytor.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1754283AbcHXNKW (ORCPT ); Wed, 24 Aug 2016 09:10:22 -0400 Date: Wed, 24 Aug 2016 06:09:26 -0700 From: tip-bot for Brian Gerst Message-ID: Cc: peterz@infradead.org, dvlasenk@redhat.com, hpa@zytor.com, brgerst@gmail.com, tglx@linutronix.de, luto@kernel.org, jpoimboe@redhat.com, bp@alien8.de, mingo@kernel.org, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org Reply-To: peterz@infradead.org, dvlasenk@redhat.com, hpa@zytor.com, brgerst@gmail.com, tglx@linutronix.de, luto@kernel.org, jpoimboe@redhat.com, bp@alien8.de, mingo@kernel.org, torvalds@linux-foundation.org, linux-kernel@vger.kernel.org In-Reply-To: <1471106302-10159-7-git-send-email-brgerst@gmail.com> References: <1471106302-10159-7-git-send-email-brgerst@gmail.com> To: linux-tip-commits@vger.kernel.org Subject: [tip:x86/asm] sched/x86: Fix thread_saved_pc() Git-Commit-ID: ffcb043ba524d3fbd979a9dac2c9ce8ad352000d X-Mailer: tip-git-log-daemon Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Content-Type: text/plain; charset=UTF-8 Content-Disposition: inline Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Commit-ID: ffcb043ba524d3fbd979a9dac2c9ce8ad352000d Gitweb: http://git.kernel.org/tip/ffcb043ba524d3fbd979a9dac2c9ce8ad352000d Author: Brian Gerst AuthorDate: Sat, 13 Aug 2016 12:38:21 -0400 Committer: Ingo Molnar CommitDate: Wed, 24 Aug 2016 12:31:51 +0200 sched/x86: Fix thread_saved_pc() thread_saved_pc() was using a completely bogus method to get the return address. Since switch_to() was previously inlined, there was no sane way to know where on the stack the return address was stored. Now with the frame of a sleeping thread well defined, this can be implemented correctly. Signed-off-by: Brian Gerst Reviewed-by: Josh Poimboeuf Cc: Andy Lutomirski Cc: Borislav Petkov Cc: Denys Vlasenko Cc: H. Peter Anvin Cc: Linus Torvalds Cc: Peter Zijlstra Cc: Thomas Gleixner Link: http://lkml.kernel.org/r/1471106302-10159-7-git-send-email-brgerst@gmail.com Signed-off-by: Ingo Molnar --- arch/x86/include/asm/processor.h | 10 ++-------- arch/x86/kernel/process.c | 11 +++++++++++ arch/x86/kernel/process_32.c | 8 -------- 3 files changed, 13 insertions(+), 16 deletions(-) diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h index 6fee863..b22fb5a 100644 --- a/arch/x86/include/asm/processor.h +++ b/arch/x86/include/asm/processor.h @@ -721,8 +721,6 @@ static inline void spin_lock_prefetch(const void *x) .addr_limit = KERNEL_DS, \ } -extern unsigned long thread_saved_pc(struct task_struct *tsk); - /* * TOP_OF_KERNEL_STACK_PADDING reserves 8 bytes on top of the ring0 stack. * This is necessary to guarantee that the entire "struct pt_regs" @@ -773,17 +771,13 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk); .addr_limit = KERNEL_DS, \ } -/* - * Return saved PC of a blocked thread. - * What is this good for? it will be always the scheduler or ret_from_fork. - */ -#define thread_saved_pc(t) READ_ONCE_NOCHECK(*(unsigned long *)((t)->thread.sp - 8)) - #define task_pt_regs(tsk) ((struct pt_regs *)(tsk)->thread.sp0 - 1) extern unsigned long KSTK_ESP(struct task_struct *task); #endif /* CONFIG_X86_64 */ +extern unsigned long thread_saved_pc(struct task_struct *tsk); + extern void start_thread(struct pt_regs *regs, unsigned long new_ip, unsigned long new_sp); diff --git a/arch/x86/kernel/process.c b/arch/x86/kernel/process.c index 0115a4a..c1fa790 100644 --- a/arch/x86/kernel/process.c +++ b/arch/x86/kernel/process.c @@ -514,6 +514,17 @@ unsigned long arch_randomize_brk(struct mm_struct *mm) } /* + * Return saved PC of a blocked thread. + * What is this good for? it will be always the scheduler or ret_from_fork. + */ +unsigned long thread_saved_pc(struct task_struct *tsk) +{ + struct inactive_task_frame *frame = + (struct inactive_task_frame *) READ_ONCE(tsk->thread.sp); + return READ_ONCE_NOCHECK(frame->ret_addr); +} + +/* * Called from fs/proc with a reference on @p to find the function * which called into schedule(). This needs to be done carefully * because the task might wake up and we might look at a stack diff --git a/arch/x86/kernel/process_32.c b/arch/x86/kernel/process_32.c index 18714a1..404efdf 100644 --- a/arch/x86/kernel/process_32.c +++ b/arch/x86/kernel/process_32.c @@ -55,14 +55,6 @@ #include #include -/* - * Return saved PC of a blocked thread. - */ -unsigned long thread_saved_pc(struct task_struct *tsk) -{ - return ((unsigned long *)tsk->thread.sp)[3]; -} - void __show_regs(struct pt_regs *regs, int all) { unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;