Pull fork cleanups from Christian Brauner: "This is cleanup series from when we reworked a chunk of the process creation paths in the kernel and switched to struct {kernel_}clone_args. High-level this does two main things: - Remove the double export of both do_fork() and _do_fork() where do_fork() used the incosistent legacy clone calling convention. Now we only export _do_fork() which is based on struct kernel_clone_args. - Remove the copy_thread_tls()/copy_thread() split making the architecture specific HAVE_COYP_THREAD_TLS config option obsolete. This switches all remaining architectures to select HAVE_COPY_THREAD_TLS and thus to the copy_thread_tls() calling convention. The current split makes the process creation codepaths more convoluted than they need to be. Each architecture has their own copy_thread() function unless it selects HAVE_COPY_THREAD_TLS then it has a copy_thread_tls() function. The split is not needed anymore nowadays, all architectures support CLONE_SETTLS but quite a few of them never bothered to select HAVE_COPY_THREAD_TLS and instead simply continued to use copy_thread() and use the old calling convention. Removing this split cleans up the process creation codepaths and paves the way for implementing clone3() on such architectures since it requires the copy_thread_tls() calling convention. After having made each architectures support copy_thread_tls() this series simply renames that function back to copy_thread(). It also switches all architectures that call do_fork() directly over to _do_fork() and the struct kernel_clone_args calling convention. This is a corollary of switching the architectures that did not yet support it over to copy_thread_tls() since do_fork() is conditional on not supporting copy_thread_tls() (Mostly because it lacks a separate argument for tls which is trivial to fix but there's no need for this function to exist.). The do_fork() removal is in itself already useful as it allows to to remove the export of both do_fork() and _do_fork() we currently have in favor of only _do_fork(). This has already been discussed back when we added clone3(). The legacy clone() calling convention is - as is probably well-known - somewhat odd: # # ABI hall of shame # config CLONE_BACKWARDS config CLONE_BACKWARDS2 config CLONE_BACKWARDS3 that is aggravated by the fact that some architectures such as sparc follow the CLONE_BACKWARDSx calling convention but don't really select the corresponding config option since they call do_fork() directly. So do_fork() enforces a somewhat arbitrary calling convention in the first place that doesn't really help the individual architectures that deviate from it. They can thus simply be switched to _do_fork() enforcing a single calling convention. (I really hope that any new architectures will __not__ try to implement their own calling conventions...) Most architectures already have made a similar switch (m68k comes to mind). Overall this removes more code than it adds even with a good portion of added comments. It simplifies a chunk of arch specific assembly either by moving the code into C or by simply rewriting the assembly. Architectures that have been touched in non-trivial ways have all been actually boot and stress tested: sparc and ia64 have been tested with Debian 9 images. They are the two architectures which have been touched the most. All non-trivial changes to architectures have seen acks from the relevant maintainers. nios2 with a custom built buildroot image. h8300 I couldn't get something bootable to test on but the changes have been fairly automatic and I'm sure we'll hear people yell if I broke something there. All other architectures that have been touched in trivial ways have been compile tested for each single patch of the series via git rebase -x "make ..." v5.8-rc2. arm{64} and x86{_64} have been boot tested even though they have just been trivially touched (removal of the HAVE_COPY_THREAD_TLS macro from their Kconfig) because well they are basically "core architectures" and since it is trivial to get your hands on a useable image" * tag 'fork-v5.9' of git://git.kernel.org/pub/scm/linux/kernel/git/brauner/linux: arch: rename copy_thread_tls() back to copy_thread() arch: remove HAVE_COPY_THREAD_TLS unicore: switch to copy_thread_tls() sh: switch to copy_thread_tls() nds32: switch to copy_thread_tls() microblaze: switch to copy_thread_tls() hexagon: switch to copy_thread_tls() c6x: switch to copy_thread_tls() alpha: switch to copy_thread_tls() fork: remove do_fork() h8300: select HAVE_COPY_THREAD_TLS, switch to kernel_clone_args nios2: enable HAVE_COPY_THREAD_TLS, switch to kernel_clone_args ia64: enable HAVE_COPY_THREAD_TLS, switch to kernel_clone_args sparc: unconditionally enable HAVE_COPY_THREAD_TLS sparc: share process creation helpers between sparc and sparc64 sparc64: enable HAVE_COPY_THREAD_TLS fork: fold legacy_clone_args_valid() into _do_fork()
Unified · Split
| @@ -754,13 +754,6 @@ config ARCH_WANT_DEFAULT_TOPDOWN_MMAP_LAYOUT · 753 unmodified lines | |||
| 754 | depends on MMU | 754 | depends on MMU |
| 755 | select ARCH_HAS_ELF_RANDOMIZE | 755 | select ARCH_HAS_ELF_RANDOMIZE |
| 756 | 756 | ||
| 757 | config HAVE_COPY_THREAD_TLS | ||
| 758 | bool | ||
| 759 | help | ||
| 760 | Architecture provides copy_thread_tls to accept tls argument via | ||
| 761 | normal C parameter passing, rather than extracting the syscall | ||
| 762 | argument from pt_regs. | ||
| 763 | |||
| 764 | config HAVE_STACK_VALIDATION | 757 | config HAVE_STACK_VALIDATION |
| 765 | bool | 758 | bool |
| 766 | help | 759 | help |
| @@ -233,10 +233,9 @@ release_thread(struct task_struct *dead_task) · 232 unmodified lines | |||
| 233 | /* | 233 | /* |
| 234 | * Copy architecture-specific thread state | 234 | * Copy architecture-specific thread state |
| 235 | */ | 235 | */ |
| 236 | int | 236 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 237 | copy_thread(unsigned long clone_flags, unsigned long usp, | 237 | unsigned long kthread_arg, struct task_struct *p, |
| 238 | unsigned long kthread_arg, | 238 | unsigned long tls) |
| 239 | struct task_struct *p) | ||
| 240 | { | 239 | { |
| 241 | extern void ret_from_fork(void); | 240 | extern void ret_from_fork(void); |
| 242 | extern void ret_from_kernel_thread(void); | 241 | extern void ret_from_kernel_thread(void); |
| @@ -267,7 +266,7 @@ copy_thread(unsigned long clone_flags, unsigned long usp, · 24 unmodified lines | |||
| 267 | required for proper operation in the case of a threaded | 266 | required for proper operation in the case of a threaded |
| 268 | application calling fork. */ | 267 | application calling fork. */ |
| 269 | if (clone_flags & CLONE_SETTLS) | 268 | if (clone_flags & CLONE_SETTLS) |
| 270 | childti->pcb.unique = regs->r20; | 269 | childti->pcb.unique = tls; |
| 271 | else | 270 | else |
| 272 | regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */ | 271 | regs->r20 = 0; /* OSF/1 has some strange fork() semantics. */ |
| 273 | childti->pcb.usp = usp ?: rdusp(); | 272 | childti->pcb.usp = usp ?: rdusp(); |
| @@ -29,7 +29,6 @@ config ARC · 28 unmodified lines | |||
| 29 | select GENERIC_SMP_IDLE_THREAD | 29 | select GENERIC_SMP_IDLE_THREAD |
| 30 | select HAVE_ARCH_KGDB | 30 | select HAVE_ARCH_KGDB |
| 31 | select HAVE_ARCH_TRACEHOOK | 31 | select HAVE_ARCH_TRACEHOOK |
| 32 | select HAVE_COPY_THREAD_TLS | ||
| 33 | select HAVE_DEBUG_STACKOVERFLOW | 32 | select HAVE_DEBUG_STACKOVERFLOW |
| 34 | select HAVE_DEBUG_KMEMLEAK | 33 | select HAVE_DEBUG_KMEMLEAK |
| 35 | select HAVE_FUTEX_CMPXCHG if FUTEX | 34 | select HAVE_FUTEX_CMPXCHG if FUTEX |
| @@ -173,8 +173,9 @@ asmlinkage void ret_from_fork(void); · 172 unmodified lines | |||
| 173 | * | user_r25 | | 173 | * | user_r25 | |
| 174 | * ------------------ <===== END of PAGE | 174 | * ------------------ <===== END of PAGE |
| 175 | */ | 175 | */ |
| 176 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 176 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 177 | unsigned long kthread_arg, struct task_struct *p, unsigned long tls) | 177 | unsigned long kthread_arg, struct task_struct *p, |
| 178 | unsigned long tls) | ||
| 178 | { | 179 | { |
| 179 | struct pt_regs *c_regs; /* child's pt_regs */ | 180 | struct pt_regs *c_regs; /* child's pt_regs */ |
| 180 | unsigned long *childksp; /* to unwind out of __switch_to() */ | 181 | unsigned long *childksp; /* to unwind out of __switch_to() */ |
| @@ -72,7 +72,6 @@ config ARM · 71 unmodified lines | |||
| 72 | select HAVE_ARM_SMCCC if CPU_V7 | 72 | select HAVE_ARM_SMCCC if CPU_V7 |
| 73 | select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32 | 73 | select HAVE_EBPF_JIT if !CPU_ENDIAN_BE32 |
| 74 | select HAVE_CONTEXT_TRACKING | 74 | select HAVE_CONTEXT_TRACKING |
| 75 | select HAVE_COPY_THREAD_TLS | ||
| 76 | select HAVE_C_RECORDMCOUNT | 75 | select HAVE_C_RECORDMCOUNT |
| 77 | select HAVE_DEBUG_KMEMLEAK if !XIP_KERNEL | 76 | select HAVE_DEBUG_KMEMLEAK if !XIP_KERNEL |
| 78 | select HAVE_DMA_CONTIGUOUS if MMU | 77 | select HAVE_DMA_CONTIGUOUS if MMU |
| @@ -225,9 +225,8 @@ void release_thread(struct task_struct *dead_task) · 224 unmodified lines | |||
| 225 | 225 | ||
| 226 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 226 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
| 227 | 227 | ||
| 228 | int | 228 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, |
| 229 | copy_thread_tls(unsigned long clone_flags, unsigned long stack_start, | 229 | unsigned long stk_sz, struct task_struct *p, unsigned long tls) |
| 230 | unsigned long stk_sz, struct task_struct *p, unsigned long tls) | ||
| 231 | { | 230 | { |
| 232 | struct thread_info *thread = task_thread_info(p); | 231 | struct thread_info *thread = task_thread_info(p); |
| 233 | struct pt_regs *childregs = task_pt_regs(p); | 232 | struct pt_regs *childregs = task_pt_regs(p); |
| @@ -149,7 +149,6 @@ config ARM64 · 148 unmodified lines | |||
| 149 | select HAVE_CMPXCHG_DOUBLE | 149 | select HAVE_CMPXCHG_DOUBLE |
| 150 | select HAVE_CMPXCHG_LOCAL | 150 | select HAVE_CMPXCHG_LOCAL |
| 151 | select HAVE_CONTEXT_TRACKING | 151 | select HAVE_CONTEXT_TRACKING |
| 152 | select HAVE_COPY_THREAD_TLS | ||
| 153 | select HAVE_DEBUG_BUGVERBOSE | 152 | select HAVE_DEBUG_BUGVERBOSE |
| 154 | select HAVE_DEBUG_KMEMLEAK | 153 | select HAVE_DEBUG_KMEMLEAK |
| 155 | select HAVE_DMA_CONTIGUOUS | 154 | select HAVE_DMA_CONTIGUOUS |
| @@ -375,7 +375,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) · 374 unmodified lines | |||
| 375 | 375 | ||
| 376 | asmlinkage void ret_from_fork(void) asm("ret_from_fork"); | 376 | asmlinkage void ret_from_fork(void) asm("ret_from_fork"); |
| 377 | 377 | ||
| 378 | int copy_thread_tls(unsigned long clone_flags, unsigned long stack_start, | 378 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, |
| 379 | unsigned long stk_sz, struct task_struct *p, unsigned long tls) | 379 | unsigned long stk_sz, struct task_struct *p, unsigned long tls) |
| 380 | { | 380 | { |
| 381 | struct pt_regs *childregs = task_pt_regs(p); | 381 | struct pt_regs *childregs = task_pt_regs(p); |
| @@ -105,8 +105,8 @@ void start_thread(struct pt_regs *regs, unsigned int pc, unsigned long usp) · 104 unmodified lines | |||
| 105 | * Copy a new thread context in its stack. | 105 | * Copy a new thread context in its stack. |
| 106 | */ | 106 | */ |
| 107 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 107 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 108 | unsigned long ustk_size, | 108 | unsigned long ustk_size, struct task_struct *p, |
| 109 | struct task_struct *p) | 109 | unsigned long tls) |
| 110 | { | 110 | { |
| 111 | struct pt_regs *childregs; | 111 | struct pt_regs *childregs; |
| 112 | 112 | ||
| @@ -38,7 +38,6 @@ config CSKY · 37 unmodified lines | |||
| 38 | select GX6605S_TIMER if CPU_CK610 | 38 | select GX6605S_TIMER if CPU_CK610 |
| 39 | select HAVE_ARCH_TRACEHOOK | 39 | select HAVE_ARCH_TRACEHOOK |
| 40 | select HAVE_ARCH_AUDITSYSCALL | 40 | select HAVE_ARCH_AUDITSYSCALL |
| 41 | select HAVE_COPY_THREAD_TLS | ||
| 42 | select HAVE_DEBUG_BUGVERBOSE | 41 | select HAVE_DEBUG_BUGVERBOSE |
| 43 | select HAVE_DYNAMIC_FTRACE | 42 | select HAVE_DYNAMIC_FTRACE |
| 44 | select HAVE_DYNAMIC_FTRACE_WITH_REGS | 43 | select HAVE_DYNAMIC_FTRACE_WITH_REGS |
| @@ -40,7 +40,7 @@ unsigned long thread_saved_pc(struct task_struct *tsk) · 39 unmodified lines | |||
| 40 | return sw->r15; | 40 | return sw->r15; |
| 41 | } | 41 | } |
| 42 | 42 | ||
| 43 | int copy_thread_tls(unsigned long clone_flags, | 43 | int copy_thread(unsigned long clone_flags, |
| 44 | unsigned long usp, | 44 | unsigned long usp, |
| 45 | unsigned long kthread_arg, | 45 | unsigned long kthread_arg, |
| 46 | struct task_struct *p, | 46 | struct task_struct *p, |
| @@ -105,9 +105,8 @@ void flush_thread(void) · 104 unmodified lines | |||
| 105 | { | 105 | { |
| 106 | } | 106 | } |
| 107 | 107 | ||
| 108 | int copy_thread(unsigned long clone_flags, | 108 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 109 | unsigned long usp, unsigned long topstk, | 109 | unsigned long topstk, struct task_struct *p, unsigned long tls) |
| 110 | struct task_struct *p) | ||
| 111 | { | 110 | { |
| 112 | struct pt_regs *childregs; | 111 | struct pt_regs *childregs; |
| 113 | 112 | ||
| @@ -159,11 +158,19 @@ asmlinkage int sys_clone(unsigned long __user *args) · 45 unmodified lines | |||
| 159 | unsigned long newsp; | 158 | unsigned long newsp; |
| 160 | uintptr_t parent_tidptr; | 159 | uintptr_t parent_tidptr; |
| 161 | uintptr_t child_tidptr; | 160 | uintptr_t child_tidptr; |
| 161 | struct kernel_clone_args kargs = {}; | ||
| 162 | 162 | ||
| 163 | get_user(clone_flags, &args[0]); | 163 | get_user(clone_flags, &args[0]); |
| 164 | get_user(newsp, &args[1]); | 164 | get_user(newsp, &args[1]); |
| 165 | get_user(parent_tidptr, &args[2]); | 165 | get_user(parent_tidptr, &args[2]); |
| 166 | get_user(child_tidptr, &args[3]); | 166 | get_user(child_tidptr, &args[3]); |
| 167 | return do_fork(clone_flags, newsp, 0, | 167 | |
| 168 | (int __user *)parent_tidptr, (int __user *)child_tidptr); | 168 | kargs.flags = (lower_32_bits(clone_flags) & ~CSIGNAL); |
| 169 | kargs.pidfd = (int __user *)parent_tidptr; | ||
| 170 | kargs.child_tid = (int __user *)child_tidptr; | ||
| 171 | kargs.parent_tid = (int __user *)parent_tidptr; | ||
| 172 | kargs.exit_signal = (lower_32_bits(clone_flags) & CSIGNAL); | ||
| 173 | kargs.stack = newsp; | ||
| 174 | |||
| 175 | return _do_fork(&kargs); | ||
| 169 | } | 176 | } |
| @@ -50,8 +50,8 @@ void arch_cpu_idle(void) · 49 unmodified lines | |||
| 50 | /* | 50 | /* |
| 51 | * Copy architecture-specific thread state | 51 | * Copy architecture-specific thread state |
| 52 | */ | 52 | */ |
| 53 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 53 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 54 | unsigned long arg, struct task_struct *p) | 54 | struct task_struct *p, unsigned long tls) |
| 55 | { | 55 | { |
| 56 | struct thread_info *ti = task_thread_info(p); | 56 | struct thread_info *ti = task_thread_info(p); |
| 57 | struct hexagon_switch_stack *ss; | 57 | struct hexagon_switch_stack *ss; |
| @@ -100,7 +100,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, · 42 unmodified lines | |||
| 100 | * ugp is used to provide TLS support. | 100 | * ugp is used to provide TLS support. |
| 101 | */ | 101 | */ |
| 102 | if (clone_flags & CLONE_SETTLS) | 102 | if (clone_flags & CLONE_SETTLS) |
| 103 | childregs->ugp = childregs->r04; | 103 | childregs->ugp = tls; |
| 104 | 104 | ||
| 105 | /* | 105 | /* |
| 106 | * Parent sees new pid -- not necessary, not even possible at | 106 | * Parent sees new pid -- not necessary, not even possible at |
| @@ -112,19 +112,16 @@ GLOBAL_ENTRY(sys_clone2) · 111 unmodified lines | |||
| 112 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | 112 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) |
| 113 | alloc r16=ar.pfs,8,2,6,0 | 113 | alloc r16=ar.pfs,8,2,6,0 |
| 114 | DO_SAVE_SWITCH_STACK | 114 | DO_SAVE_SWITCH_STACK |
| 115 | adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp | ||
| 116 | mov loc0=rp | 115 | mov loc0=rp |
| 117 | mov loc1=r16 // save ar.pfs across do_fork | 116 | mov loc1=r16 // save ar.pfs across ia64_clone |
| 118 | .body | 117 | .body |
| 118 | mov out0=in0 | ||
| 119 | mov out1=in1 | 119 | mov out1=in1 |
| 120 | mov out2=in2 | 120 | mov out2=in2 |
| 121 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT | 121 | mov out3=in3 |
| 122 | mov out3=in3 // parent_tidptr: valid only w/CLONE_PARENT_SETTID | 122 | mov out4=in4 |
| 123 | ;; | 123 | mov out5=in5 |
| 124 | (p6) st8 [r2]=in5 // store TLS in r16 for copy_thread() | 124 | br.call.sptk.many rp=ia64_clone |
| 125 | mov out4=in4 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID | ||
| 126 | mov out0=in0 // out0 = clone_flags | ||
| 127 | br.call.sptk.many rp=do_fork | ||
| 128 | .ret1: .restore sp | 125 | .ret1: .restore sp |
| 129 | adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack | 126 | adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack |
| 130 | mov ar.pfs=loc1 | 127 | mov ar.pfs=loc1 |
| @@ -143,19 +140,16 @@ GLOBAL_ENTRY(sys_clone) · 12 unmodified lines | |||
| 143 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) | 140 | .prologue ASM_UNW_PRLG_RP|ASM_UNW_PRLG_PFS, ASM_UNW_PRLG_GRSAVE(8) |
| 144 | alloc r16=ar.pfs,8,2,6,0 | 141 | alloc r16=ar.pfs,8,2,6,0 |
| 145 | DO_SAVE_SWITCH_STACK | 142 | DO_SAVE_SWITCH_STACK |
| 146 | adds r2=PT(R16)+IA64_SWITCH_STACK_SIZE+16,sp | ||
| 147 | mov loc0=rp | 143 | mov loc0=rp |
| 148 | mov loc1=r16 // save ar.pfs across do_fork | 144 | mov loc1=r16 // save ar.pfs across ia64_clone |
| 149 | .body | 145 | .body |
| 146 | mov out0=in0 | ||
| 150 | mov out1=in1 | 147 | mov out1=in1 |
| 151 | mov out2=16 // stacksize (compensates for 16-byte scratch area) | 148 | mov out2=16 // stacksize (compensates for 16-byte scratch area) |
| 152 | tbit.nz p6,p0=in0,CLONE_SETTLS_BIT | 149 | mov out3=in3 |
| 153 | mov out3=in2 // parent_tidptr: valid only w/CLONE_PARENT_SETTID | 150 | mov out4=in4 |
| 154 | ;; | 151 | mov out5=in5 |
| 155 | (p6) st8 [r2]=in4 // store TLS in r13 (tp) | 152 | br.call.sptk.many rp=ia64_clone |
| 156 | mov out4=in3 // child_tidptr: valid only w/CLONE_CHILD_SETTID or CLONE_CHILD_CLEARTID | ||
| 157 | mov out0=in0 // out0 = clone_flags | ||
| 158 | br.call.sptk.many rp=do_fork | ||
| 159 | .ret2: .restore sp | 153 | .ret2: .restore sp |
| 160 | adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack | 154 | adds sp=IA64_SWITCH_STACK_SIZE,sp // pop the switch stack |
| 161 | mov ar.pfs=loc1 | 155 | mov ar.pfs=loc1 |
| @@ -590,7 +584,7 @@ GLOBAL_ENTRY(ia64_ret_from_clone) · 428 unmodified lines | |||
| 590 | nop.i 0 | 584 | nop.i 0 |
| 591 | /* | 585 | /* |
| 592 | * We need to call schedule_tail() to complete the scheduling process. | 586 | * We need to call schedule_tail() to complete the scheduling process. |
| 593 | * Called by ia64_switch_to() after do_fork()->copy_thread(). r8 contains the | 587 | * Called by ia64_switch_to() after ia64_clone()->copy_thread(). r8 contains the |
| 594 | * address of the previously executing task. | 588 | * address of the previously executing task. |
| 595 | */ | 589 | */ |
| 596 | br.call.sptk.many rp=ia64_invoke_schedule_tail | 590 | br.call.sptk.many rp=ia64_invoke_schedule_tail |
| @@ -296,7 +296,7 @@ ia64_load_extra (struct task_struct *task) · 295 unmodified lines | |||
| 296 | pfm_load_regs(task); | 296 | pfm_load_regs(task); |
| 297 | 297 | ||
| 298 | info = __this_cpu_read(pfm_syst_info); | 298 | info = __this_cpu_read(pfm_syst_info); |
| 299 | if (info & PFM_CPUINFO_SYST_WIDE) | 299 | if (info & PFM_CPUINFO_SYST_WIDE) |
| 300 | pfm_syst_wide_update_task(task, info, 1); | 300 | pfm_syst_wide_update_task(task, info, 1); |
| 301 | #endif | 301 | #endif |
| 302 | } | 302 | } |
| @@ -310,7 +310,7 @@ ia64_load_extra (struct task_struct *task) · 7 unmodified lines | |||
| 310 | * | 310 | * |
| 311 | * <clone syscall> <some kernel call frames> | 311 | * <clone syscall> <some kernel call frames> |
| 312 | * sys_clone : | 312 | * sys_clone : |
| 313 | * do_fork do_fork | 313 | * _do_fork _do_fork |
| 314 | * copy_thread copy_thread | 314 | * copy_thread copy_thread |
| 315 | * | 315 | * |
| 316 | * This means that the stack layout is as follows: | 316 | * This means that the stack layout is as follows: |
| @@ -333,9 +333,8 @@ ia64_load_extra (struct task_struct *task) · 16 unmodified lines | |||
| 333 | * so there is nothing to worry about. | 333 | * so there is nothing to worry about. |
| 334 | */ | 334 | */ |
| 335 | int | 335 | int |
| 336 | copy_thread(unsigned long clone_flags, | 336 | copy_thread(unsigned long clone_flags, unsigned long user_stack_base, |
| 337 | unsigned long user_stack_base, unsigned long user_stack_size, | 337 | unsigned long user_stack_size, struct task_struct *p, unsigned long tls) |
| 338 | struct task_struct *p) | ||
| 339 | { | 338 | { |
| 340 | extern char ia64_ret_from_clone; | 339 | extern char ia64_ret_from_clone; |
| 341 | struct switch_stack *child_stack, *stack; | 340 | struct switch_stack *child_stack, *stack; |
| @@ -416,7 +415,7 @@ copy_thread(unsigned long clone_flags, · 74 unmodified lines | |||
| 416 | rbs_size = stack->ar_bspstore - rbs; | 415 | rbs_size = stack->ar_bspstore - rbs; |
| 417 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); | 416 | memcpy((void *) child_rbs, (void *) rbs, rbs_size); |
| 418 | if (clone_flags & CLONE_SETTLS) | 417 | if (clone_flags & CLONE_SETTLS) |
| 419 | child_ptregs->r13 = regs->r16; /* see sys_clone2() in entry.S */ | 418 | child_ptregs->r13 = tls; |
| 420 | if (user_stack_base) { | 419 | if (user_stack_base) { |
| 421 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; | 420 | child_ptregs->r12 = user_stack_base + user_stack_size - 16; |
| 422 | child_ptregs->ar_bspstore = user_stack_base; | 421 | child_ptregs->ar_bspstore = user_stack_base; |
| @@ -441,6 +440,24 @@ copy_thread(unsigned long clone_flags, · 18 unmodified lines | |||
| 441 | return retval; | 440 | return retval; |
| 442 | } | 441 | } |
| 443 | 442 | ||
| 443 | asmlinkage long ia64_clone(unsigned long clone_flags, unsigned long stack_start, | ||
| 444 | unsigned long stack_size, unsigned long parent_tidptr, | ||
| 445 | unsigned long child_tidptr, unsigned long tls) | ||
| 446 | { | ||
| 447 | struct kernel_clone_args args = { | ||
| 448 | .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), | ||
| 449 | .pidfd = (int __user *)parent_tidptr, | ||
| 450 | .child_tid = (int __user *)child_tidptr, | ||
| 451 | .parent_tid = (int __user *)parent_tidptr, | ||
| 452 | .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), | ||
| 453 | .stack = stack_start, | ||
| 454 | .stack_size = stack_size, | ||
| 455 | .tls = tls, | ||
| 456 | }; | ||
| 457 | |||
| 458 | return _do_fork(&args); | ||
| 459 | } | ||
| 460 | |||
| 444 | static void | 461 | static void |
| 445 | do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) | 462 | do_copy_task_regs (struct task_struct *task, struct unw_frame_info *info, void *arg) |
| 446 | { | 463 | { |
| @@ -14,7 +14,6 @@ config M68K · 13 unmodified lines | |||
| 14 | select HAVE_AOUT if MMU | 14 | select HAVE_AOUT if MMU |
| 15 | select HAVE_ASM_MODVERSIONS | 15 | select HAVE_ASM_MODVERSIONS |
| 16 | select HAVE_DEBUG_BUGVERBOSE | 16 | select HAVE_DEBUG_BUGVERBOSE |
| 17 | select HAVE_COPY_THREAD_TLS | ||
| 18 | select GENERIC_IRQ_SHOW | 17 | select GENERIC_IRQ_SHOW |
| 19 | select GENERIC_ATOMIC64 | 18 | select GENERIC_ATOMIC64 |
| 20 | select HAVE_UID16 | 19 | select HAVE_UID16 |
| @@ -125,9 +125,6 @@ asmlinkage int m68k_clone(struct pt_regs *regs) · 124 unmodified lines | |||
| 125 | .tls = regs->d5, | 125 | .tls = regs->d5, |
| 126 | }; | 126 | }; |
| 127 | 127 | ||
| 128 | if (!legacy_clone_args_valid(&args)) | ||
| 129 | return -EINVAL; | ||
| 130 | |||
| 131 | return _do_fork(&args); | 128 | return _do_fork(&args); |
| 132 | } | 129 | } |
| 133 | 130 | ||
| @@ -141,9 +138,8 @@ asmlinkage int m68k_clone3(struct pt_regs *regs) · 7 unmodified lines | |||
| 141 | return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); | 138 | return sys_clone3((struct clone_args __user *)regs->d1, regs->d2); |
| 142 | } | 139 | } |
| 143 | 140 | ||
| 144 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 141 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 145 | unsigned long arg, struct task_struct *p, | 142 | struct task_struct *p, unsigned long tls) |
| 146 | unsigned long tls) | ||
| 147 | { | 143 | { |
| 148 | struct fork_frame { | 144 | struct fork_frame { |
| 149 | struct switch_stack sw; | 145 | struct switch_stack sw; |
| @@ -54,8 +54,8 @@ void flush_thread(void) · 53 unmodified lines | |||
| 54 | { | 54 | { |
| 55 | } | 55 | } |
| 56 | 56 | ||
| 57 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 57 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 58 | unsigned long arg, struct task_struct *p) | 58 | struct task_struct *p, unsigned long tls) |
| 59 | { | 59 | { |
| 60 | struct pt_regs *childregs = task_pt_regs(p); | 60 | struct pt_regs *childregs = task_pt_regs(p); |
| 61 | struct thread_info *ti = task_thread_info(p); | 61 | struct thread_info *ti = task_thread_info(p); |
| @@ -114,7 +114,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, · 52 unmodified lines | |||
| 114 | * which contains TLS area | 114 | * which contains TLS area |
| 115 | */ | 115 | */ |
| 116 | if (clone_flags & CLONE_SETTLS) | 116 | if (clone_flags & CLONE_SETTLS) |
| 117 | childregs->r21 = childregs->r10; | 117 | childregs->r21 = tls; |
| 118 | 118 | ||
| 119 | return 0; | 119 | return 0; |
| 120 | } | 120 | } |
| @@ -51,7 +51,6 @@ config MIPS · 50 unmodified lines | |||
| 51 | select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS | 51 | select HAVE_CBPF_JIT if !64BIT && !CPU_MICROMIPS |
| 52 | select HAVE_CONTEXT_TRACKING | 52 | select HAVE_CONTEXT_TRACKING |
| 53 | select HAVE_TIF_NOHZ | 53 | select HAVE_TIF_NOHZ |
| 54 | select HAVE_COPY_THREAD_TLS | ||
| 55 | select HAVE_C_RECORDMCOUNT | 54 | select HAVE_C_RECORDMCOUNT |
| 56 | select HAVE_DEBUG_KMEMLEAK | 55 | select HAVE_DEBUG_KMEMLEAK |
| 57 | select HAVE_DEBUG_STACKOVERFLOW | 56 | select HAVE_DEBUG_STACKOVERFLOW |
| @@ -119,8 +119,9 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) · 118 unmodified lines | |||
| 119 | /* | 119 | /* |
| 120 | * Copy architecture-specific thread state | 120 | * Copy architecture-specific thread state |
| 121 | */ | 121 | */ |
| 122 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 122 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 123 | unsigned long kthread_arg, struct task_struct *p, unsigned long tls) | 123 | unsigned long kthread_arg, struct task_struct *p, |
| 124 | unsigned long tls) | ||
| 124 | { | 125 | { |
| 125 | struct thread_info *ti = task_thread_info(p); | 126 | struct thread_info *ti = task_thread_info(p); |
| 126 | struct pt_regs *childregs, *regs = current_pt_regs(); | 127 | struct pt_regs *childregs, *regs = current_pt_regs(); |
| @@ -150,7 +150,7 @@ DEFINE_PER_CPU(struct task_struct *, __entry_task); · 149 unmodified lines | |||
| 150 | 150 | ||
| 151 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); | 151 | asmlinkage void ret_from_fork(void) __asm__("ret_from_fork"); |
| 152 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, | 152 | int copy_thread(unsigned long clone_flags, unsigned long stack_start, |
| 153 | unsigned long stk_sz, struct task_struct *p) | 153 | unsigned long stk_sz, struct task_struct *p, unsigned long tls) |
| 154 | { | 154 | { |
| 155 | struct pt_regs *childregs = task_pt_regs(p); | 155 | struct pt_regs *childregs = task_pt_regs(p); |
| 156 | 156 | ||
| @@ -170,7 +170,7 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start, · 13 unmodified lines | |||
| 170 | childregs->uregs[0] = 0; | 170 | childregs->uregs[0] = 0; |
| 171 | childregs->osp = 0; | 171 | childregs->osp = 0; |
| 172 | if (clone_flags & CLONE_SETTLS) | 172 | if (clone_flags & CLONE_SETTLS) |
| 173 | childregs->uregs[25] = childregs->uregs[3]; | 173 | childregs->uregs[25] = tls; |
| 174 | } | 174 | } |
| 175 | /* cpu context switching */ | 175 | /* cpu context switching */ |
| 176 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; | 176 | p->thread.cpu_context.pc = (unsigned long)ret_from_fork; |
| @@ -389,12 +389,7 @@ ENTRY(ret_from_interrupt) · 388 unmodified lines | |||
| 389 | */ | 389 | */ |
| 390 | ENTRY(sys_clone) | 390 | ENTRY(sys_clone) |
| 391 | SAVE_SWITCH_STACK | 391 | SAVE_SWITCH_STACK |
| 392 | addi sp, sp, -4 | 392 | call nios2_clone |
| 393 | stw r7, 0(sp) /* Pass 5th arg thru stack */ | ||
| 394 | mov r7, r6 /* 4th arg is 3rd of clone() */ | ||
| 395 | mov r6, zero /* 3rd arg always 0 */ | ||
| 396 | call do_fork | ||
| 397 | addi sp, sp, 4 | ||
| 398 | RESTORE_SWITCH_STACK | 393 | RESTORE_SWITCH_STACK |
| 399 | ret | 394 | ret |
| 400 | 395 | ||
| @@ -100,8 +100,8 @@ void flush_thread(void) · 99 unmodified lines | |||
| 100 | { | 100 | { |
| 101 | } | 101 | } |
| 102 | 102 | ||
| 103 | int copy_thread(unsigned long clone_flags, | 103 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 104 | unsigned long usp, unsigned long arg, struct task_struct *p) | 104 | struct task_struct *p, unsigned long tls) |
| 105 | { | 105 | { |
| 106 | struct pt_regs *childregs = task_pt_regs(p); | 106 | struct pt_regs *childregs = task_pt_regs(p); |
| 107 | struct pt_regs *regs; | 107 | struct pt_regs *regs; |
| @@ -140,7 +140,7 @@ int copy_thread(unsigned long clone_flags, · 32 unmodified lines | |||
| 140 | 140 | ||
| 141 | /* Initialize tls register. */ | 141 | /* Initialize tls register. */ |
| 142 | if (clone_flags & CLONE_SETTLS) | 142 | if (clone_flags & CLONE_SETTLS) |
| 143 | childstack->r23 = regs->r8; | 143 | childstack->r23 = tls; |
| 144 | 144 | ||
| 145 | return 0; | 145 | return 0; |
| 146 | } | 146 | } |
| @@ -259,3 +259,20 @@ int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r) · 112 unmodified lines | |||
| 259 | { | 259 | { |
| 260 | return 0; /* Nios2 has no FPU and thus no FPU registers */ | 260 | return 0; /* Nios2 has no FPU and thus no FPU registers */ |
| 261 | } | 261 | } |
| 262 | |||
| 263 | asmlinkage int nios2_clone(unsigned long clone_flags, unsigned long newsp, | ||
| 264 | int __user *parent_tidptr, int __user *child_tidptr, | ||
| 265 | unsigned long tls) | ||
| 266 | { | ||
| 267 | struct kernel_clone_args args = { | ||
| 268 | .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), | ||
| 269 | .pidfd = parent_tidptr, | ||
| 270 | .child_tid = child_tidptr, | ||
| 271 | .parent_tid = parent_tidptr, | ||
| 272 | .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), | ||
| 273 | .stack = newsp, | ||
| 274 | .tls = tls, | ||
| 275 | }; | ||
| 276 | |||
| 277 | return _do_fork(&args); | ||
| 278 | } | ||
| @@ -16,7 +16,6 @@ config OPENRISC · 15 unmodified lines | |||
| 16 | select HANDLE_DOMAIN_IRQ | 16 | select HANDLE_DOMAIN_IRQ |
| 17 | select GPIOLIB | 17 | select GPIOLIB |
| 18 | select HAVE_ARCH_TRACEHOOK | 18 | select HAVE_ARCH_TRACEHOOK |
| 19 | select HAVE_COPY_THREAD_TLS | ||
| 20 | select SPARSE_IRQ | 19 | select SPARSE_IRQ |
| 21 | select GENERIC_IRQ_CHIP | 20 | select GENERIC_IRQ_CHIP |
| 22 | select GENERIC_IRQ_PROBE | 21 | select GENERIC_IRQ_PROBE |
| @@ -116,7 +116,7 @@ void release_thread(struct task_struct *dead_task) · 115 unmodified lines | |||
| 116 | extern asmlinkage void ret_from_fork(void); | 116 | extern asmlinkage void ret_from_fork(void); |
| 117 | 117 | ||
| 118 | /* | 118 | /* |
| 119 | * copy_thread_tls | 119 | * copy_thread |
| 120 | * @clone_flags: flags | 120 | * @clone_flags: flags |
| 121 | * @usp: user stack pointer or fn for kernel thread | 121 | * @usp: user stack pointer or fn for kernel thread |
| 122 | * @arg: arg to fn for kernel thread; always NULL for userspace thread | 122 | * @arg: arg to fn for kernel thread; always NULL for userspace thread |
| @@ -147,8 +147,8 @@ extern asmlinkage void ret_from_fork(void); · 24 unmodified lines | |||
| 147 | */ | 147 | */ |
| 148 | 148 | ||
| 149 | int | 149 | int |
| 150 | copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 150 | copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 151 | unsigned long arg, struct task_struct *p, unsigned long tls) | 151 | struct task_struct *p, unsigned long tls) |
| 152 | { | 152 | { |
| 153 | struct pt_regs *userregs; | 153 | struct pt_regs *userregs; |
| 154 | struct pt_regs *kregs; | 154 | struct pt_regs *kregs; |
| @@ -62,7 +62,6 @@ config PARISC · 61 unmodified lines | |||
| 62 | select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE | 62 | select HAVE_FTRACE_MCOUNT_RECORD if HAVE_DYNAMIC_FTRACE |
| 63 | select HAVE_KPROBES_ON_FTRACE | 63 | select HAVE_KPROBES_ON_FTRACE |
| 64 | select HAVE_DYNAMIC_FTRACE_WITH_REGS | 64 | select HAVE_DYNAMIC_FTRACE_WITH_REGS |
| 65 | select HAVE_COPY_THREAD_TLS | ||
| 66 | 65 | ||
| 67 | help | 66 | help |
| 68 | The PA-RISC microprocessor is designed by Hewlett-Packard and used | 67 | The PA-RISC microprocessor is designed by Hewlett-Packard and used |
| @@ -208,7 +208,7 @@ arch_initcall(parisc_idle_init); · 207 unmodified lines | |||
| 208 | * Copy architecture-specific thread state | 208 | * Copy architecture-specific thread state |
| 209 | */ | 209 | */ |
| 210 | int | 210 | int |
| 211 | copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 211 | copy_thread(unsigned long clone_flags, unsigned long usp, |
| 212 | unsigned long kthread_arg, struct task_struct *p, unsigned long tls) | 212 | unsigned long kthread_arg, struct task_struct *p, unsigned long tls) |
| 213 | { | 213 | { |
| 214 | struct pt_regs *cregs = &(p->thread.regs); | 214 | struct pt_regs *cregs = &(p->thread.regs); |
| @@ -186,7 +186,6 @@ config PPC · 185 unmodified lines | |||
| 186 | select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) | 186 | select HAVE_STACKPROTECTOR if PPC32 && $(cc-option,-mstack-protector-guard=tls -mstack-protector-guard-reg=r2) |
| 187 | select HAVE_CONTEXT_TRACKING if PPC64 | 187 | select HAVE_CONTEXT_TRACKING if PPC64 |
| 188 | select HAVE_TIF_NOHZ if PPC64 | 188 | select HAVE_TIF_NOHZ if PPC64 |
| 189 | select HAVE_COPY_THREAD_TLS | ||
| 190 | select HAVE_DEBUG_KMEMLEAK | 189 | select HAVE_DEBUG_KMEMLEAK |
| 191 | select HAVE_DEBUG_STACKOVERFLOW | 190 | select HAVE_DEBUG_STACKOVERFLOW |
| 192 | select HAVE_DYNAMIC_FTRACE | 191 | select HAVE_DYNAMIC_FTRACE |
| @@ -1593,7 +1593,7 @@ static void setup_ksp_vsid(struct task_struct *p, unsigned long sp) · 1592 unmodified lines | |||
| 1593 | /* | 1593 | /* |
| 1594 | * Copy architecture-specific thread state | 1594 | * Copy architecture-specific thread state |
| 1595 | */ | 1595 | */ |
| 1596 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 1596 | int copy_thread(unsigned long clone_flags, unsigned long usp, |
| 1597 | unsigned long kthread_arg, struct task_struct *p, | 1597 | unsigned long kthread_arg, struct task_struct *p, |
| 1598 | unsigned long tls) | 1598 | unsigned long tls) |
| 1599 | { | 1599 | { |
| @@ -54,7 +54,6 @@ config RISCV · 53 unmodified lines | |||
| 54 | select HAVE_ARCH_SECCOMP_FILTER | 54 | select HAVE_ARCH_SECCOMP_FILTER |
| 55 | select HAVE_ARCH_TRACEHOOK | 55 | select HAVE_ARCH_TRACEHOOK |
| 56 | select HAVE_ASM_MODVERSIONS | 56 | select HAVE_ASM_MODVERSIONS |
| 57 | select HAVE_COPY_THREAD_TLS | ||
| 58 | select HAVE_DMA_CONTIGUOUS if MMU | 57 | select HAVE_DMA_CONTIGUOUS if MMU |
| 59 | select HAVE_EBPF_JIT if MMU | 58 | select HAVE_EBPF_JIT if MMU |
| 60 | select HAVE_FUTEX_CMPXCHG if FUTEX | 59 | select HAVE_FUTEX_CMPXCHG if FUTEX |
| @@ -101,8 +101,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) · 100 unmodified lines | |||
| 101 | return 0; | 101 | return 0; |
| 102 | } | 102 | } |
| 103 | 103 | ||
| 104 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp, | 104 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 105 | unsigned long arg, struct task_struct *p, unsigned long tls) | 105 | struct task_struct *p, unsigned long tls) |
| 106 | { | 106 | { |
| 107 | struct pt_regs *childregs = task_pt_regs(p); | 107 | struct pt_regs *childregs = task_pt_regs(p); |
| 108 | 108 | ||
| @@ -136,7 +136,6 @@ config S390 · 135 unmodified lines | |||
| 136 | select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES | 136 | select HAVE_EBPF_JIT if PACK_STACK && HAVE_MARCH_Z196_FEATURES |
| 137 | select HAVE_CMPXCHG_DOUBLE | 137 | select HAVE_CMPXCHG_DOUBLE |
| 138 | select HAVE_CMPXCHG_LOCAL | 138 | select HAVE_CMPXCHG_LOCAL |
| 139 | select HAVE_COPY_THREAD_TLS | ||
| 140 | select HAVE_DEBUG_KMEMLEAK | 139 | select HAVE_DEBUG_KMEMLEAK |
| 141 | select HAVE_DMA_CONTIGUOUS | 140 | select HAVE_DMA_CONTIGUOUS |
| 142 | select HAVE_DYNAMIC_FTRACE | 141 | select HAVE_DYNAMIC_FTRACE |
| @@ -80,8 +80,8 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) · 79 unmodified lines | |||
| 80 | return 0; | 80 | return 0; |
| 81 | } | 81 | } |
| 82 | 82 | ||
| 83 | int copy_thread_tls(unsigned long clone_flags, unsigned long new_stackp, | 83 | int copy_thread(unsigned long clone_flags, unsigned long new_stackp, |
| 84 | unsigned long arg, struct task_struct *p, unsigned long tls) | 84 | unsigned long arg, struct task_struct *p, unsigned long tls) |
| 85 | { | 85 | { |
| 86 | struct fake_frame | 86 | struct fake_frame |
| 87 | { | 87 | { |
| @@ -115,8 +115,8 @@ EXPORT_SYMBOL(dump_fpu); · 114 unmodified lines | |||
| 115 | asmlinkage void ret_from_fork(void); | 115 | asmlinkage void ret_from_fork(void); |
| 116 | asmlinkage void ret_from_kernel_thread(void); | 116 | asmlinkage void ret_from_kernel_thread(void); |
| 117 | 117 | ||
| 118 | int copy_thread(unsigned long clone_flags, unsigned long usp, | 118 | int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long arg, |
| 119 | unsigned long arg, struct task_struct *p) | 119 | struct task_struct *p, unsigned long tls) |
| 120 | { | 120 | { |
| 121 | struct thread_info *ti = task_thread_info(p); | 121 | struct thread_info *ti = task_thread_info(p); |
| 122 | struct pt_regs *childregs; | 122 | struct pt_regs *childregs; |
| @@ -158,7 +158,7 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, · 35 unmodified lines | |||
| 158 | ti->addr_limit = USER_DS; | 158 | ti->addr_limit = USER_DS; |
| 159 | 159 | ||
| 160 | if (clone_flags & CLONE_SETTLS) | 160 | if (clone_flags & CLONE_SETTLS) |
| 161 | childregs->gbr = childregs->regs[0]; | 161 | childregs->gbr = tls; |
| 162 | 162 | ||
| 163 | childregs->regs[0] = 0; /* Set return value for child */ | 163 | childregs->regs[0] = 0; /* Set return value for child */ |
| 164 | p->thread.pc = (unsigned long) ret_from_fork; | 164 | p->thread.pc = (unsigned long) ret_from_fork; |
| @@ -4,9 +4,8 @@ · 3 unmodified lines | |||
| 4 | 4 | ||
| 5 | struct pt_regs; | 5 | struct pt_regs; |
| 6 | 6 | ||
| 7 | asmlinkage long sparc_do_fork(unsigned long clone_flags, | 7 | asmlinkage long sparc_fork(struct pt_regs *regs); |
| 8 | unsigned long stack_start, | 8 | asmlinkage long sparc_vfork(struct pt_regs *regs); |
| 9 | struct pt_regs *regs, | 9 | asmlinkage long sparc_clone(struct pt_regs *regs); |
| 10 | unsigned long stack_size); | ||
| 11 | 10 | ||
| 12 | #endif /* _SPARC64_SYSCALLS_H */ | 11 | #endif /* _SPARC64_SYSCALLS_H */ |
| @@ -33,6 +33,7 @@ obj-y += irq_$(BITS).o · 32 unmodified lines | |||
| 33 | obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o | 33 | obj-$(CONFIG_SPARC32) += sun4m_irq.o sun4d_irq.o |
| 34 | 34 | ||
| 35 | obj-y += process_$(BITS).o | 35 | obj-y += process_$(BITS).o |
| 36 | obj-y += process.o | ||
| 36 | obj-y += signal_$(BITS).o | 37 | obj-y += signal_$(BITS).o |
| 37 | obj-y += sigutil_$(BITS).o | 38 | obj-y += sigutil_$(BITS).o |
| 38 | obj-$(CONFIG_SPARC32) += ioport.o | 39 | obj-$(CONFIG_SPARC32) += ioport.o |
| @@ -869,14 +869,11 @@ flush_patch_two: · 868 unmodified lines | |||
| 869 | ld [%curptr + TI_TASK], %o4 | 869 | ld [%curptr + TI_TASK], %o4 |
| 870 | rd %psr, %g4 | 870 | rd %psr, %g4 |
| 871 | WRITE_PAUSE | 871 | WRITE_PAUSE |
| 872 | mov SIGCHLD, %o0 ! arg0: clone flags | ||
| 873 | rd %wim, %g5 | 872 | rd %wim, %g5 |
| 874 | WRITE_PAUSE | 873 | WRITE_PAUSE |
| 875 | mov %fp, %o1 ! arg1: usp | ||
| 876 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] | 874 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] |
| 877 | add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr | 875 | add %sp, STACKFRAME_SZ, %o0 |
| 878 | mov 0, %o3 | 876 | call sparc_fork |
| 879 | call sparc_do_fork | ||
| 880 | mov %l5, %o7 | 877 | mov %l5, %o7 |
| 881 | 878 | ||
| 882 | /* Whee, kernel threads! */ | 879 | /* Whee, kernel threads! */ |
| @@ -888,19 +885,11 @@ flush_patch_three: · 5 unmodified lines | |||
| 888 | ld [%curptr + TI_TASK], %o4 | 885 | ld [%curptr + TI_TASK], %o4 |
| 889 | rd %psr, %g4 | 886 | rd %psr, %g4 |
| 890 | WRITE_PAUSE | 887 | WRITE_PAUSE |
| 891 | |||
| 892 | /* arg0,1: flags,usp -- loaded already */ | ||
| 893 | cmp %o1, 0x0 ! Is new_usp NULL? | ||
| 894 | rd %wim, %g5 | 888 | rd %wim, %g5 |
| 895 | WRITE_PAUSE | 889 | WRITE_PAUSE |
| 896 | be,a 1f | ||
| 897 | mov %fp, %o1 ! yes, use callers usp | ||
| 898 | andn %o1, 7, %o1 ! no, align to 8 bytes | ||
| 899 | 1: | ||
| 900 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] | 890 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] |
| 901 | add %sp, STACKFRAME_SZ, %o2 ! arg2: pt_regs ptr | 891 | add %sp, STACKFRAME_SZ, %o0 |
| 902 | mov 0, %o3 | 892 | call sparc_clone |
| 903 | call sparc_do_fork | ||
| 904 | mov %l5, %o7 | 893 | mov %l5, %o7 |
| 905 | 894 | ||
| 906 | /* Whee, real vfork! */ | 895 | /* Whee, real vfork! */ |
| @@ -914,13 +903,9 @@ flush_patch_four: · 7 unmodified lines | |||
| 914 | rd %wim, %g5 | 903 | rd %wim, %g5 |
| 915 | WRITE_PAUSE | 904 | WRITE_PAUSE |
| 916 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] | 905 | std %g4, [%o4 + AOFF_task_thread + AOFF_thread_fork_kpsr] |
| 917 | sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 | 906 | sethi %hi(sparc_vfork), %l1 |
| 918 | mov %fp, %o1 | 907 | jmpl %l1 + %lo(sparc_vfork), %g0 |
| 919 | or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 | 908 | add %sp, STACKFRAME_SZ, %o0 |
| 920 | sethi %hi(sparc_do_fork), %l1 | ||
| 921 | mov 0, %o3 | ||
| 922 | jmpl %l1 + %lo(sparc_do_fork), %g0 | ||
| 923 | add %sp, STACKFRAME_SZ, %o2 | ||
| 924 | 909 | ||
| 925 | .align 4 | 910 | .align 4 |
| 926 | linux_sparc_ni_syscall: | 911 | linux_sparc_ni_syscall: |
| @@ -14,6 +14,11 @@ extern const char *sparc_pmu_type; · 13 unmodified lines | |||
| 14 | extern unsigned int fsr_storage; | 14 | extern unsigned int fsr_storage; |
| 15 | extern int ncpus_probed; | 15 | extern int ncpus_probed; |
| 16 | 16 | ||
| 17 | /* process{_32,_64}.c */ | ||
| 18 | asmlinkage long sparc_clone(struct pt_regs *regs); | ||
| 19 | asmlinkage long sparc_fork(struct pt_regs *regs); | ||
| 20 | asmlinkage long sparc_vfork(struct pt_regs *regs); | ||
| 21 | |||
| 17 | #ifdef CONFIG_SPARC64 | 22 | #ifdef CONFIG_SPARC64 |
| 18 | /* setup_64.c */ | 23 | /* setup_64.c */ |
| 19 | struct seq_file; | 24 | struct seq_file; |
| @@ -153,12 +158,6 @@ void floppy_hardint(void); · 133 unmodified lines | |||
| 153 | extern unsigned long sun4m_cpu_startup; | 158 | extern unsigned long sun4m_cpu_startup; |
| 154 | extern unsigned long sun4d_cpu_startup; | 159 | extern unsigned long sun4d_cpu_startup; |
| 155 | 160 | ||
| 156 | /* process_32.c */ | ||
| 157 | asmlinkage int sparc_do_fork(unsigned long clone_flags, | ||
| 158 | unsigned long stack_start, | ||
| 159 | struct pt_regs *regs, | ||
| 160 | unsigned long stack_size); | ||
| 161 | |||
| 162 | /* signal_32.c */ | 161 | /* signal_32.c */ |
| 163 | asmlinkage void do_sigreturn(struct pt_regs *regs); | 162 | asmlinkage void do_sigreturn(struct pt_regs *regs); |
| 164 | asmlinkage void do_rt_sigreturn(struct pt_regs *regs); | 163 | asmlinkage void do_rt_sigreturn(struct pt_regs *regs); |
| @@ -0,0 +1,110 @@ | |||
| 1 | // SPDX-License-Identifier: GPL-2.0 | ||
| 2 | |||
| 3 | /* | ||
| 4 | * This file handles the architecture independent parts of process handling.. | ||
| 5 | */ | ||
| 6 | |||
| 7 | #include <linux/compat.h> | ||
| 8 | #include <linux/errno.h> | ||
| 9 | #include <linux/kernel.h> | ||
| 10 | #include <linux/ptrace.h> | ||
| 11 | #include <linux/sched.h> | ||
| 12 | #include <linux/sched/task.h> | ||
| 13 | #include <linux/sched/task_stack.h> | ||
| 14 | #include <linux/signal.h> | ||
| 15 | |||
| 16 | #include "kernel.h" | ||
| 17 | |||
| 18 | asmlinkage long sparc_fork(struct pt_regs *regs) | ||
| 19 | { | ||
| 20 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 21 | long ret; | ||
| 22 | struct kernel_clone_args args = { | ||
| 23 | .exit_signal = SIGCHLD, | ||
| 24 | /* Reuse the parent's stack for the child. */ | ||
| 25 | .stack = regs->u_regs[UREG_FP], | ||
| 26 | }; | ||
| 27 | |||
| 28 | ret = _do_fork(&args); | ||
| 29 | |||
| 30 | /* If we get an error and potentially restart the system | ||
| 31 | * call, we're screwed because copy_thread() clobbered | ||
| 32 | * the parent's %o1. So detect that case and restore it | ||
| 33 | * here. | ||
| 34 | */ | ||
| 35 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 36 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 37 | |||
| 38 | return ret; | ||
| 39 | } | ||
| 40 | |||
| 41 | asmlinkage long sparc_vfork(struct pt_regs *regs) | ||
| 42 | { | ||
| 43 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 44 | long ret; | ||
| 45 | |||
| 46 | struct kernel_clone_args args = { | ||
| 47 | .flags = CLONE_VFORK | CLONE_VM, | ||
| 48 | .exit_signal = SIGCHLD, | ||
| 49 | /* Reuse the parent's stack for the child. */ | ||
| 50 | .stack = regs->u_regs[UREG_FP], | ||
| 51 | }; | ||
| 52 | |||
| 53 | ret = _do_fork(&args); | ||
| 54 | |||
| 55 | /* If we get an error and potentially restart the system | ||
| 56 | * call, we're screwed because copy_thread() clobbered | ||
| 57 | * the parent's %o1. So detect that case and restore it | ||
| 58 | * here. | ||
| 59 | */ | ||
| 60 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 61 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 62 | |||
| 63 | return ret; | ||
| 64 | } | ||
| 65 | |||
| 66 | asmlinkage long sparc_clone(struct pt_regs *regs) | ||
| 67 | { | ||
| 68 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 69 | unsigned int flags = lower_32_bits(regs->u_regs[UREG_I0]); | ||
| 70 | long ret; | ||
| 71 | |||
| 72 | struct kernel_clone_args args = { | ||
| 73 | .flags = (flags & ~CSIGNAL), | ||
| 74 | .exit_signal = (flags & CSIGNAL), | ||
| 75 | .tls = regs->u_regs[UREG_I3], | ||
| 76 | }; | ||
| 77 | |||
| 78 | #ifdef CONFIG_COMPAT | ||
| 79 | if (test_thread_flag(TIF_32BIT)) { | ||
| 80 | args.pidfd = compat_ptr(regs->u_regs[UREG_I2]); | ||
| 81 | args.child_tid = compat_ptr(regs->u_regs[UREG_I4]); | ||
| 82 | args.parent_tid = compat_ptr(regs->u_regs[UREG_I2]); | ||
| 83 | } else | ||
| 84 | #endif | ||
| 85 | { | ||
| 86 | args.pidfd = (int __user *)regs->u_regs[UREG_I2]; | ||
| 87 | args.child_tid = (int __user *)regs->u_regs[UREG_I4]; | ||
| 88 | args.parent_tid = (int __user *)regs->u_regs[UREG_I2]; | ||
| 89 | } | ||
| 90 | |||
| 91 | /* Did userspace give setup a separate stack for the child or are we | ||
| 92 | * reusing the parent's? | ||
| 93 | */ | ||
| 94 | if (regs->u_regs[UREG_I1]) | ||
| 95 | args.stack = regs->u_regs[UREG_I1]; | ||
| 96 | else | ||
| 97 | args.stack = regs->u_regs[UREG_FP]; | ||
| 98 | |||
| 99 | ret = _do_fork(&args); | ||
| 100 | |||
| 101 | /* If we get an error and potentially restart the system | ||
| 102 | * call, we're screwed because copy_thread() clobbered | ||
| 103 | * the parent's %o1. So detect that case and restore it | ||
| 104 | * here. | ||
| 105 | */ | ||
| 106 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 107 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 108 | |||
| 109 | return ret; | ||
| 110 | } | ||
| @@ -257,33 +257,6 @@ clone_stackframe(struct sparc_stackf __user *dst, · 256 unmodified lines | |||
| 257 | return sp; | 257 | return sp; |
| 258 | } | 258 | } |
| 259 | 259 | ||
| 260 | asmlinkage int sparc_do_fork(unsigned long clone_flags, | ||
| 261 | unsigned long stack_start, | ||
| 262 | struct pt_regs *regs, | ||
| 263 | unsigned long stack_size) | ||
| 264 | { | ||
| 265 | unsigned long parent_tid_ptr, child_tid_ptr; | ||
| 266 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 267 | long ret; | ||
| 268 | |||
| 269 | parent_tid_ptr = regs->u_regs[UREG_I2]; | ||
| 270 | child_tid_ptr = regs->u_regs[UREG_I4]; | ||
| 271 | |||
| 272 | ret = do_fork(clone_flags, stack_start, stack_size, | ||
| 273 | (int __user *) parent_tid_ptr, | ||
| 274 | (int __user *) child_tid_ptr); | ||
| 275 | |||
| 276 | /* If we get an error and potentially restart the system | ||
| 277 | * call, we're screwed because copy_thread() clobbered | ||
| 278 | * the parent's %o1. So detect that case and restore it | ||
| 279 | * here. | ||
| 280 | */ | ||
| 281 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 282 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 283 | |||
| 284 | return ret; | ||
| 285 | } | ||
| 286 | |||
| 287 | /* Copy a Sparc thread. The fork() return value conventions | 260 | /* Copy a Sparc thread. The fork() return value conventions |
| 288 | * under SunOS are nothing short of bletcherous: | 261 | * under SunOS are nothing short of bletcherous: |
| 289 | * Parent --> %o0 == childs pid, %o1 == 0 | 262 | * Parent --> %o0 == childs pid, %o1 == 0 |
| @@ -300,8 +273,8 @@ asmlinkage int sparc_do_fork(unsigned long clone_flags, · 10 unmodified lines | |||
| 300 | extern void ret_from_fork(void); | 273 | extern void ret_from_fork(void); |
| 301 | extern void ret_from_kernel_thread(void); | 274 | extern void ret_from_kernel_thread(void); |
| 302 | 275 | ||
| 303 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 276 | int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, |
| 304 | unsigned long arg, struct task_struct *p) | 277 | struct task_struct *p, unsigned long tls) |
| 305 | { | 278 | { |
| 306 | struct thread_info *ti = task_thread_info(p); | 279 | struct thread_info *ti = task_thread_info(p); |
| 307 | struct pt_regs *childregs, *regs = current_pt_regs(); | 280 | struct pt_regs *childregs, *regs = current_pt_regs(); |
| @@ -403,7 +376,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 95 unmodified lines | |||
| 403 | regs->u_regs[UREG_I1] = 0; | 376 | regs->u_regs[UREG_I1] = 0; |
| 404 | 377 | ||
| 405 | if (clone_flags & CLONE_SETTLS) | 378 | if (clone_flags & CLONE_SETTLS) |
| 406 | childregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3]; | 379 | childregs->u_regs[UREG_G7] = tls; |
| 407 | 380 | ||
| 408 | return 0; | 381 | return 0; |
| 409 | } | 382 | } |
| @@ -572,47 +572,13 @@ barf: · 571 unmodified lines | |||
| 572 | force_sig(SIGSEGV); | 572 | force_sig(SIGSEGV); |
| 573 | } | 573 | } |
| 574 | 574 | ||
| 575 | asmlinkage long sparc_do_fork(unsigned long clone_flags, | ||
| 576 | unsigned long stack_start, | ||
| 577 | struct pt_regs *regs, | ||
| 578 | unsigned long stack_size) | ||
| 579 | { | ||
| 580 | int __user *parent_tid_ptr, *child_tid_ptr; | ||
| 581 | unsigned long orig_i1 = regs->u_regs[UREG_I1]; | ||
| 582 | long ret; | ||
| 583 | |||
| 584 | #ifdef CONFIG_COMPAT | ||
| 585 | if (test_thread_flag(TIF_32BIT)) { | ||
| 586 | parent_tid_ptr = compat_ptr(regs->u_regs[UREG_I2]); | ||
| 587 | child_tid_ptr = compat_ptr(regs->u_regs[UREG_I4]); | ||
| 588 | } else | ||
| 589 | #endif | ||
| 590 | { | ||
| 591 | parent_tid_ptr = (int __user *) regs->u_regs[UREG_I2]; | ||
| 592 | child_tid_ptr = (int __user *) regs->u_regs[UREG_I4]; | ||
| 593 | } | ||
| 594 | |||
| 595 | ret = do_fork(clone_flags, stack_start, stack_size, | ||
| 596 | parent_tid_ptr, child_tid_ptr); | ||
| 597 | |||
| 598 | /* If we get an error and potentially restart the system | ||
| 599 | * call, we're screwed because copy_thread() clobbered | ||
| 600 | * the parent's %o1. So detect that case and restore it | ||
| 601 | * here. | ||
| 602 | */ | ||
| 603 | if ((unsigned long)ret >= -ERESTART_RESTARTBLOCK) | ||
| 604 | regs->u_regs[UREG_I1] = orig_i1; | ||
| 605 | |||
| 606 | return ret; | ||
| 607 | } | ||
| 608 | |||
| 609 | /* Copy a Sparc thread. The fork() return value conventions | 575 | /* Copy a Sparc thread. The fork() return value conventions |
| 610 | * under SunOS are nothing short of bletcherous: | 576 | * under SunOS are nothing short of bletcherous: |
| 611 | * Parent --> %o0 == childs pid, %o1 == 0 | 577 | * Parent --> %o0 == childs pid, %o1 == 0 |
| 612 | * Child --> %o0 == parents pid, %o1 == 1 | 578 | * Child --> %o0 == parents pid, %o1 == 1 |
| 613 | */ | 579 | */ |
| 614 | int copy_thread(unsigned long clone_flags, unsigned long sp, | 580 | int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, |
| 615 | unsigned long arg, struct task_struct *p) | 581 | struct task_struct *p, unsigned long tls) |
| 616 | { | 582 | { |
| 617 | struct thread_info *t = task_thread_info(p); | 583 | struct thread_info *t = task_thread_info(p); |
| 618 | struct pt_regs *regs = current_pt_regs(); | 584 | struct pt_regs *regs = current_pt_regs(); |
| @@ -670,7 +636,7 @@ int copy_thread(unsigned long clone_flags, unsigned long sp, · 51 unmodified lines | |||
| 670 | regs->u_regs[UREG_I1] = 0; | 636 | regs->u_regs[UREG_I1] = 0; |
| 671 | 637 | ||
| 672 | if (clone_flags & CLONE_SETTLS) | 638 | if (clone_flags & CLONE_SETTLS) |
| 673 | t->kregs->u_regs[UREG_G7] = regs->u_regs[UREG_I3]; | 639 | t->kregs->u_regs[UREG_G7] = tls; |
| 674 | 640 | ||
| 675 | return 0; | 641 | return 0; |
| 676 | } | 642 | } |
| @@ -86,19 +86,22 @@ sys32_rt_sigreturn: · 85 unmodified lines | |||
| 86 | * during system calls... | 86 | * during system calls... |
| 87 | */ | 87 | */ |
| 88 | .align 32 | 88 | .align 32 |
| 89 | sys_vfork: /* Under Linux, vfork and fork are just special cases of clone. */ | 89 | sys_vfork: |
| 90 | sethi %hi(0x4000 | 0x0100 | SIGCHLD), %o0 | 90 | flushw |
| 91 | or %o0, %lo(0x4000 | 0x0100 | SIGCHLD), %o0 | 91 | ba,pt %xcc, sparc_vfork |
| 92 | ba,pt %xcc, sys_clone | 92 | add %sp, PTREGS_OFF, %o0 |
| 93 | |||
| 94 | .align 32 | ||
| 93 | sys_fork: | 95 | sys_fork: |
| 94 | clr %o1 | 96 | flushw |
| 95 | mov SIGCHLD, %o0 | 97 | ba,pt %xcc, sparc_fork |
| 98 | add %sp, PTREGS_OFF, %o0 | ||
| 99 | |||
| 100 | .align 32 | ||
| 96 | sys_clone: | 101 | sys_clone: |
| 97 | flushw | 102 | flushw |
| 98 | movrz %o1, %fp, %o1 | 103 | ba,pt %xcc, sparc_clone |
| 99 | mov 0, %o3 | 104 | add %sp, PTREGS_OFF, %o0 |
| 100 | ba,pt %xcc, sparc_do_fork | ||
| 101 | add %sp, PTREGS_OFF, %o2 | ||
| 102 | 105 | ||
| 103 | .globl ret_from_fork | 106 | .globl ret_from_fork |
| 104 | ret_from_fork: | 107 | ret_from_fork: |
| @@ -14,7 +14,6 @@ config UML · 13 unmodified lines | |||
| 14 | select HAVE_FUTEX_CMPXCHG if FUTEX | 14 | select HAVE_FUTEX_CMPXCHG if FUTEX |
| 15 | select HAVE_DEBUG_KMEMLEAK | 15 | select HAVE_DEBUG_KMEMLEAK |
| 16 | select HAVE_DEBUG_BUGVERBOSE | 16 | select HAVE_DEBUG_BUGVERBOSE |
| 17 | select HAVE_COPY_THREAD_TLS | ||
| 18 | select GENERIC_IRQ_SHOW | 17 | select GENERIC_IRQ_SHOW |
| 19 | select GENERIC_CPU_DEVICES | 18 | select GENERIC_CPU_DEVICES |
| 20 | select GENERIC_CLOCKEVENTS | 19 | select GENERIC_CLOCKEVENTS |
| @@ -152,7 +152,7 @@ void fork_handler(void) · 151 unmodified lines | |||
| 152 | userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); | 152 | userspace(¤t->thread.regs.regs, current_thread_info()->aux_fp_regs); |
| 153 | } | 153 | } |
| 154 | 154 | ||
| 155 | int copy_thread_tls(unsigned long clone_flags, unsigned long sp, | 155 | int copy_thread(unsigned long clone_flags, unsigned long sp, |
| 156 | unsigned long arg, struct task_struct * p, unsigned long tls) | 156 | unsigned long arg, struct task_struct * p, unsigned long tls) |
| 157 | { | 157 | { |
| 158 | void (*handler)(void); | 158 | void (*handler)(void); |
| @@ -161,7 +161,6 @@ config X86 · 160 unmodified lines | |||
| 161 | select HAVE_CMPXCHG_DOUBLE | 161 | select HAVE_CMPXCHG_DOUBLE |
| 162 | select HAVE_CMPXCHG_LOCAL | 162 | select HAVE_CMPXCHG_LOCAL |
| 163 | select HAVE_CONTEXT_TRACKING if X86_64 | 163 | select HAVE_CONTEXT_TRACKING if X86_64 |
| 164 | select HAVE_COPY_THREAD_TLS | ||
| 165 | select HAVE_C_RECORDMCOUNT | 164 | select HAVE_C_RECORDMCOUNT |
| 166 | select HAVE_DEBUG_KMEMLEAK | 165 | select HAVE_DEBUG_KMEMLEAK |
| 167 | select HAVE_DMA_CONTIGUOUS | 166 | select HAVE_DMA_CONTIGUOUS |
| @@ -121,8 +121,8 @@ static int set_new_tls(struct task_struct *p, unsigned long tls) · 120 unmodified lines | |||
| 121 | return do_set_thread_area_64(p, ARCH_SET_FS, tls); | 121 | return do_set_thread_area_64(p, ARCH_SET_FS, tls); |
| 122 | } | 122 | } |
| 123 | 123 | ||
| 124 | int copy_thread_tls(unsigned long clone_flags, unsigned long sp, | 124 | int copy_thread(unsigned long clone_flags, unsigned long sp, unsigned long arg, |
| 125 | unsigned long arg, struct task_struct *p, unsigned long tls) | 125 | struct task_struct *p, unsigned long tls) |
| 126 | { | 126 | { |
| 127 | struct inactive_task_frame *frame; | 127 | struct inactive_task_frame *frame; |
| 128 | struct fork_frame *fork_frame; | 128 | struct fork_frame *fork_frame; |
| @@ -251,9 +251,6 @@ COMPAT_SYSCALL_DEFINE5(ia32_clone, unsigned long, clone_flags, · 250 unmodified lines | |||
| 251 | .tls = tls_val, | 251 | .tls = tls_val, |
| 252 | }; | 252 | }; |
| 253 | 253 | ||
| 254 | if (!legacy_clone_args_valid(&args)) | ||
| 255 | return -EINVAL; | ||
| 256 | |||
| 257 | return _do_fork(&args); | 254 | return _do_fork(&args); |
| 258 | } | 255 | } |
| 259 | #endif /* CONFIG_IA32_EMULATION */ | 256 | #endif /* CONFIG_IA32_EMULATION */ |
| @@ -269,7 +269,7 @@ bool unwind_next_frame(struct unwind_state *state) · 268 unmodified lines | |||
| 269 | /* | 269 | /* |
| 270 | * kthreads (other than the boot CPU's idle thread) have some | 270 | * kthreads (other than the boot CPU's idle thread) have some |
| 271 | * partial regs at the end of their stack which were placed | 271 | * partial regs at the end of their stack which were placed |
| 272 | * there by copy_thread_tls(). But the regs don't have any | 272 | * there by copy_thread(). But the regs don't have any |
| 273 | * useful information, so we can skip them. | 273 | * useful information, so we can skip them. |
| 274 | * | 274 | * |
| 275 | * This user_mode() check is slightly broader than a PF_KTHREAD | 275 | * This user_mode() check is slightly broader than a PF_KTHREAD |
| @@ -24,7 +24,6 @@ config XTENSA · 23 unmodified lines | |||
| 24 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL | 24 | select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL |
| 25 | select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL | 25 | select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL |
| 26 | select HAVE_ARCH_TRACEHOOK | 26 | select HAVE_ARCH_TRACEHOOK |
| 27 | select HAVE_COPY_THREAD_TLS | ||
| 28 | select HAVE_DEBUG_KMEMLEAK | 27 | select HAVE_DEBUG_KMEMLEAK |
| 29 | select HAVE_DMA_CONTIGUOUS | 28 | select HAVE_DMA_CONTIGUOUS |
| 30 | select HAVE_EXIT_THREAD | 29 | select HAVE_EXIT_THREAD |
| @@ -201,7 +201,7 @@ int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) · 200 unmodified lines | |||
| 201 | * involved. Much simpler to just not copy those live frames across. | 201 | * involved. Much simpler to just not copy those live frames across. |
| 202 | */ | 202 | */ |
| 203 | 203 | ||
| 204 | int copy_thread_tls(unsigned long clone_flags, unsigned long usp_thread_fn, | 204 | int copy_thread(unsigned long clone_flags, unsigned long usp_thread_fn, |
| 205 | unsigned long thread_fn_arg, struct task_struct *p, | 205 | unsigned long thread_fn_arg, struct task_struct *p, |
| 206 | unsigned long tls) | 206 | unsigned long tls) |
| 207 | { | 207 | { |
| @@ -66,22 +66,9 @@ extern void fork_init(void); · 65 unmodified lines | |||
| 66 | 66 | ||
| 67 | extern void release_task(struct task_struct * p); | 67 | extern void release_task(struct task_struct * p); |
| 68 | 68 | ||
| 69 | #ifdef CONFIG_HAVE_COPY_THREAD_TLS | ||
| 70 | extern int copy_thread_tls(unsigned long, unsigned long, unsigned long, | ||
| 71 | struct task_struct *, unsigned long); | ||
| 72 | #else | ||
| 73 | extern int copy_thread(unsigned long, unsigned long, unsigned long, | 69 | extern int copy_thread(unsigned long, unsigned long, unsigned long, |
| 74 | struct task_struct *); | 70 | struct task_struct *, unsigned long); |
| 75 | 71 | ||
| 76 | /* Architectures that haven't opted into copy_thread_tls get the tls argument | ||
| 77 | * via pt_regs, so ignore the tls argument passed via C. */ | ||
| 78 | static inline int copy_thread_tls( | ||
| 79 | unsigned long clone_flags, unsigned long sp, unsigned long arg, | ||
| 80 | struct task_struct *p, unsigned long tls) | ||
| 81 | { | ||
| 82 | return copy_thread(clone_flags, sp, arg, p); | ||
| 83 | } | ||
| 84 | #endif | ||
| 85 | extern void flush_thread(void); | 72 | extern void flush_thread(void); |
| 86 | 73 | ||
| 87 | #ifdef CONFIG_HAVE_EXIT_THREAD | 74 | #ifdef CONFIG_HAVE_EXIT_THREAD |
| @@ -97,8 +84,6 @@ extern void exit_files(struct task_struct *); · 9 unmodified lines | |||
| 97 | extern void exit_itimers(struct signal_struct *); | 84 | extern void exit_itimers(struct signal_struct *); |
| 98 | 85 | ||
| 99 | extern long _do_fork(struct kernel_clone_args *kargs); | 86 | extern long _do_fork(struct kernel_clone_args *kargs); |
| 100 | extern bool legacy_clone_args_valid(const struct kernel_clone_args *kargs); | ||
| 101 | extern long do_fork(unsigned long, unsigned long, unsigned long, int __user *, int __user *); | ||
| 102 | struct task_struct *fork_idle(int); | 87 | struct task_struct *fork_idle(int); |
| 103 | struct mm_struct *copy_init_mm(void); | 88 | struct mm_struct *copy_init_mm(void); |
| 104 | extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); | 89 | extern pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags); |
| @@ -2097,8 +2097,7 @@ static __latent_entropy struct task_struct *copy_process( · 2096 unmodified lines | |||
| 2097 | retval = copy_io(clone_flags, p); | 2097 | retval = copy_io(clone_flags, p); |
| 2098 | if (retval) | 2098 | if (retval) |
| 2099 | goto bad_fork_cleanup_namespaces; | 2099 | goto bad_fork_cleanup_namespaces; |
| 2100 | retval = copy_thread_tls(clone_flags, args->stack, args->stack_size, p, | 2100 | retval = copy_thread(clone_flags, args->stack, args->stack_size, p, args->tls); |
| 2101 | args->tls); | ||
| 2102 | if (retval) | 2101 | if (retval) |
| 2103 | goto bad_fork_cleanup_io; | 2102 | goto bad_fork_cleanup_io; |
| 2104 | 2103 | ||
| @@ -2416,6 +2415,20 @@ long _do_fork(struct kernel_clone_args *args) · 311 unmodified lines | |||
| 2416 | int trace = 0; | 2415 | int trace = 0; |
| 2417 | long nr; | 2416 | long nr; |
| 2418 | 2417 | ||
| 2418 | /* | ||
| 2419 | * For legacy clone() calls, CLONE_PIDFD uses the parent_tid argument | ||
| 2420 | * to return the pidfd. Hence, CLONE_PIDFD and CLONE_PARENT_SETTID are | ||
| 2421 | * mutually exclusive. With clone3() CLONE_PIDFD has grown a separate | ||
| 2422 | * field in struct clone_args and it still doesn't make sense to have | ||
| 2423 | * them both point at the same memory location. Performing this check | ||
| 2424 | * here has the advantage that we don't need to have a separate helper | ||
| 2425 | * to check for legacy clone(). | ||
| 2426 | */ | ||
| 2427 | if ((args->flags & CLONE_PIDFD) && | ||
| 2428 | (args->flags & CLONE_PARENT_SETTID) && | ||
| 2429 | (args->pidfd == args->parent_tid)) | ||
| 2430 | return -EINVAL; | ||
| 2431 | |||
| 2419 | /* | 2432 | /* |
| 2420 | * Determine whether and which event to report to ptracer. When | 2433 | * Determine whether and which event to report to ptracer. When |
| 2421 | * called from kernel_thread or CLONE_UNTRACED is explicitly | 2434 | * called from kernel_thread or CLONE_UNTRACED is explicitly |
| @@ -2473,42 +2486,6 @@ long _do_fork(struct kernel_clone_args *args) · 51 unmodified lines | |||
| 2473 | return nr; | 2486 | return nr; |
| 2474 | } | 2487 | } |
| 2475 | 2488 | ||
| 2476 | bool legacy_clone_args_valid(const struct kernel_clone_args *kargs) | ||
| 2477 | { | ||
| 2478 | /* clone(CLONE_PIDFD) uses parent_tidptr to return a pidfd */ | ||
| 2479 | if ((kargs->flags & CLONE_PIDFD) && | ||
| 2480 | (kargs->flags & CLONE_PARENT_SETTID)) | ||
| 2481 | return false; | ||
| 2482 | |||
| 2483 | return true; | ||
| 2484 | } | ||
| 2485 | |||
| 2486 | #ifndef CONFIG_HAVE_COPY_THREAD_TLS | ||
| 2487 | /* For compatibility with architectures that call do_fork directly rather than | ||
| 2488 | * using the syscall entry points below. */ | ||
| 2489 | long do_fork(unsigned long clone_flags, | ||
| 2490 | unsigned long stack_start, | ||
| 2491 | unsigned long stack_size, | ||
| 2492 | int __user *parent_tidptr, | ||
| 2493 | int __user *child_tidptr) | ||
| 2494 | { | ||
| 2495 | struct kernel_clone_args args = { | ||
| 2496 | .flags = (lower_32_bits(clone_flags) & ~CSIGNAL), | ||
| 2497 | .pidfd = parent_tidptr, | ||
| 2498 | .child_tid = child_tidptr, | ||
| 2499 | .parent_tid = parent_tidptr, | ||
| 2500 | .exit_signal = (lower_32_bits(clone_flags) & CSIGNAL), | ||
| 2501 | .stack = stack_start, | ||
| 2502 | .stack_size = stack_size, | ||
| 2503 | }; | ||
| 2504 | |||
| 2505 | if (!legacy_clone_args_valid(&args)) | ||
| 2506 | return -EINVAL; | ||
| 2507 | |||
| 2508 | return _do_fork(&args); | ||
| 2509 | } | ||
| 2510 | #endif | ||
| 2511 | |||
| 2512 | /* | 2489 | /* |
| 2513 | * Create a kernel thread. | 2490 | * Create a kernel thread. |
| 2514 | */ | 2491 | */ |
| @@ -2587,24 +2564,12 @@ SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp, · 72 unmodified lines | |||
| 2587 | .tls = tls, | 2564 | .tls = tls, |
| 2588 | }; | 2565 | }; |
| 2589 | 2566 | ||
| 2590 | if (!legacy_clone_args_valid(&args)) | ||
| 2591 | return -EINVAL; | ||
| 2592 | |||
| 2593 | return _do_fork(&args); | 2567 | return _do_fork(&args); |
| 2594 | } | 2568 | } |
| 2595 | #endif | 2569 | #endif |
| 2596 | 2570 | ||
| 2597 | #ifdef __ARCH_WANT_SYS_CLONE3 | 2571 | #ifdef __ARCH_WANT_SYS_CLONE3 |
| 2598 | 2572 | ||
| 2599 | /* | ||
| 2600 | * copy_thread implementations handle CLONE_SETTLS by reading the TLS value from | ||
| 2601 | * the registers containing the syscall arguments for clone. This doesn't work | ||
| 2602 | * with clone3 since the TLS value is passed in clone_args instead. | ||
| 2603 | */ | ||
| 2604 | #ifndef CONFIG_HAVE_COPY_THREAD_TLS | ||
| 2605 | #error clone3 requires copy_thread_tls support in arch | ||
| 2606 | #endif | ||
| 2607 | |||
| 2608 | noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, | 2573 | noinline static int copy_clone_args_from_user(struct kernel_clone_args *kargs, |
| 2609 | struct clone_args __user *uargs, | 2574 | struct clone_args __user *uargs, |
| 2610 | size_t usize) | 2575 | size_t usize) |
| @@ -2919,7 +2884,7 @@ static int unshare_fd(unsigned long unshare_flags, struct files_struct **new_fdp · 308 unmodified lines | |||
| 2919 | /* | 2884 | /* |
| 2920 | * unshare allows a process to 'unshare' part of the process | 2885 | * unshare allows a process to 'unshare' part of the process |
| 2921 | * context which was originally shared using clone. copy_* | 2886 | * context which was originally shared using clone. copy_* |
| 2922 | * functions used by do_fork() cannot be used here directly | 2887 | * functions used by _do_fork() cannot be used here directly |
| 2923 | * because they modify an inactive task_struct that is being | 2888 | * because they modify an inactive task_struct that is being |
| 2924 | * constructed. Here we are modifying the current, active, | 2889 | * constructed. Here we are modifying the current, active, |
| 2925 | * task_struct. | 2890 | * task_struct. |