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: Keith Packard <keithpac@amazon.com> Signed-off-by: Keith Packard <keithpac@amazon.com> Signed-off-by: Ard Biesheuvel <ardb@kernel.org> Reviewed-by: Linus Walleij <linus.walleij@linaro.org> Tested-by: Amit Daniel Kachhap <amit.kachhap@arm.com>
This commit is contained in:
parent
50596b7559
commit
18ed1c01a7
@ -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.
|
||||
|
@ -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
|
||||
|
||||
/*
|
||||
|
@ -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)); \
|
||||
|
@ -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))
|
||||
|
@ -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));
|
||||
|
@ -765,7 +765,7 @@ ENTRY(__switch_to)
|
||||
.endif
|
||||
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
|
||||
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
|
||||
ldr r7, [r2, #TI_TASK]
|
||||
mov r7, r2 @ Preserve 'next'
|
||||
#endif
|
||||
#ifdef CONFIG_CPU_USE_DOMAINS
|
||||
mcr p15, 0, r6, c3, c0, 0 @ Set domain register
|
||||
|
@ -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);
|
||||
#endif
|
||||
secondary_data.task = idle;
|
||||
if (IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK))
|
||||
task_thread_info(idle)->cpu = cpu;
|
||||
|
||||
sync_cache_w(&secondary_data);
|
||||
|
||||
/*
|
||||
|
Loading…
Reference in New Issue
Block a user