Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Construct init thread stack in the linker script rather than by union

Construct the init thread stack in the linker script rather than doing it
by means of a union so that ia64's init_task.c can be got rid of.

The following symbols are then made available from INIT_TASK_DATA() linker
script macro:

init_thread_union
init_stack

INIT_TASK_DATA() also expands the region to THREAD_SIZE to accommodate the
size of the init stack. init_thread_union is given its own section so that
it can be placed into the stack space in the right order. I'm assuming
that the ia64 ordering is correct and that the task_struct is first and the
thread_info second.

Signed-off-by: David Howells <dhowells@redhat.com>
Tested-by: Tony Luck <tony.luck@intel.com>
Tested-by: Will Deacon <will.deacon@arm.com> (arm64)
Tested-by: Palmer Dabbelt <palmer@sifive.com>
Acked-by: Thomas Gleixner <tglx@linutronix.de>

+42 -155
+2 -2
arch/Kconfig
··· 234 234 config ARCH_HAS_SET_MEMORY 235 235 bool 236 236 237 - # Select if arch init_task initializer is different to init/init_task.c 238 - config ARCH_INIT_TASK 237 + # Select if arch init_task must go in the __init_task_data section 238 + config ARCH_TASK_STRUCT_ON_STACK 239 239 bool 240 240 241 241 # Select if arch has its private alloc_task_struct() function
-3
arch/alpha/include/asm/thread_info.h
··· 39 39 .preempt_count = INIT_PREEMPT_COUNT, \ 40 40 } 41 41 42 - #define init_thread_info (init_thread_union.thread_info) 43 - #define init_stack (init_thread_union.stack) 44 - 45 42 /* How to get the thread information struct from C. */ 46 43 register struct thread_info *__current_thread_info __asm__("$8"); 47 44 #define current_thread_info() __current_thread_info
-3
arch/arc/include/asm/thread_info.h
··· 62 62 .addr_limit = KERNEL_DS, \ 63 63 } 64 64 65 - #define init_thread_info (init_thread_union.thread_info) 66 - #define init_stack (init_thread_union.stack) 67 - 68 65 static inline __attribute_const__ struct thread_info *current_thread_info(void) 69 66 { 70 67 register unsigned long sp asm("sp");
-3
arch/arm/include/asm/thread_info.h
··· 75 75 .addr_limit = KERNEL_DS, \ 76 76 } 77 77 78 - #define init_thread_info (init_thread_union.thread_info) 79 - #define init_stack (init_thread_union.stack) 80 - 81 78 /* 82 79 * how to get the current stack pointer in C 83 80 */
-2
arch/arm64/include/asm/thread_info.h
··· 51 51 .addr_limit = KERNEL_DS, \ 52 52 } 53 53 54 - #define init_stack (init_thread_union.stack) 55 - 56 54 #define thread_saved_pc(tsk) \ 57 55 ((unsigned long)(tsk->thread.cpu_context.pc)) 58 56 #define thread_saved_sp(tsk) \
-2
arch/blackfin/include/asm/thread_info.h
··· 56 56 .cpu = 0, \ 57 57 .preempt_count = INIT_PREEMPT_COUNT, \ 58 58 } 59 - #define init_thread_info (init_thread_union.thread_info) 60 - #define init_stack (init_thread_union.stack) 61 59 62 60 /* Given a task stack pointer, you can find its corresponding 63 61 * thread_info structure just by masking it to the THREAD_SIZE
-3
arch/c6x/include/asm/thread_info.h
··· 60 60 .addr_limit = KERNEL_DS, \ 61 61 } 62 62 63 - #define init_thread_info (init_thread_union.thread_info) 64 - #define init_stack (init_thread_union.stack) 65 - 66 63 /* get the thread information struct of current task */ 67 64 static inline __attribute__((const)) 68 65 struct thread_info *current_thread_info(void)
-2
arch/cris/include/asm/processor.h
··· 52 52 /* Nothing needs to be done. */ 53 53 } 54 54 55 - #define init_stack (init_thread_union.stack) 56 - 57 55 #define cpu_relax() barrier() 58 56 59 57 void default_idle(void);
-2
arch/cris/include/asm/thread_info.h
··· 63 63 .addr_limit = KERNEL_DS, \ 64 64 } 65 65 66 - #define init_thread_info (init_thread_union.thread_info) 67 - 68 66 #endif /* !__ASSEMBLY__ */ 69 67 70 68 /*
-3
arch/frv/include/asm/thread_info.h
··· 64 64 .addr_limit = KERNEL_DS, \ 65 65 } 66 66 67 - #define init_thread_info (init_thread_union.thread_info) 68 - #define init_stack (init_thread_union.stack) 69 - 70 67 /* how to get the thread information struct from C */ 71 68 register struct thread_info *__current_thread_info asm("gr15"); 72 69
-3
arch/h8300/include/asm/thread_info.h
··· 46 46 .addr_limit = KERNEL_DS, \ 47 47 } 48 48 49 - #define init_thread_info (init_thread_union.thread_info) 50 - #define init_stack (init_thread_union.stack) 51 - 52 49 /* how to get the thread information struct from C */ 53 50 static inline struct thread_info *current_thread_info(void) 54 51 {
-3
arch/hexagon/include/asm/thread_info.h
··· 84 84 .regs = NULL, \ 85 85 } 86 86 87 - #define init_thread_info (init_thread_union.thread_info) 88 - #define init_stack (init_thread_union.stack) 89 - 90 87 /* Tacky preprocessor trickery */ 91 88 #define qqstr(s) qstr(s) 92 89 #define qstr(s) #s
+1 -1
arch/ia64/Kconfig
··· 43 43 select ARCH_HAVE_NMI_SAFE_CMPXCHG 44 44 select GENERIC_IOMAP 45 45 select GENERIC_SMP_IDLE_THREAD 46 - select ARCH_INIT_TASK 46 + select ARCH_TASK_STRUCT_ON_STACK 47 47 select ARCH_TASK_STRUCT_ALLOCATOR 48 48 select ARCH_THREAD_STACK_ALLOCATOR 49 49 select ARCH_CLOCKSOURCE_DATA
+1 -1
arch/ia64/Makefile
··· 42 42 endif 43 43 44 44 KBUILD_CFLAGS += $(cflags-y) 45 - head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o 45 + head-y := arch/ia64/kernel/head.o 46 46 47 47 libs-y += arch/ia64/lib/ 48 48 core-y += arch/ia64/kernel/ arch/ia64/mm/
+2 -2
arch/ia64/include/asm/thread_info.h
··· 12 12 #include <asm/processor.h> 13 13 #include <asm/ptrace.h> 14 14 15 + #define THREAD_SIZE KERNEL_STACK_SIZE 16 + 15 17 #ifndef __ASSEMBLY__ 16 18 17 19 /* ··· 42 40 __u64 ac_utime; 43 41 #endif 44 42 }; 45 - 46 - #define THREAD_SIZE KERNEL_STACK_SIZE 47 43 48 44 #define INIT_THREAD_INFO(tsk) \ 49 45 { \
+1 -1
arch/ia64/kernel/Makefile
··· 7 7 CFLAGS_REMOVE_ftrace.o = -pg 8 8 endif 9 9 10 - extra-y := head.o init_task.o vmlinux.lds 10 + extra-y := head.o vmlinux.lds 11 11 12 12 obj-y := entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o \ 13 13 irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o \
-44
arch/ia64/kernel/init_task.c
··· 1 - // SPDX-License-Identifier: GPL-2.0 2 - /* 3 - * This is where we statically allocate and initialize the initial 4 - * task. 5 - * 6 - * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co 7 - * David Mosberger-Tang <davidm@hpl.hp.com> 8 - */ 9 - 10 - #include <linux/init.h> 11 - #include <linux/mm.h> 12 - #include <linux/fs.h> 13 - #include <linux/module.h> 14 - #include <linux/sched.h> 15 - #include <linux/init_task.h> 16 - #include <linux/mqueue.h> 17 - 18 - #include <linux/uaccess.h> 19 - #include <asm/pgtable.h> 20 - 21 - static struct signal_struct init_signals = INIT_SIGNALS(init_signals); 22 - static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); 23 - /* 24 - * Initial task structure. 25 - * 26 - * We need to make sure that this is properly aligned due to the way process stacks are 27 - * handled. This is done by having a special ".data..init_task" section... 28 - */ 29 - #define init_thread_info init_task_mem.s.thread_info 30 - #define init_stack init_task_mem.stack 31 - 32 - union { 33 - struct { 34 - struct task_struct task; 35 - struct thread_info thread_info; 36 - } s; 37 - unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)]; 38 - } init_task_mem asm ("init_task") __init_task_data = 39 - {{ 40 - .task = INIT_TASK(init_task_mem.s.task), 41 - .thread_info = INIT_THREAD_INFO(init_task_mem.s.task) 42 - }}; 43 - 44 - EXPORT_SYMBOL(init_task);
+1
arch/ia64/kernel/vmlinux.lds.S
··· 3 3 #include <asm/cache.h> 4 4 #include <asm/ptrace.h> 5 5 #include <asm/pgtable.h> 6 + #include <asm/thread_info.h> 6 7 7 8 #include <asm-generic/vmlinux.lds.h> 8 9
-3
arch/m32r/include/asm/thread_info.h
··· 56 56 .addr_limit = KERNEL_DS, \ 57 57 } 58 58 59 - #define init_thread_info (init_thread_union.thread_info) 60 - #define init_stack (init_thread_union.stack) 61 - 62 59 /* how to get the thread information struct from C */ 63 60 static inline struct thread_info *current_thread_info(void) 64 61 {
-4
arch/m68k/include/asm/thread_info.h
··· 41 41 .preempt_count = INIT_PREEMPT_COUNT, \ 42 42 } 43 43 44 - #define init_stack (init_thread_union.stack) 45 - 46 44 #ifndef __ASSEMBLY__ 47 45 /* how to get the thread information struct from C */ 48 46 static inline struct thread_info *current_thread_info(void) ··· 55 57 return ti; 56 58 } 57 59 #endif 58 - 59 - #define init_thread_info (init_thread_union.thread_info) 60 60 61 61 /* entry.S relies on these definitions! 62 62 * bits 0-7 are tested at every exception exit
-3
arch/metag/include/asm/thread_info.h
··· 74 74 .addr_limit = KERNEL_DS, \ 75 75 } 76 76 77 - #define init_thread_info (init_thread_union.thread_info) 78 - #define init_stack (init_thread_union.stack) 79 - 80 77 /* how to get the current stack pointer from C */ 81 78 register unsigned long current_stack_pointer asm("A0StP") __used; 82 79
-3
arch/microblaze/include/asm/thread_info.h
··· 86 86 .addr_limit = KERNEL_DS, \ 87 87 } 88 88 89 - #define init_thread_info (init_thread_union.thread_info) 90 - #define init_stack (init_thread_union.stack) 91 - 92 89 /* how to get the thread information struct from C */ 93 90 static inline struct thread_info *current_thread_info(void) 94 91 {
-3
arch/mips/include/asm/thread_info.h
··· 49 49 .addr_limit = KERNEL_DS, \ 50 50 } 51 51 52 - #define init_thread_info (init_thread_union.thread_info) 53 - #define init_stack (init_thread_union.stack) 54 - 55 52 /* How to get the thread information struct from C. */ 56 53 register struct thread_info *__current_thread_info __asm__("$28"); 57 54
-2
arch/mn10300/include/asm/thread_info.h
··· 79 79 .addr_limit = KERNEL_DS, \ 80 80 } 81 81 82 - #define init_thread_info (init_thread_union.thread_info) 83 - #define init_stack (init_thread_union.stack) 84 82 #define init_uregs \ 85 83 ((struct pt_regs *) \ 86 84 ((unsigned long) init_stack + THREAD_SIZE - sizeof(struct pt_regs)))
-3
arch/nios2/include/asm/thread_info.h
··· 63 63 .addr_limit = KERNEL_DS, \ 64 64 } 65 65 66 - #define init_thread_info (init_thread_union.thread_info) 67 - #define init_stack (init_thread_union.stack) 68 - 69 66 /* how to get the thread information struct from C */ 70 67 static inline struct thread_info *current_thread_info(void) 71 68 {
-2
arch/openrisc/include/asm/processor.h
··· 84 84 void release_thread(struct task_struct *); 85 85 unsigned long get_wchan(struct task_struct *p); 86 86 87 - #define init_stack (init_thread_union.stack) 88 - 89 87 #define cpu_relax() barrier() 90 88 91 89 #endif /* __ASSEMBLY__ */
-2
arch/openrisc/include/asm/thread_info.h
··· 79 79 .ksp = 0, \ 80 80 } 81 81 82 - #define init_thread_info (init_thread_union.thread_info) 83 - 84 82 /* how to get the thread information struct from C */ 85 83 register struct thread_info *current_thread_info_reg asm("r10"); 86 84 #define current_thread_info() (current_thread_info_reg)
-3
arch/parisc/include/asm/thread_info.h
··· 25 25 .preempt_count = INIT_PREEMPT_COUNT, \ 26 26 } 27 27 28 - #define init_thread_info (init_thread_union.thread_info) 29 - #define init_stack (init_thread_union.stack) 30 - 31 28 /* how to get the thread information struct from C */ 32 29 #define current_thread_info() ((struct thread_info *)mfctl(30)) 33 30
-3
arch/powerpc/include/asm/thread_info.h
··· 58 58 .flags = 0, \ 59 59 } 60 60 61 - #define init_thread_info (init_thread_union.thread_info) 62 - #define init_stack (init_thread_union.stack) 63 - 64 61 #define THREAD_SIZE_ORDER (THREAD_SHIFT - PAGE_SHIFT) 65 62 66 63 /* how to get the thread information struct from C */
-2
arch/riscv/include/asm/thread_info.h
··· 64 64 .addr_limit = KERNEL_DS, \ 65 65 } 66 66 67 - #define init_stack (init_thread_union.stack) 68 - 69 67 #endif /* !__ASSEMBLY__ */ 70 68 71 69 /*
-2
arch/s390/include/asm/thread_info.h
··· 42 42 .flags = 0, \ 43 43 } 44 44 45 - #define init_stack (init_thread_union.stack) 46 - 47 45 void arch_release_task_struct(struct task_struct *tsk); 48 46 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src); 49 47
-3
arch/score/include/asm/thread_info.h
··· 58 58 .addr_limit = KERNEL_DS, \ 59 59 } 60 60 61 - #define init_thread_info (init_thread_union.thread_info) 62 - #define init_stack (init_thread_union.stack) 63 - 64 61 /* How to get the thread information struct from C. */ 65 62 register struct thread_info *__current_thread_info __asm__("r28"); 66 63 #define current_thread_info() __current_thread_info
-3
arch/sh/include/asm/thread_info.h
··· 63 63 .addr_limit = KERNEL_DS, \ 64 64 } 65 65 66 - #define init_thread_info (init_thread_union.thread_info) 67 - #define init_stack (init_thread_union.stack) 68 - 69 66 /* how to get the current stack pointer from C */ 70 67 register unsigned long current_stack_pointer asm("r15") __used; 71 68
-3
arch/sparc/include/asm/thread_info_32.h
··· 63 63 .preempt_count = INIT_PREEMPT_COUNT, \ 64 64 } 65 65 66 - #define init_thread_info (init_thread_union.thread_info) 67 - #define init_stack (init_thread_union.stack) 68 - 69 66 /* how to get the thread information struct from C */ 70 67 register struct thread_info *current_thread_info_reg asm("g6"); 71 68 #define current_thread_info() (current_thread_info_reg)
-3
arch/sparc/include/asm/thread_info_64.h
··· 120 120 .preempt_count = INIT_PREEMPT_COUNT, \ 121 121 } 122 122 123 - #define init_thread_info (init_thread_union.thread_info) 124 - #define init_stack (init_thread_union.stack) 125 - 126 123 /* how to get the thread information struct from C */ 127 124 register struct thread_info *current_thread_info_reg asm("g6"); 128 125 #define current_thread_info() (current_thread_info_reg)
-3
arch/tile/include/asm/thread_info.h
··· 59 59 .align_ctl = 0, \ 60 60 } 61 61 62 - #define init_thread_info (init_thread_union.thread_info) 63 - #define init_stack (init_thread_union.stack) 64 - 65 62 #endif /* !__ASSEMBLY__ */ 66 63 67 64 #if PAGE_SIZE < 8192
+4 -1
arch/um/include/asm/processor-generic.h
··· 58 58 { 59 59 } 60 60 61 - #define init_stack (init_thread_union.stack) 61 + static inline void mm_copy_segments(struct mm_struct *from_mm, 62 + struct mm_struct *new_mm) 63 + { 64 + } 62 65 63 66 /* 64 67 * User space process size: 3GB (default).
+3 -6
arch/um/include/asm/thread_info.h
··· 6 6 #ifndef __UM_THREAD_INFO_H 7 7 #define __UM_THREAD_INFO_H 8 8 9 + #define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER 10 + #define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) 11 + 9 12 #ifndef __ASSEMBLY__ 10 13 11 14 #include <asm/types.h> ··· 40 37 .real_thread = NULL, \ 41 38 } 42 39 43 - #define init_thread_info (init_thread_union.thread_info) 44 - #define init_stack (init_thread_union.stack) 45 - 46 - #define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE) 47 40 /* how to get the thread information struct from C */ 48 41 static inline struct thread_info *current_thread_info(void) 49 42 { ··· 51 52 ti = (struct thread_info *) (((unsigned long)p) & ~mask); 52 53 return ti; 53 54 } 54 - 55 - #define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER 56 55 57 56 #endif 58 57
+2
arch/um/include/asm/vmlinux.lds.h
··· 1 + #include <asm/thread_info.h> 2 + #include <asm-generic/vmlinux.lds.h>
+1 -2
arch/um/kernel/dyn.lds.S
··· 1 - /* SPDX-License-Identifier: GPL-2.0 */ 2 - #include <asm-generic/vmlinux.lds.h> 1 + #include <asm/vmlinux.lds.h> 3 2 #include <asm/page.h> 4 3 5 4 OUTPUT_FORMAT(ELF_FORMAT)
+1 -1
arch/um/kernel/um_arch.c
··· 54 54 55 55 union thread_union cpu0_irqstack 56 56 __attribute__((__section__(".data..init_irqstack"))) = 57 - { INIT_THREAD_INFO(init_task) }; 57 + { .thread_info = INIT_THREAD_INFO(init_task) }; 58 58 59 59 /* Changed in setup_arch, which is called in early boot */ 60 60 static char host_info[(__NEW_UTS_LEN + 1) * 5];
+1 -1
arch/um/kernel/uml.lds.S
··· 1 1 /* SPDX-License-Identifier: GPL-2.0 */ 2 - #include <asm-generic/vmlinux.lds.h> 2 + #include <asm/vmlinux.lds.h> 3 3 #include <asm/page.h> 4 4 5 5 OUTPUT_FORMAT(ELF_FORMAT)
-3
arch/unicore32/include/asm/thread_info.h
··· 87 87 .addr_limit = KERNEL_DS, \ 88 88 } 89 89 90 - #define init_thread_info (init_thread_union.thread_info) 91 - #define init_stack (init_thread_union.stack) 92 - 93 90 /* 94 91 * how to get the thread information struct from C 95 92 */
-2
arch/x86/include/asm/thread_info.h
··· 62 62 .flags = 0, \ 63 63 } 64 64 65 - #define init_stack (init_thread_union.stack) 66 - 67 65 #else /* !__ASSEMBLY__ */ 68 66 69 67 #include <asm/asm-offsets.h>
-3
arch/xtensa/include/asm/thread_info.h
··· 77 77 .addr_limit = KERNEL_DS, \ 78 78 } 79 79 80 - #define init_thread_info (init_thread_union.thread_info) 81 - #define init_stack (init_thread_union.stack) 82 - 83 80 /* how to get the thread information struct from C */ 84 81 static inline struct thread_info *current_thread_info(void) 85 82 {
+4
include/asm-generic/vmlinux.lds.h
··· 268 268 #define INIT_TASK_DATA(align) \ 269 269 . = ALIGN(align); \ 270 270 VMLINUX_SYMBOL(__start_init_task) = .; \ 271 + VMLINUX_SYMBOL(init_thread_union) = .; \ 272 + VMLINUX_SYMBOL(init_stack) = .; \ 271 273 *(.data..init_task) \ 274 + *(.data..init_thread_info) \ 275 + . = VMLINUX_SYMBOL(__start_init_task) + THREAD_SIZE; \ 272 276 VMLINUX_SYMBOL(__end_init_task) = .; 273 277 274 278 /*
+3
include/linux/init_task.h
··· 304 304 /* Attach to the init_task data structure for proper alignment */ 305 305 #define __init_task_data __attribute__((__section__(".data..init_task"))) 306 306 307 + /* Attach to the thread_info data structure for proper alignment */ 308 + #define __init_thread_info __attribute__((__section__(".data..init_thread_info"))) 309 + 307 310 308 311 #endif
+9
include/linux/sched.h
··· 1446 1446 void yield(void); 1447 1447 1448 1448 union thread_union { 1449 + #ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACK 1450 + struct task_struct task; 1451 + #endif 1449 1452 #ifndef CONFIG_THREAD_INFO_IN_TASK 1450 1453 struct thread_info thread_info; 1451 1454 #endif 1452 1455 unsigned long stack[THREAD_SIZE/sizeof(long)]; 1453 1456 }; 1457 + 1458 + #ifndef CONFIG_THREAD_INFO_IN_TASK 1459 + extern struct thread_info init_thread_info; 1460 + #endif 1461 + 1462 + extern unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)]; 1454 1463 1455 1464 #ifdef CONFIG_THREAD_INFO_IN_TASK 1456 1465 static inline struct thread_info *task_thread_info(struct task_struct *task)
-2
init/Makefile
··· 13 13 endif 14 14 obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o 15 15 16 - ifneq ($(CONFIG_ARCH_INIT_TASK),y) 17 16 obj-y += init_task.o 18 - endif 19 17 20 18 mounts-y := do_mounts.o 21 19 mounts-$(CONFIG_BLK_DEV_RAM) += do_mounts_rd.o
+6 -4
init/init_task.c
··· 17 17 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand); 18 18 19 19 /* Initial task structure */ 20 - struct task_struct init_task = INIT_TASK(init_task); 20 + struct task_struct init_task 21 + #ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK 22 + __init_task_data 23 + #endif 24 + = INIT_TASK(init_task); 21 25 EXPORT_SYMBOL(init_task); 22 26 23 27 /* 24 28 * Initial thread structure. Alignment of this is handled by a special 25 29 * linker map entry. 26 30 */ 27 - union thread_union init_thread_union __init_task_data = { 28 31 #ifndef CONFIG_THREAD_INFO_IN_TASK 29 - INIT_THREAD_INFO(init_task) 32 + struct thread_info init_thread_info __init_thread_info = INIT_THREAD_INFO(init_task); 30 33 #endif 31 - };