On Mon, Jun 20, 2016 at 12:01 PM, Josh Poimboeuf <jpoim...@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 <brge...@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. -- Brian Gerst