Skip to content

Commit 18ed1c0

Browse files
committed
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 <[email protected]> Signed-off-by: Keith Packard <[email protected]> Signed-off-by: Ard Biesheuvel <[email protected]> Reviewed-by: Linus Walleij <[email protected]> Tested-by: Amit Daniel Kachhap <[email protected]>
1 parent 50596b7 commit 18ed1c0

File tree

7 files changed

+35
-2
lines changed

7 files changed

+35
-2
lines changed

arch/arm/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,7 @@ config ARM
125125
select PERF_USE_VMALLOC
126126
select RTC_LIB
127127
select SYS_SUPPORTS_APM_EMULATION
128+
select THREAD_INFO_IN_TASK if CURRENT_POINTER_IN_TPIDRURO
128129
select TRACE_IRQFLAGS_SUPPORT if !CPU_V7M
129130
# Above selects are sorted alphabetically; please add new ones
130131
# according to that. Thanks.

arch/arm/include/asm/assembler.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -227,10 +227,15 @@
227227
* Get current thread_info.
228228
*/
229229
.macro get_thread_info, rd
230+
#ifdef CONFIG_THREAD_INFO_IN_TASK
231+
/* thread_info is the first member of struct task_struct */
232+
get_current \rd
233+
#else
230234
ARM( mov \rd, sp, lsr #THREAD_SIZE_ORDER + PAGE_SHIFT )
231235
THUMB( mov \rd, sp )
232236
THUMB( lsr \rd, \rd, #THREAD_SIZE_ORDER + PAGE_SHIFT )
233237
mov \rd, \rd, lsl #THREAD_SIZE_ORDER + PAGE_SHIFT
238+
#endif
234239
.endm
235240

236241
/*

arch/arm/include/asm/switch_to.h

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,23 @@
2323
*/
2424
extern struct task_struct *__switch_to(struct task_struct *, struct thread_info *, struct thread_info *);
2525

26+
static inline void set_ti_cpu(struct task_struct *p)
27+
{
28+
#ifdef CONFIG_THREAD_INFO_IN_TASK
29+
/*
30+
* The core code no longer maintains the thread_info::cpu field once
31+
* CONFIG_THREAD_INFO_IN_TASK is in effect, but we rely on it for
32+
* raw_smp_processor_id(), which cannot access struct task_struct*
33+
* directly for reasons of circular #inclusion hell.
34+
*/
35+
task_thread_info(p)->cpu = task_cpu(p);
36+
#endif
37+
}
38+
2639
#define switch_to(prev,next,last) \
2740
do { \
2841
__complete_pending_tlbi(); \
42+
set_ti_cpu(next); \
2943
if (IS_ENABLED(CONFIG_CURRENT_POINTER_IN_TPIDRURO)) \
3044
__this_cpu_write(__entry_task, next); \
3145
last = __switch_to(prev,task_thread_info(prev), task_thread_info(next)); \

arch/arm/include/asm/thread_info.h

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,9 @@ struct cpu_context_save {
5454
struct thread_info {
5555
unsigned long flags; /* low level flags */
5656
int preempt_count; /* 0 => preemptable, <0 => bug */
57+
#ifndef CONFIG_THREAD_INFO_IN_TASK
5758
struct task_struct *task; /* main task structure */
59+
#endif
5860
__u32 cpu; /* cpu */
5961
__u32 cpu_domain; /* cpu domain */
6062
struct cpu_context_save cpu_context; /* cpu context */
@@ -70,11 +72,16 @@ struct thread_info {
7072

7173
#define INIT_THREAD_INFO(tsk) \
7274
{ \
73-
.task = &tsk, \
75+
INIT_THREAD_INFO_TASK(tsk) \
7476
.flags = 0, \
7577
.preempt_count = INIT_PREEMPT_COUNT, \
7678
}
7779

80+
#ifdef CONFIG_THREAD_INFO_IN_TASK
81+
#define INIT_THREAD_INFO_TASK(tsk)
82+
#else
83+
#define INIT_THREAD_INFO_TASK(tsk) .task = &(tsk),
84+
7885
/*
7986
* how to get the thread information struct from C
8087
*/
@@ -85,6 +92,7 @@ static inline struct thread_info *current_thread_info(void)
8592
return (struct thread_info *)
8693
(current_stack_pointer & ~(THREAD_SIZE - 1));
8794
}
95+
#endif
8896

8997
#define thread_saved_pc(tsk) \
9098
((unsigned long)(task_thread_info(tsk)->cpu_context.pc))

arch/arm/kernel/asm-offsets.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,9 @@ int main(void)
4343
BLANK();
4444
DEFINE(TI_FLAGS, offsetof(struct thread_info, flags));
4545
DEFINE(TI_PREEMPT, offsetof(struct thread_info, preempt_count));
46+
#ifndef CONFIG_THREAD_INFO_IN_TASK
4647
DEFINE(TI_TASK, offsetof(struct thread_info, task));
48+
#endif
4749
DEFINE(TI_CPU, offsetof(struct thread_info, cpu));
4850
DEFINE(TI_CPU_DOMAIN, offsetof(struct thread_info, cpu_domain));
4951
DEFINE(TI_CPU_SAVE, offsetof(struct thread_info, cpu_context));

arch/arm/kernel/entry-armv.S

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -765,7 +765,7 @@ ENTRY(__switch_to)
765765
.endif
766766
ldr r7, [r7, #TSK_STACK_CANARY & IMM12_MASK]
767767
#elif defined(CONFIG_CURRENT_POINTER_IN_TPIDRURO)
768-
ldr r7, [r2, #TI_TASK]
768+
mov r7, r2 @ Preserve 'next'
769769
#endif
770770
#ifdef CONFIG_CPU_USE_DOMAINS
771771
mcr p15, 0, r6, c3, c0, 0 @ Set domain register

arch/arm/kernel/smp.c

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,6 +154,9 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
154154
secondary_data.swapper_pg_dir = get_arch_pgd(swapper_pg_dir);
155155
#endif
156156
secondary_data.task = idle;
157+
if (IS_ENABLED(CONFIG_THREAD_INFO_IN_TASK))
158+
task_thread_info(idle)->cpu = cpu;
159+
157160
sync_cache_w(&secondary_data);
158161

159162
/*

0 commit comments

Comments
 (0)