Commit 18ed1c01 authored by Ard Biesheuvel's avatar Ard Biesheuvel
Browse files

ARM: smp: Enable THREAD_INFO_IN_TASK



Now that we no longer rely on thread_info living at the base of the task
stack to be able to access the 'current' pointer, we can wire up the
generic support for moving thread_info into the task struct itself.

Note that this requires us to update the cpu field in thread_info
explicitly, now that the core code no longer does so. Ideally, we would
switch the percpu code to access the cpu field in task_struct instead,
but this unleashes #include circular dependency hell.

Co-developed-by: default avatarKeith Packard <keithpac@amazon.com>
Signed-off-by: default avatarKeith Packard <keithpac@amazon.com>
Signed-off-by: default avatarArd Biesheuvel <ardb@kernel.org>
Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
Tested-by: default avatarAmit Daniel Kachhap <amit.kachhap@arm.com>
parent 50596b75
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -125,6 +125,7 @@ config ARM
	select PERF_USE_VMALLOC
	select RTC_LIB
	select SYS_SUPPORTS_APM_EMULATION
	select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
	select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
	# Above selects are sorted alphabetically; please add new ones
	# according to that.  Thanks.
+5 −0
Original line number Diff line number Diff line
@@ -227,10 +227,15 @@
 * Get current thread_info.
 */
	.macro	get_thread_info, rd
#ifdef CONFIG_THREAD_INFO_IN_TASK
	/* thread_info is the first member of struct task_struct */
	get_current \rd
#else
 ARM(	mov	\rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT	)
 THUMB(	mov	\rd, sp			)
 THUMB(	lsr	\rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT	)
	mov	\rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
#endif
	.endm

/*
+14 −0
Original line number Diff line number Diff line
@@ -23,9 +23,23 @@
 */
extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);

static inline void set_ti_cpu(struct task_struct *p)
{
#ifdef CONFIG_THREAD_INFO_IN_TASK
	/*
	 * The core code no longer maintains the thread_info::cpu field once
	 * CONFIG_THREAD_INFO_IN_TASK is in effect, but we rely on it for
	 * raw_smp_processor_id(), which cannot access struct task_struct*
	 * directly for reasons of circular #inclusion hell.
	 */
	task_thread_info(p)->cpu = task_cpu(p);
#endif
}

#define switch_to(prev,next,last)					\
do {									\
	__complete_pending_tlbi();					\
	set_ti_cpu(next);						\
	if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO))		\
		__this_cpu_write(__entry_task, next);			\
	last = __switch_to(prev,task_thread_info(prev), task_thread_info(next));	\
+9 −1
Original line number Diff line number Diff line
@@ -54,7 +54,9 @@ struct cpu_context_save {
struct thread_info {
	unsigned long		flags;		/* low level flags */
	int			preempt_count;	/* 0 => preemptable, <0 => bug */
#ifndef CONFIG_THREAD_INFO_IN_TASK
	struct task_struct	*task;		/* main task structure */
#endif
	__u32			cpu;		/* cpu */
	__u32			cpu_domain;	/* cpu domain */
	struct cpu_context_save	cpu_context;	/* cpu context */
@@ -70,11 +72,16 @@ struct thread_info {

#define INIT_THREAD_INFO(tsk)						\
{									\
	.task		= &tsk,						\
	INIT_THREAD_INFO_TASK(tsk)					\
	.flags		= 0,						\
	.preempt_count	= INIT_PREEMPT_COUNT,				\
}

#ifdef CONFIG_THREAD_INFO_IN_TASK
#define INIT_THREAD_INFO_TASK(tsk)
#else
#define INIT_THREAD_INFO_TASK(tsk)	.task = &(tsk),

/*
 * how to get the thread information struct from C
 */
@@ -85,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
	return (struct thread_info *)
		(current_stack_pointer & ~(THREAD_SIZE - 1));
}
#endif

#define thread_saved_pc(tsk)	\
	((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
+2 −0
Original line number Diff line number Diff line
@@ -43,7 +43,9 @@ int main(void)
  BLANK();
  DEFINE(TI_FLAGS,		offsetof(struct thread_info, flags));
  DEFINE(TI_PREEMPT,		offsetof(struct thread_info, preempt_count));
#ifndef CONFIG_THREAD_INFO_IN_TASK
  DEFINE(TI_TASK,		offsetof(struct thread_info, task));
#endif
  DEFINE(TI_CPU,		offsetof(struct thread_info, cpu));
  DEFINE(TI_CPU_DOMAIN,		offsetof(struct thread_info, cpu_domain));
  DEFINE(TI_CPU_SAVE,		offsetof(struct thread_info, cpu_context));
Loading