All of lore.kernel.org
 help / color / mirror / Atom feed
From: mark.rutland@arm.com (Mark Rutland)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 10/10] arm64: split thread_info from task stack
Date: Fri, 21 Oct 2016 16:59:02 +0100	[thread overview]
Message-ID: <20161021155701.GA17287@leverpostej> (raw)
In-Reply-To: <580A2B3A.7000300@arm.com>

Hi James,

On Fri, Oct 21, 2016 at 03:50:34PM +0100, James Morse wrote:
> >  arch/arm64/kernel/entry.S            |  4 ++--
> 
> 4? That was too easy...

Indeed... ;)

> > diff --git a/arch/arm64/kernel/entry.S b/arch/arm64/kernel/entry.S
> > index 2d4c83b..e781391 100644
> > --- a/arch/arm64/kernel/entry.S
> > +++ b/arch/arm64/kernel/entry.S
> > @@ -123,6 +123,7 @@
> >  	 * Set sp_el0 to current thread_info.
> >  	 */
> >  	.if	\el == 0
> > +	ldr_this_cpu	tsk, __entry_task, x21
> >  	msr	sp_el0, tsk
> >  	.endif
> >  
> > @@ -674,8 +675,7 @@ ENTRY(cpu_switch_to)
> >  	ldp	x29, x9, [x8], #16
> >  	ldr	lr, [x8]
> >  	mov	sp, x9
> > -	and	x9, x9, #~(THREAD_SIZE - 1)
> > -	msr	sp_el0, x9
> > +	msr	sp_el0, x1
> >  	ret
> >  ENDPROC(cpu_switch_to)
> >  
> 
> So now tsk is current instead of current_thread_info(), but we still access it
> with TI_* offsets:

Yes; luckily thread_info is the first member of task_struct, so this
works (as offsetof(struct task_struct, thread_info) == 0). The core code
also relies on this, e.g. in <linux/thread_info.h>:

	#ifdef CONFIG_THREAD_INFO_IN_TASK
	#define current_thread_info() ((struct thread_info *)current)
	#endif

... regardless, I should have commented that, mentioned it in the commit
message, and perhaps put a BUILD_BUG_ON()-style assert somewhere. I'll
need to double-check, but IIRC I can't update asm-offsets to base the
TI_* offsets on task_struct without introducing a potential circular
include dependency.

I could at least s/TI_/TSK_/, with a comment.

> The 're-entered irq stack' check is going to need re-thinking:
> entry.S:195
> > 	/*
> > 	 * Compare sp with the current thread_info, if the top
> > 	 * ~(THREAD_SIZE - 1) bits match, we are on a task stack, and
> > 	 * should switch to the irq stack.
> > 	 */
> > 	and	x25, x19, #~(THREAD_SIZE - 1)
> > 	cmp	x25, tsk
> > 	b.ne	9998f
> 
> It was done like this as the irq stack isn't naturally aligned, so this check
> implicitly assumes tsk is on the stack. I will try and come up with an alternative.

Ouch; I clearly didn't vet this thoroughly enough.

If we can corrupt another register here, we can load task_struct::stack
to compare against instead.

> And there are a few other things like this:
> entry.S:431
> > 	ldr	w24, [tsk, #TI_PREEMPT]		// get preempt count
> > 	cbnz	w24, 1f				// preempt count != 0
> > 	ldr	x0, [tsk, #TI_FLAGS]		// get flags
> > 	tbz	x0, #TIF_NEED_RESCHED, 1f	// needs rescheduling?
> > 	bl	el1_preempt
> 
> (It may be worth renaming the register alias 'tsk' as it isn't really a
>  struct_task. This would catch any missed users at build time, including
>  any patches in flight...)

Entertainingly, with these patches 'tsk' *is* task_struct, whereas
before it wasn't. 

> > diff --git a/arch/arm64/kernel/smp.c b/arch/arm64/kernel/smp.c
> > index 2679722..cde25f4 100644
> > --- a/arch/arm64/kernel/smp.c
> > +++ b/arch/arm64/kernel/smp.c
> > @@ -149,6 +149,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
> >  	 * We need to tell the secondary core where to find its stack and the
> >  	 * page tables.
> >  	 */
> > +	secondary_data.task = idle;
> >  	secondary_data.stack = task_stack_page(idle) + THREAD_START_SP;
> >  	update_cpu_boot_status(CPU_MMU_OFF);
> >  	__flush_dcache_area(&secondary_data, sizeof(secondary_data));
> > @@ -173,6 +174,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
> >  		pr_err("CPU%u: failed to boot: %d\n", cpu, ret);
> >  	}
> >  
> > +	secondary_data.task = NULL;
> >  	secondary_data.stack = NULL;
> >  	status = READ_ONCE(secondary_data.status);
> >  	if (ret && status) {
> > 
> 
> Nit-territory: Something we should remember is that __entry_task isn't written
> on secondary startup, so its stale (CPU0s idle task) until the first
> __switch_to(). This isn't a problem as its only read on entry from EL0.

Good point. I think I can initialise this in the hotplug path, if
nothing else but to save us any surprises when debugging.

Thanks,
Mark.

  reply	other threads:[~2016-10-21 15:59 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-10-19 19:10 [PATCH 00/10] arm64: move thread_info off of the task stack Mark Rutland
2016-10-19 19:10 ` [PATCH 01/10] arm64: thread_info remove stale items Mark Rutland
2016-10-19 19:10 ` [PATCH 02/10] arm64: asm-offsets: remove unused definitions Mark Rutland
2016-10-19 19:10 ` [PATCH 03/10] arm64: factor out current_stack_pointer Mark Rutland
2016-10-19 19:10 ` [PATCH 04/10] arm64: traps: simplify die() and __die() Mark Rutland
2016-10-19 19:10 ` [PATCH 05/10] arm64: prep stack walkers for THREAD_INFO_IN_TASK Mark Rutland
2016-10-19 19:10 ` [PATCH 06/10] arm64: move sp_el0 and tpidr_el1 into cpu_suspend_ctx Mark Rutland
2016-10-19 19:10 ` [PATCH 07/10] arm64: smp: prepare for smp_processor_id() rework Mark Rutland
2016-10-19 19:10 ` [PATCH 08/10] arm64: make cpu number a percpu variable Mark Rutland
2016-10-19 19:10 ` [PATCH 09/10] arm64: assembler: introduce ldr_this_cpu Mark Rutland
2016-10-19 19:10 ` [PATCH 10/10] arm64: split thread_info from task stack Mark Rutland
2016-10-21 14:50   ` James Morse
2016-10-21 15:59     ` Mark Rutland [this message]
2016-10-21 17:27       ` Mark Rutland
2016-10-21 16:20     ` Mark Rutland
2016-10-24 17:38 ` [PATCH 00/10] arm64: move thread_info off of the " Laura Abbott
2016-10-24 17:48   ` Mark Rutland
2016-10-24 17:58     ` Laura Abbott
2016-10-24 18:09       ` Mark Rutland
2016-10-24 18:15         ` Mark Rutland
2016-10-24 18:18           ` Kees Cook
2016-10-25 10:05             ` Mark Rutland
2016-10-26  0:46         ` Laura Abbott
2016-10-26  9:55           ` Mark Rutland

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20161021155701.GA17287@leverpostej \
    --to=mark.rutland@arm.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.