config ARCH_HAS_SET_MEMORY
        bool
 
-# Select if arch init_task initializer is different to init/init_task.c
-config ARCH_INIT_TASK
+# Select if arch init_task must go in the __init_task_data section
+config ARCH_TASK_STRUCT_ON_STACK
        bool
 
 # Select if arch has its private alloc_task_struct() function
 
        .preempt_count  = INIT_PREEMPT_COUNT,   \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* How to get the thread information struct from C.  */
 register struct thread_info *__current_thread_info __asm__("$8");
 #define current_thread_info()  __current_thread_info
 
        .addr_limit = KERNEL_DS,                \
 }
 
-#define init_thread_info    (init_thread_union.thread_info)
-#define init_stack          (init_thread_union.stack)
-
 static inline __attribute_const__ struct thread_info *current_thread_info(void)
 {
        register unsigned long sp asm("sp");
 
        .addr_limit     = KERNEL_DS,                                    \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /*
  * how to get the current stack pointer in C
  */
 
        .addr_limit     = KERNEL_DS,                                    \
 }
 
-#define init_stack             (init_thread_union.stack)
-
 #define thread_saved_pc(tsk)   \
        ((unsigned long)(tsk->thread.cpu_context.pc))
 #define thread_saved_sp(tsk)   \
 
        .cpu            = 0,                    \
        .preempt_count  = INIT_PREEMPT_COUNT,   \
 }
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
 
 /* Given a task stack pointer, you can find its corresponding
  * thread_info structure just by masking it to the THREAD_SIZE
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* get the thread information struct of current task */
 static inline __attribute__((const))
 struct thread_info *current_thread_info(void)
 
         /* Nothing needs to be done.  */
 }
 
-#define init_stack      (init_thread_union.stack)
-
 #define cpu_relax()     barrier()
 
 void default_idle(void);
 
        .addr_limit     = KERNEL_DS,                    \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 register struct thread_info *__current_thread_info asm("gr15");
 
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 
        .regs = NULL,                   \
 }
 
-#define init_thread_info        (init_thread_union.thread_info)
-#define init_stack              (init_thread_union.stack)
-
 /* Tacky preprocessor trickery */
 #define        qqstr(s) qstr(s)
 #define qstr(s) #s
 
        select ARCH_HAVE_NMI_SAFE_CMPXCHG
        select GENERIC_IOMAP
        select GENERIC_SMP_IDLE_THREAD
-       select ARCH_INIT_TASK
+       select ARCH_TASK_STRUCT_ON_STACK
        select ARCH_TASK_STRUCT_ALLOCATOR
        select ARCH_THREAD_STACK_ALLOCATOR
        select ARCH_CLOCKSOURCE_DATA
 
 endif
 
 KBUILD_CFLAGS += $(cflags-y)
-head-y := arch/ia64/kernel/head.o arch/ia64/kernel/init_task.o
+head-y := arch/ia64/kernel/head.o
 
 libs-y                         += arch/ia64/lib/
 core-y                         += arch/ia64/kernel/ arch/ia64/mm/
 
 #include <asm/processor.h>
 #include <asm/ptrace.h>
 
+#define THREAD_SIZE                    KERNEL_STACK_SIZE
+
 #ifndef __ASSEMBLY__
 
 /*
 #endif
 };
 
-#define THREAD_SIZE                    KERNEL_STACK_SIZE
-
 #define INIT_THREAD_INFO(tsk)                  \
 {                                              \
        .task           = &tsk,                 \
 
 CFLAGS_REMOVE_ftrace.o = -pg
 endif
 
-extra-y        := head.o init_task.o vmlinux.lds
+extra-y        := head.o vmlinux.lds
 
 obj-y := entry.o efi.o efi_stub.o gate-data.o fsys.o ia64_ksyms.o irq.o irq_ia64.o     \
         irq_lsapic.o ivt.o machvec.o pal.o patch.o process.o perfmon.o ptrace.o sal.o          \
 
+++ /dev/null
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This is where we statically allocate and initialize the initial
- * task.
- *
- * Copyright (C) 1999, 2002-2003 Hewlett-Packard Co
- *     David Mosberger-Tang <davidm@hpl.hp.com>
- */
-
-#include <linux/init.h>
-#include <linux/mm.h>
-#include <linux/fs.h>
-#include <linux/module.h>
-#include <linux/sched.h>
-#include <linux/init_task.h>
-#include <linux/mqueue.h>
-
-#include <linux/uaccess.h>
-#include <asm/pgtable.h>
-
-static struct signal_struct init_signals = INIT_SIGNALS(init_signals);
-static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
-/*
- * Initial task structure.
- *
- * We need to make sure that this is properly aligned due to the way process stacks are
- * handled. This is done by having a special ".data..init_task" section...
- */
-#define init_thread_info       init_task_mem.s.thread_info
-#define init_stack             init_task_mem.stack
-
-union {
-       struct {
-               struct task_struct task;
-               struct thread_info thread_info;
-       } s;
-       unsigned long stack[KERNEL_STACK_SIZE/sizeof (unsigned long)];
-} init_task_mem asm ("init_task") __init_task_data =
-       {{
-       .task =         INIT_TASK(init_task_mem.s.task),
-       .thread_info =  INIT_THREAD_INFO(init_task_mem.s.task)
-}};
-
-EXPORT_SYMBOL(init_task);
 
 #include <asm/cache.h>
 #include <asm/ptrace.h>
 #include <asm/pgtable.h>
