Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > linux.kernel > #1425847

[PATCH v2 6/6] x86: Fix thread_saved_pc()

From Brian Gerst <brgerst@gmail.com>
Newsgroups linux.kernel
Subject [PATCH v2 6/6] x86: Fix thread_saved_pc()
Date 2016-06-18 23:00 +0200
Message-ID <rLvvs-F3-9@gated-at.bofh.it> (permalink)
References <rLvvr-F3-3@gated-at.bofh.it>
Organization linux.* mail to news gateway

Show all headers | View raw


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 <brgerst@gmail.com>
---
 arch/x86/include/asm/processor.h | 10 ++--------
 arch/x86/kernel/process.c        | 10 ++++++++++
 arch/x86/kernel/process_32.c     |  8 --------
 3 files changed, 12 insertions(+), 16 deletions(-)

diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
index 1e7d634..413f4f1 100644
--- a/arch/x86/include/asm/processor.h
+++ b/arch/x86/include/asm/processor.h
@@ -716,8 +716,6 @@ static inline void spin_lock_prefetch(const void *x)
 	.io_bitmap_ptr		= NULL,					  \
 }
 
-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"
@@ -767,17 +765,13 @@ extern unsigned long thread_saved_pc(struct task_struct *tsk);
 	.sp0 = TOP_OF_INIT_STACK \
 }
 
-/*
- * 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 00ebab0..db458c4 100644
--- a/arch/x86/kernel/process.c
+++ b/arch/x86/kernel/process.c
@@ -513,6 +513,16 @@ unsigned long arch_randomize_brk(struct mm_struct *mm)
 }
 
 /*
+ * Return saved PC of a blocked thread.
+ */
+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 acee6ca..bcf0a38 100644
--- a/arch/x86/kernel/process_32.c
+++ b/arch/x86/kernel/process_32.c
@@ -58,14 +58,6 @@
 asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
 asmlinkage void ret_from_kernel_thread(void) __asm__("ret_from_kernel_thread");
 
-/*
- * 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;
-- 
2.5.5

Back to linux.kernel | Previous | NextPrevious in thread | Next in thread | Find similar | Unroll thread


Thread

[PATCH v2 0/6] x86: Rewrite switch_to() Brian Gerst <brgerst@gmail.com> - 2016-06-18 23:00 +0200
  [PATCH v2 6/6] x86: Fix thread_saved_pc() Brian Gerst <brgerst@gmail.com> - 2016-06-18 23:00 +0200
    Re: [PATCH v2 6/6] x86: Fix thread_saved_pc() Josh Poimboeuf <jpoimboe@redhat.com> - 2016-06-20 18:10 +0200
      Re: [PATCH v2 6/6] x86: Fix thread_saved_pc() Brian Gerst <brgerst@gmail.com> - 2016-06-22 06:30 +0200
  [PATCH v2 2/6] x86-64, kgdb: clear GDB_PS on 64-bit Brian Gerst <brgerst@gmail.com> - 2016-06-18 23:00 +0200
  [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Brian Gerst <brgerst@gmail.com> - 2016-06-18 23:00 +0200
    Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Andy Lutomirski <luto@amacapital.net> - 2016-06-19 23:30 +0200
      Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Brian Gerst <brgerst@gmail.com> - 2016-06-20 00:10 +0200
    Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Borislav Petkov <bp@suse.de> - 2016-06-20 16:00 +0200
      Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Brian Gerst <brgerst@gmail.com> - 2016-06-20 17:20 +0200
        Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Borislav Petkov <bp@alien8.de> - 2016-06-21 13:50 +0200
          Re: [PATCH v2 5/6] x86: Pass kernel thread parameters in fork_frame Brian Gerst <brgerst@gmail.com> - 2016-06-22 10:30 +0200
  Re: [PATCH v2 0/6] x86: Rewrite switch_to() Brian Gerst <brgerst@gmail.com> - 2016-06-20 00:10 +0200

csiph-web