Messages in this thread | | | Date | Fri, 24 Jun 2016 13:12:45 -0500 | From | Josh Poimboeuf <> | Subject | Re: [PATCH v2 6/6] x86: Fix thread_saved_pc() |
| |
On Wed, Jun 22, 2016 at 12:27:43AM -0400, Brian Gerst wrote: > On Mon, Jun 20, 2016 at 12:01 PM, Josh Poimboeuf <jpoimboe@redhat.com> wrote: > > On Sat, Jun 18, 2016 at 04:56:18PM -0400, Brian Gerst wrote: > >> 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); > >> +} > >> + > >> +/* > > > > I would agree with the above (removed) comment: > > > > "What is this good for? it will be always the scheduler or ret_from_fork." > > > > And I'd guess the same is true for all the arches which have to > > implement it. Maybe this function (and its single call site in > > sched_show_task()) should just be removed altogether? > > I didn't really want to stray down that path with this series. This > just makes it functional again. the usefulness is still open for > debate.
Fair enough.
Reviewed-by: Josh Poimboeuf <jpoimboe@redhat.com>
-- Josh
| |