+#include <asm/thread_info.h>
 
 #include <asm-generic/vmlinux.lds.h>
 
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 
        .preempt_count  = INIT_PREEMPT_COUNT,   \
 }
 
-#define init_stack             (init_thread_union.stack)
-
 #ifndef __ASSEMBLY__
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 }
 #endif
 
-#define init_thread_info       (init_thread_union.thread_info)
-
 /* entry.S relies on these definitions!
  * bits 0-7 are tested at every exception exit
  * bits 8-15 are also tested at syscall exit
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the current stack pointer from C */
 register unsigned long current_stack_pointer asm("A0StP") __used;
 
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* How to get the thread information struct from C.  */
 register struct thread_info *__current_thread_info __asm__("$28");
 
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
 #define init_uregs                                                     \
        ((struct pt_regs *)                                             \
         ((unsigned long) init_stack + THREAD_SIZE - sizeof(struct pt_regs)))
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 
 void release_thread(struct task_struct *);
 unsigned long get_wchan(struct task_struct *p);
 
-#define init_stack      (init_thread_union.stack)
-
 #define cpu_relax()     barrier()
 
 #endif /* __ASSEMBLY__ */
 
        .ksp            = 0,                            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-
 /* how to get the thread information struct from C */
 register struct thread_info *current_thread_info_reg asm("r10");
 #define current_thread_info()   (current_thread_info_reg)
 
        .preempt_count  = INIT_PREEMPT_COUNT,   \
 }
 
-#define init_thread_info        (init_thread_union.thread_info)
-#define init_stack              (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 #define current_thread_info()  ((struct thread_info *)mfctl(30))
 
 
        .flags =        0,                      \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 #define THREAD_SIZE_ORDER      (THREAD_SHIFT - PAGE_SHIFT)
 
 /* how to get the thread information struct from C */
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_stack             (init_thread_union.stack)
-
 #endif /* !__ASSEMBLY__ */
 
 /*
 
        .flags          = 0,                    \
 }
 
-#define init_stack             (init_thread_union.stack)
-
 void arch_release_task_struct(struct task_struct *tsk);
 int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src);
 
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* How to get the thread information struct from C. */
 register struct thread_info *__current_thread_info __asm__("r28");
 #define current_thread_info()  __current_thread_info
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the current stack pointer from C */
 register unsigned long current_stack_pointer asm("r15") __used;
 
 
        .preempt_count  =       INIT_PREEMPT_COUNT,     \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 register struct thread_info *current_thread_info_reg asm("g6");
 #define current_thread_info()   (current_thread_info_reg)
 
        .preempt_count  =       INIT_PREEMPT_COUNT,     \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 register struct thread_info *current_thread_info_reg asm("g6");
 #define current_thread_info()  (current_thread_info_reg)
 
        .align_ctl      = 0,                    \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 #endif /* !__ASSEMBLY__ */
 
 #if PAGE_SIZE < 8192
 
 {
 }
 
-#define init_stack     (init_thread_union.stack)
+static inline void mm_copy_segments(struct mm_struct *from_mm,
+                                   struct mm_struct *new_mm)
+{
+}
 
 /*
  * User space process size: 3GB (default).
 
 #ifndef __UM_THREAD_INFO_H
 #define __UM_THREAD_INFO_H
 
+#define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER
+#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
+
 #ifndef __ASSEMBLY__
 
 #include <asm/types.h>
        .real_thread = NULL,                    \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
-#define THREAD_SIZE ((1 << CONFIG_KERNEL_STACK_ORDER) * PAGE_SIZE)
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
        return ti;
 }
 
-#define THREAD_SIZE_ORDER CONFIG_KERNEL_STACK_ORDER
-
 #endif
 
 #define TIF_SYSCALL_TRACE      0       /* syscall trace active */
 
--- /dev/null
+#include <asm/thread_info.h>
+#include <asm-generic/vmlinux.lds.h>
 
-/* SPDX-License-Identifier: GPL-2.0 */
-#include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 #include <asm/page.h>
 
 OUTPUT_FORMAT(ELF_FORMAT)
 
 
 union thread_union cpu0_irqstack
        __attribute__((__section__(".data..init_irqstack"))) =
-               { INIT_THREAD_INFO(init_task) };
+               { .thread_info = INIT_THREAD_INFO(init_task) };
 
 /* Changed in setup_arch, which is called in early boot */
 static char host_info[(__NEW_UTS_LEN + 1) * 5];
 
 /* SPDX-License-Identifier: GPL-2.0 */
-#include <asm-generic/vmlinux.lds.h>
+#include <asm/vmlinux.lds.h>
 #include <asm/page.h>
 
 OUTPUT_FORMAT(ELF_FORMAT)
 
        .addr_limit     = KERNEL_DS,                                    \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /*
  * how to get the thread information struct from C
  */
 
        .flags          = 0,                    \
 }
 
-#define init_stack             (init_thread_union.stack)
-
 #else /* !__ASSEMBLY__ */
 
 #include <asm/asm-offsets.h>
 
        .addr_limit     = KERNEL_DS,            \
 }
 
-#define init_thread_info       (init_thread_union.thread_info)
-#define init_stack             (init_thread_union.stack)
-
 /* how to get the thread information struct from C */
 static inline struct thread_info *current_thread_info(void)
 {
 
 #define INIT_TASK_DATA(align)                                          \
        . = ALIGN(align);                                               \
        VMLINUX_SYMBOL(__start_init_task) = .;                          \
+       VMLINUX_SYMBOL(init_thread_union) = .;                          \
+       VMLINUX_SYMBOL(init_stack) = .;                                 \
        *(.data..init_task)                                             \
+       *(.data..init_thread_info)                                      \
+       . = VMLINUX_SYMBOL(__start_init_task) + THREAD_SIZE;            \
        VMLINUX_SYMBOL(__end_init_task) = .;
 
 /*
 
 /* Attach to the init_task data structure for proper alignment */
 #define __init_task_data __attribute__((__section__(".data..init_task")))
 
+/* Attach to the thread_info data structure for proper alignment */
+#define __init_thread_info __attribute__((__section__(".data..init_thread_info")))
+
 
 #endif
 
 void yield(void);
 
 union thread_union {
+#ifndef CONFIG_ARCH_TASK_STRUCT_ON_STACK
+       struct task_struct task;
+#endif
 #ifndef CONFIG_THREAD_INFO_IN_TASK
        struct thread_info thread_info;
 #endif
        unsigned long stack[THREAD_SIZE/sizeof(long)];
 };
 
+#ifndef CONFIG_THREAD_INFO_IN_TASK
+extern struct thread_info init_thread_info;
+#endif
+
+extern unsigned long init_stack[THREAD_SIZE / sizeof(unsigned long)];
+
 #ifdef CONFIG_THREAD_INFO_IN_TASK
 static inline struct thread_info *task_thread_info(struct task_struct *task)
 {
 
 endif
 obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
 
-ifneq ($(CONFIG_ARCH_INIT_TASK),y)
 obj-y                          += init_task.o
-endif
 
 mounts-y                       := do_mounts.o
 mounts-$(CONFIG_BLK_DEV_RAM)   += do_mounts_rd.o
 
 static struct sighand_struct init_sighand = INIT_SIGHAND(init_sighand);
 
 /* Initial task structure */
-struct task_struct init_task = INIT_TASK(init_task);
+struct task_struct init_task
+#ifdef CONFIG_ARCH_TASK_STRUCT_ON_STACK
+       __init_task_data
+#endif
+       = INIT_TASK(init_task);
 EXPORT_SYMBOL(init_task);
 
 /*
  * Initial thread structure. Alignment of this is handled by a special
  * linker map entry.
  */
-union thread_union init_thread_union __init_task_data = {
 #ifndef CONFIG_THREAD_INFO_IN_TASK
-       INIT_THREAD_INFO(init_task)
+struct thread_info init_thread_info __init_thread_info = INIT_THREAD_INFO(init_task);
 #endif
-};