Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1756275AbbGTIUP (ORCPT ); Mon, 20 Jul 2015 04:20:15 -0400 Received: from mail-wi0-f177.google.com ([209.85.212.177]:35942 "EHLO mail-wi0-f177.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1756153AbbGTIUJ (ORCPT ); Mon, 20 Jul 2015 04:20:09 -0400 Date: Mon, 20 Jul 2015 10:20:04 +0200 From: Ingo Molnar To: Heiko Carstens Cc: Linus Torvalds , linux-kernel@vger.kernel.org, Thomas Gleixner , "H. Peter Anvin" , Andy Lutomirski , Dave Hansen , Andrew Morton , Oleg Nesterov , Martin Schwidefsky , Peter Zijlstra Subject: [PATCH] s390, sched: Fix thread_struct move fallout to __switch_to() Message-ID: <20150720082004.GB12468@gmail.com> References: <20150718031810.GA19818@gmail.com> <20150720072037.GA3607@osiris> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: <20150720072037.GA3607@osiris> User-Agent: Mutt/1.5.23 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Content-Length: 6236 Lines: 149 * Heiko Carstens wrote: > Unfortunately not true. It breaks the build on s390 since a couple of > displacements used in asm code now get too large: > > arch/s390/kernel/entry.S:181: Error: operand out of range (0x00000000000018a8 is not between 0x0000000000000000 and 0x0000000000000fff) > arch/s390/kernel/entry.S:191: Error: operand out of range (0x00000000000018a8 is not between 0x0000000000000000 and 0x0000000000000fff) > arch/s390/kernel/entry.S:423: Error: operand out of range (0x0000000000001924 is not between 0x0000000000000000 and 0x0000000000000fff) > arch/s390/kernel/entry.S:437: Error: operand out of range (0x00000000000018e8 is not between 0x0000000000000000 and 0x0000000000000fff) > arch/s390/kernel/entry.S:438: Error: operand out of range (0x00000000000018e0 is not between 0x0000000000000000 and 0x0000000000000fff) > arch/s390/kernel/entry.S:439: Error: operand out of range (0x00000000000018f0 is not between 0x0000000000000000 and 0x0000000000000fff) > make[1]: *** [arch/s390/kernel/entry.o] Error 1 > > Let's see how we can fix this. Sorry about this! So I looked at the __switch_to() assembly, and the main complication appears to be that we have two uses of 'prev': lg %r4,__THREAD_info(%r2) # get thread_info of prev stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev the __THREAD_info offset is best expressed relative to task_struct - the __THREAD_ksp offset is best expressed relative to thread_struct. I.e. I think the best fix would be to extend the signature of s390's __switch_to() from (prev,next) to (prev,next,prev_thread,next_thread). Is the C parameter mapping r2,r3,r4,r5? If yes then the patch below should do the trick. (Utterly untested.) Note: - I renamed __THREAD_info to __TASK_thread_info, to better separate task_struct and thread_struct offsets syntactically and visually. - I removed __THREAD_mm_segment which is unused I also looked at fixing pgm_check_handler(), but my s390-fu gave up completely on that one: task_struct is in 'r14', but this is a hardware entry function it appears. So to fix it we'd have to pick a temporary register, put thread_struct pointer into it, and fix up these offsets: arch/s390/kernel/asm-offsets.c: DEFINE(__THREAD_per_address, offsetof(struct task_struct, thread.per_event.address)); arch/s390/kernel/asm-offsets.c: DEFINE(__THREAD_per_paid, offsetof(struct task_struct, thread.per_event.paid)); arch/s390/kernel/asm-offsets.c: DEFINE(__THREAD_trap_tdb, offsetof(struct task_struct, thread.trap_tdb)); to be thread_struct relative. Thanks, Ingo ==============> arch/s390/include/asm/switch_to.h | 7 +++++-- arch/s390/kernel/asm-offsets.c | 5 ++--- arch/s390/kernel/entry.S | 14 +++++++++----- 3 files changed, 16 insertions(+), 10 deletions(-) diff --git a/arch/s390/include/asm/switch_to.h b/arch/s390/include/asm/switch_to.h index d62e7a69605f..aa854b600938 100644 --- a/arch/s390/include/asm/switch_to.h +++ b/arch/s390/include/asm/switch_to.h @@ -10,7 +10,10 @@ #include #include -extern struct task_struct *__switch_to(void *, void *); +extern struct task_struct * +__switch_to(struct task_struct *prev, struct task_struct *next, + struct thread_struct *prev_thread, struct thread_struct *next_thrad); + extern void update_cr_regs(struct task_struct *task); static inline int test_fp_ctl(u32 fpc) @@ -169,7 +172,7 @@ static inline void restore_access_regs(unsigned int *acrs) restore_access_regs(&next->thread.acrs[0]); \ restore_ri_cb(next->thread.ri_cb, prev->thread.ri_cb); \ } \ - prev = __switch_to(prev,next); \ + prev = __switch_to(prev, next, &prev->thread, &next->thread); \ } while (0) #endif /* __ASM_SWITCH_TO_H */ diff --git a/arch/s390/kernel/asm-offsets.c b/arch/s390/kernel/asm-offsets.c index c7d1b9d09011..2b422297660f 100644 --- a/arch/s390/kernel/asm-offsets.c +++ b/arch/s390/kernel/asm-offsets.c @@ -23,9 +23,8 @@ int main(void) { - DEFINE(__THREAD_info, offsetof(struct task_struct, stack)); - DEFINE(__THREAD_ksp, offsetof(struct task_struct, thread.ksp)); - DEFINE(__THREAD_mm_segment, offsetof(struct task_struct, thread.mm_segment)); + DEFINE(__TASK_thread_info, offsetof(struct task_struct, stack)); + DEFINE(__THREAD_ksp, offsetof(struct thread_struct, ksp)); BLANK(); DEFINE(__TASK_pid, offsetof(struct task_struct, pid)); BLANK(); diff --git a/arch/s390/kernel/entry.S b/arch/s390/kernel/entry.S index 3238893c9d4f..c2fcb9e7ad25 100644 --- a/arch/s390/kernel/entry.S +++ b/arch/s390/kernel/entry.S @@ -170,17 +170,21 @@ _PIF_WORK = (_PIF_PER_TRAP) .section .kprobes.text, "ax" /* - * Scheduler resume function, called by switch_to + * Low level scheduler resume function, called by switch_to(): + * * gpr2 = (task_struct *) prev * gpr3 = (task_struct *) next + * gpr4 = (thread_struct *) prev->thread + * gpr5 = (thread_struct *) next->thread + * * Returns: * gpr2 = prev */ ENTRY(__switch_to) stmg %r6,%r15,__SF_GPRS(%r15) # store gprs of prev task - stg %r15,__THREAD_ksp(%r2) # store kernel stack of prev - lg %r4,__THREAD_info(%r2) # get thread_info of prev - lg %r5,__THREAD_info(%r3) # get thread_info of next + stg %r15,__THREAD_ksp(%r4) # store kernel stack of prev + lg %r4,__TASK_thread_info(%r2) # get thread_info of prev + lg %r5,__TASK_thread_info(%r3) # get thread_info of next lgr %r15,%r5 aghi %r15,STACK_INIT # end of kernel stack of next stg %r3,__LC_CURRENT # store task struct of next @@ -188,7 +192,7 @@ ENTRY(__switch_to) stg %r15,__LC_KERNEL_STACK # store end of kernel stack lctl %c4,%c4,__TASK_pid(%r3) # load pid to control reg. 4 mvc __LC_CURRENT_PID+4(4,%r0),__TASK_pid(%r3) # store pid of next - lg %r15,__THREAD_ksp(%r3) # load kernel stack of next + lg %r15,__THREAD_ksp(%r5) # load kernel stack of next lmg %r6,%r15,__SF_GPRS(%r15) # load gprs of next task br %r14 -- To unsubscribe from this list: send the line "unsubscribe linux-kernel" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html Please read the FAQ at http://www.tux.org/lkml/