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

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
...@@ -125,6 +125,7 @@ config ARM ...@@ -125,6 +125,7 @@ config ARM
select PERF_USE_VMALLOC select PERF_USE_VMALLOC
select RTC_LIB select RTC_LIB
select SYS_SUPPORTS_APM_EMULATION select SYS_SUPPORTS_APM_EMULATION
select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
# Above selects are sorted alphabetically; please add new ones # Above selects are sorted alphabetically; please add new ones
# according to that. Thanks. # according to that. Thanks.
......
...@@ -227,10 +227,15 @@ ...@@ -227,10 +227,15 @@
* Get current thread_info. * Get current thread_info.
*/ */
.macro get_thread_info, rd .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 ) ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT )
THUMB( mov \rd, sp ) THUMB( mov \rd, sp )
THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT ) THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT )
mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
#endif
.endm .endm
/* /*
......
...@@ -23,9 +23,23 @@ ...@@ -23,9 +23,23 @@
*/ */
extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *); 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) \ #define switch_to(prev,next,last) \
do { \ do { \
__complete_pending_tlbi(); \ __complete_pending_tlbi(); \
set_ti_cpu(next); \
if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) \ if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) \
__this_cpu_write(__entry_task, next); \ __this_cpu_write(__entry_task, next); \
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \ last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \
......
...@@ -54,7 +54,9 @@ struct cpu_context_save { ...@@ -54,7 +54,9 @@ struct cpu_context_save {
struct thread_info { struct thread_info {
unsigned long flags; /* low level flags */ unsigned long flags; /* low level flags */
int preempt_count; /* 0 => preemptable, <0 => bug */ int preempt_count; /* 0 => preemptable, <0 => bug */
#ifndef CONFIG_THREAD_INFO_IN_TASK
struct task_struct *task; /* main task structure */ struct task_struct *task; /* main task structure */
#endif
__u32 cpu; /* cpu */ __u32 cpu; /* cpu */
__u32 cpu_domain; /* cpu domain */ __u32 cpu_domain; /* cpu domain */
struct cpu_context_save cpu_context; /* cpu context */ struct cpu_context_save cpu_context; /* cpu context */
...@@ -70,11 +72,16 @@ struct thread_info { ...@@ -70,11 +72,16 @@ struct thread_info {
#define INIT_THREAD_INFO(tsk) \ #define INIT_THREAD_INFO(tsk) \
{ \ { \
.task = &tsk, \ INIT_THREAD_INFO_TASK(tsk) \
.flags = 0, \ .flags = 0, \
.preempt_count = INIT_PREEMPT_COUNT, \ .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 * how to get the thread information struct from C
*/ */
...@@ -85,6 +92,7 @@ static inline struct thread_info *current_thread_info(void) ...@@ -85,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
return (struct thread_info *) return (struct thread_info *)
(current_stack_pointer & ~(THREAD_SIZE - 1)); (current_stack_pointer & ~(THREAD_SIZE - 1));
} }
#endif
#define thread_saved_pc(tsk) \ #define thread_saved_pc(tsk) \
((unsigned long)(task_thread_info(tsk)->cpu_context.pc)) ((unsigned long)(task_thread_info(tsk)->cpu_context.pc))
......
...@@ -43,7 +43,9 @@ int main(void) ...@@ -43,7 +43,9 @@ int main(void)
BLANK(); BLANK();
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags)); DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count)); DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
#ifndef CONFIG_THREAD_INFO_IN_TASK
DEFINE(TI_TASK, offsetof(struct thread_info, task)); DEFINE(TI_TASK, offsetof(struct thread_info, task));
#endif
DEFINE(TI_CPU, offsetof(struct thread_info, cpu)); DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain)); DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context)); DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));
......
...@@ -765,7 +765,7 @@ ENTRY(__switch_to) ...@@ -765,7 +765,7 @@ ENTRY(__switch_to)
.endif .endif
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK] ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO) #elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
ldr r7, [r2, #TI_TASK] mov r7, r2 @ Preserve 'next'
#endif #endif
#ifdef CONFIG_CPU_USE_DOMAINS #ifdef CONFIG_CPU_USE_DOMAINS
mcr p15, 0, r6, c3, c0, 0 @ Set domain register mcr p15, 0, r6, c3, c0, 0 @ Set domain register
......
...@@ -154,6 +154,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle) ...@@ -154,6 +154,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir); secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
#endif #endif
secondary_data.task = idle; secondary_data.task = idle;
if (IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK))
task_thread_info(idle)->cpu = cpu;
sync_cache_w(&secondary_data); sync_cache_w(&secondary_data);
/* /*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment