···128128extern struct task_struct *cpu_switch_to(struct task_struct *prev,129129 struct task_struct *next);130130131131-/*132132- * Create a new kernel thread133133- */134134-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);135135-136131#define task_pt_regs(p) \137132 ((struct pt_regs *)(THREAD_START_SP + task_stack_page(p)) - 1)138133
+6-8
arch/arm64/include/asm/syscalls.h
···2323/*2424 * System call wrappers implemented in kernel/entry.S.2525 */2626-asmlinkage long sys_execve_wrapper(const char __user *filename,2727- const char __user *const __user *argv,2828- const char __user *const __user *envp);2929-asmlinkage long sys_clone_wrapper(unsigned long clone_flags,3030- unsigned long newsp,3131- void __user *parent_tid,3232- unsigned long tls_val,3333- void __user *child_tid);3426asmlinkage long sys_rt_sigreturn_wrapper(void);3527asmlinkage long sys_sigaltstack_wrapper(const stack_t __user *uss,3628 stack_t __user *uoss);2929+3030+/*3131+ * AArch64 sys_clone implementation has a different prototype than the generic3232+ * one (additional TLS value argument).3333+ */3434+#define sys_clone sys_clone37353836#include <asm-generic/syscalls.h>3937
···594594/*595595 * "slow" syscall return path.596596 */597597-ENTRY(ret_to_user)597597+ret_to_user:598598 disable_irq // disable interrupts599599 ldr x1, [tsk, #TI_FLAGS]600600 and x2, x1, #_TIF_WORK_MASK···611611 */612612ENTRY(ret_from_fork)613613 bl schedule_tail614614- get_thread_info tsk614614+ cbz x19, 1f // not a kernel thread615615+ mov x0, x20616616+ blr x19617617+1: get_thread_info tsk615618 b ret_to_user616619ENDPROC(ret_from_fork)617620···676673/*677674 * Special system call wrappers.678675 */679679-ENTRY(sys_execve_wrapper)680680- mov x3, sp681681- b sys_execve682682-ENDPROC(sys_execve_wrapper)683683-684684-ENTRY(sys_clone_wrapper)685685- mov x5, sp686686- b sys_clone687687-ENDPROC(sys_clone_wrapper)688688-689676ENTRY(sys_rt_sigreturn_wrapper)690677 mov x0, sp691678 b sys_rt_sigreturn
+33-56
arch/arm64/kernel/process.c
···240240 struct pt_regs *childregs = task_pt_regs(p);241241 unsigned long tls = p->thread.tp_value;242242243243- *childregs = *regs;244244- childregs->regs[0] = 0;245245-246246- if (is_compat_thread(task_thread_info(p)))247247- childregs->compat_sp = stack_start;248248- else {249249- /*250250- * Read the current TLS pointer from tpidr_el0 as it may be251251- * out-of-sync with the saved value.252252- */253253- asm("mrs %0, tpidr_el0" : "=r" (tls));254254- childregs->sp = stack_start;255255- }256256-257243 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));258258- p->thread.cpu_context.sp = (unsigned long)childregs;259259- p->thread.cpu_context.pc = (unsigned long)ret_from_fork;260244261261- /* If a TLS pointer was passed to clone, use that for the new thread. */262262- if (clone_flags & CLONE_SETTLS)263263- tls = regs->regs[3];245245+ if (likely(regs)) {246246+ *childregs = *regs;247247+ childregs->regs[0] = 0;248248+ if (is_compat_thread(task_thread_info(p))) {249249+ if (stack_start)250250+ childregs->compat_sp = stack_start;251251+ } else {252252+ /*253253+ * Read the current TLS pointer from tpidr_el0 as it may be254254+ * out-of-sync with the saved value.255255+ */256256+ asm("mrs %0, tpidr_el0" : "=r" (tls));257257+ if (stack_start) {258258+ /* 16-byte aligned stack mandatory on AArch64 */259259+ if (stack_start & 15)260260+ return -EINVAL;261261+ childregs->sp = stack_start;262262+ }263263+ }264264+ /*265265+ * If a TLS pointer was passed to clone (4th argument), use it266266+ * for the new thread.267267+ */268268+ if (clone_flags & CLONE_SETTLS)269269+ tls = regs->regs[3];270270+ } else {271271+ memset(childregs, 0, sizeof(struct pt_regs));272272+ childregs->pstate = PSR_MODE_EL1h;273273+ p->thread.cpu_context.x19 = stack_start;274274+ p->thread.cpu_context.x20 = stk_sz;275275+ }276276+ p->thread.cpu_context.pc = (unsigned long)ret_from_fork;277277+ p->thread.cpu_context.sp = (unsigned long)childregs;264278 p->thread.tp_value = tls;265279266280 ptrace_hw_copy_thread(p);···322308323309 return last;324310}325325-326326-/*327327- * Shuffle the argument into the correct register before calling the328328- * thread function. x1 is the thread argument, x2 is the pointer to329329- * the thread function, and x3 points to the exit function.330330- */331331-extern void kernel_thread_helper(void);332332-asm( ".section .text\n"333333-" .align\n"334334-" .type kernel_thread_helper, #function\n"335335-"kernel_thread_helper:\n"336336-" mov x0, x1\n"337337-" mov x30, x3\n"338338-" br x2\n"339339-" .size kernel_thread_helper, . - kernel_thread_helper\n"340340-" .previous");341341-342342-#define kernel_thread_exit do_exit343343-344344-/*345345- * Create a kernel thread.346346- */347347-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)348348-{349349- struct pt_regs regs;350350-351351- memset(®s, 0, sizeof(regs));352352-353353- regs.regs[1] = (unsigned long)arg;354354- regs.regs[2] = (unsigned long)fn;355355- regs.regs[3] = (unsigned long)kernel_thread_exit;356356- regs.pc = (unsigned long)kernel_thread_helper;357357- regs.pstate = PSR_MODE_EL1h;358358-359359- return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);360360-}361361-EXPORT_SYMBOL(kernel_thread);362311363312unsigned long get_wchan(struct task_struct *p)364313{
+3-73
arch/arm64/kernel/sys.c
···3131 */3232asmlinkage long sys_clone(unsigned long clone_flags, unsigned long newsp,3333 int __user *parent_tidptr, unsigned long tls_val,3434- int __user *child_tidptr, struct pt_regs *regs)3434+ int __user *child_tidptr)3535{3636- if (!newsp)3737- newsp = regs->sp;3838- /* 16-byte aligned stack mandatory on AArch64 */3939- if (newsp & 15)4040- return -EINVAL;4141- return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);3636+ return do_fork(clone_flags, newsp, current_pt_regs(), 0,3737+ parent_tidptr, child_tidptr);4238}4343-4444-/*4545- * sys_execve() executes a new program.4646- */4747-asmlinkage long sys_execve(const char __user *filenamei,4848- const char __user *const __user *argv,4949- const char __user *const __user *envp,5050- struct pt_regs *regs)5151-{5252- long error;5353- struct filename *filename;5454-5555- filename = getname(filenamei);5656- error = PTR_ERR(filename);5757- if (IS_ERR(filename))5858- goto out;5959- error = do_execve(filename->name, argv, envp, regs);6060- putname(filename);6161-out:6262- return error;6363-}6464-6565-int kernel_execve(const char *filename,6666- const char *const argv[],6767- const char *const envp[])6868-{6969- struct pt_regs regs;7070- int ret;7171-7272- memset(®s, 0, sizeof(struct pt_regs));7373- ret = do_execve(filename,7474- (const char __user *const __user *)argv,7575- (const char __user *const __user *)envp, ®s);7676- if (ret < 0)7777- goto out;7878-7979- /*8080- * Save argc to the register structure for userspace.8181- */8282- regs.regs[0] = ret;8383-8484- /*8585- * We were successful. We won't be returning to our caller, but8686- * instead to user space by manipulating the kernel stack.8787- */8888- asm( "add x0, %0, %1\n\t"8989- "mov x1, %2\n\t"9090- "mov x2, %3\n\t"9191- "bl memmove\n\t" /* copy regs to top of stack */9292- "mov x27, #0\n\t" /* not a syscall */9393- "mov x28, %0\n\t" /* thread structure */9494- "mov sp, x0\n\t" /* reposition stack pointer */9595- "b ret_to_user"9696- :9797- : "r" (current_thread_info()),9898- "Ir" (THREAD_START_SP - sizeof(regs)),9999- "r" (®s),100100- "Ir" (sizeof(regs))101101- : "x0", "x1", "x2", "x27", "x28", "x30", "memory");102102-103103- out:104104- return ret;105105-}106106-EXPORT_SYMBOL(kernel_execve);1073910840asmlinkage long sys_mmap(unsigned long addr, unsigned long len,10941 unsigned long prot, unsigned long flags,···50118/*51119 * Wrappers to pass the pt_regs argument.52120 */5353-#define sys_execve sys_execve_wrapper5454-#define sys_clone sys_clone_wrapper55121#define sys_rt_sigreturn sys_rt_sigreturn_wrapper56122#define sys_sigaltstack sys_sigaltstack_wrapper57123
-19
arch/arm64/kernel/sys32.S
···2626/*2727 * System call wrappers for the AArch32 compatibility layer.2828 */2929-compat_sys_fork_wrapper:3030- mov x0, sp3131- b compat_sys_fork3232-ENDPROC(compat_sys_fork_wrapper)3333-3434-compat_sys_vfork_wrapper:3535- mov x0, sp3636- b compat_sys_vfork3737-ENDPROC(compat_sys_vfork_wrapper)3838-3939-compat_sys_execve_wrapper:4040- mov x3, sp4141- b compat_sys_execve4242-ENDPROC(compat_sys_execve_wrapper)4343-4444-compat_sys_clone_wrapper:4545- mov x5, sp4646- b compat_sys_clone4747-ENDPROC(compat_sys_clone_wrapper)48294930compat_sys_sigreturn_wrapper:5031 mov x0, sp
+5-33
arch/arm64/kernel/sys_compat.c
···2828#include <asm/cacheflush.h>2929#include <asm/unistd32.h>30303131-asmlinkage int compat_sys_fork(struct pt_regs *regs)3131+asmlinkage int compat_sys_fork(void)3232{3333- return do_fork(SIGCHLD, regs->compat_sp, regs, 0, NULL, NULL);3333+ return do_fork(SIGCHLD, 0, current_pt_regs(), 0, NULL, NULL);3434}35353636-asmlinkage int compat_sys_clone(unsigned long clone_flags, unsigned long newsp,3737- int __user *parent_tidptr, int tls_val,3838- int __user *child_tidptr, struct pt_regs *regs)3636+asmlinkage int compat_sys_vfork(void)3937{4040- if (!newsp)4141- newsp = regs->compat_sp;4242-4343- return do_fork(clone_flags, newsp, regs, 0, parent_tidptr, child_tidptr);4444-}4545-4646-asmlinkage int compat_sys_vfork(struct pt_regs *regs)4747-{4848- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->compat_sp,4949- regs, 0, NULL, NULL);5050-}5151-5252-asmlinkage int compat_sys_execve(const char __user *filenamei,5353- compat_uptr_t argv, compat_uptr_t envp,5454- struct pt_regs *regs)5555-{5656- int error;5757- struct filename *filename;5858-5959- filename = getname(filenamei);6060- error = PTR_ERR(filename);6161- if (IS_ERR(filename))6262- goto out;6363- error = compat_do_execve(filename->name, compat_ptr(argv),6464- compat_ptr(envp), regs);6565- putname(filename);6666-out:6767- return error;3838+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,3939+ current_pt_regs(), 0, NULL, NULL);6840}69417042asmlinkage int compat_sys_sched_rr_get_interval(compat_pid_t pid,
+2
arch/avr32/Kconfig
···1717 select GENERIC_CLOCKEVENTS1818 select HAVE_MOD_ARCH_SPECIFIC1919 select MODULES_USE_ELF_RELA2020+ select GENERIC_KERNEL_THREAD2121+ select GENERIC_KERNEL_EXECVE2022 help2123 AVR32 is a high-performance 32-bit RISC microprocessor core,2224 designed for cost-sensitive embedded applications, with particular
-3
arch/avr32/include/asm/processor.h
···142142/* Free all resources held by a thread */143143extern void release_thread(struct task_struct *);144144145145-/* Create a kernel thread without removing it from tasklists */146146-extern int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);147147-148145/* Return saved PC of a blocked thread */149146#define thread_saved_pc(tsk) ((tsk)->thread.cpu_context.pc)150147
···6969}70707171/*7272- * PC is actually discarded when returning from a system call -- the7373- * return address must be stored in LR. This function will make sure7474- * LR points to do_exit before starting the thread.7575- *7676- * Also, when returning from fork(), r12 is 0, so we must copy the7777- * argument as well.7878- *7979- * r0 : The argument to the main thread function8080- * r1 : The address of do_exit8181- * r2 : The address of the main thread function8282- */8383-asmlinkage extern void kernel_thread_helper(void);8484-__asm__(" .type kernel_thread_helper, @function\n"8585- "kernel_thread_helper:\n"8686- " mov r12, r0\n"8787- " mov lr, r2\n"8888- " mov pc, r1\n"8989- " .size kernel_thread_helper, . - kernel_thread_helper");9090-9191-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)9292-{9393- struct pt_regs regs;9494-9595- memset(®s, 0, sizeof(regs));9696-9797- regs.r0 = (unsigned long)arg;9898- regs.r1 = (unsigned long)fn;9999- regs.r2 = (unsigned long)do_exit;100100- regs.lr = (unsigned long)kernel_thread_helper;101101- regs.pc = (unsigned long)kernel_thread_helper;102102- regs.sr = MODE_SUPERVISOR;103103-104104- return do_fork(flags | CLONE_VM | CLONE_UNTRACED,105105- 0, ®s, 0, NULL, NULL);106106-}107107-EXPORT_SYMBOL(kernel_thread);108108-109109-/*11072 * Free current thread data structures etc11173 */11274void exit_thread(void)···294332}295333296334asmlinkage void ret_from_fork(void);335335+asmlinkage void ret_from_kernel_thread(void);336336+asmlinkage void syscall_return(void);297337298338int copy_thread(unsigned long clone_flags, unsigned long usp,299299- unsigned long unused,339339+ unsigned long arg,300340 struct task_struct *p, struct pt_regs *regs)301341{302302- struct pt_regs *childregs;342342+ struct pt_regs *childregs = task_pt_regs(p);303343304304- childregs = ((struct pt_regs *)(THREAD_SIZE + (unsigned long)task_stack_page(p))) - 1;305305- *childregs = *regs;306306-307307- if (user_mode(regs))344344+ if (unlikely(!regs)) {345345+ memset(childregs, 0, sizeof(struct pt_regs));346346+ p->thread.cpu_context.r0 = arg;347347+ p->thread.cpu_context.r1 = usp; /* fn */348348+ p->thread.cpu_context.r2 = syscall_return;349349+ p->thread.cpu_context.pc = (unsigned long)ret_from_kernel_thread;350350+ childregs->sr = MODE_SUPERVISOR;351351+ } else {352352+ *childregs = *regs;308353 childregs->sp = usp;309309- else310310- childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;311311-312312- childregs->r12 = 0; /* Set return value for child */354354+ childregs->r12 = 0; /* Set return value for child */355355+ p->thread.cpu_context.pc = (unsigned long)ret_from_fork;356356+ }313357314358 p->thread.cpu_context.sr = MODE_SUPERVISOR | SR_GM;315359 p->thread.cpu_context.ksp = (unsigned long)childregs;316316- p->thread.cpu_context.pc = (unsigned long)ret_from_fork;317360318361 clear_tsk_thread_flag(p, TIF_DEBUG);319362 if ((clone_flags & CLONE_PTRACE) && test_thread_flag(TIF_DEBUG))···348381 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->sp, regs,349382 0, NULL, NULL);350383}351351-352352-asmlinkage int sys_execve(const char __user *ufilename,353353- const char __user *const __user *uargv,354354- const char __user *const __user *uenvp,355355- struct pt_regs *regs)356356-{357357- int error;358358- struct filename *filename;359359-360360- filename = getname(ufilename);361361- error = PTR_ERR(filename);362362- if (IS_ERR(filename))363363- goto out;364364-365365- error = do_execve(filename->name, uargv, uenvp, regs);366366- putname(filename);367367-368368-out:369369- return error;370370-}371371-372384373385/*374386 * This function is supposed to answer the question "who called
-24
arch/avr32/kernel/sys_avr32.c
···11-/*22- * Copyright (C) 2004-2006 Atmel Corporation33- *44- * This program is free software; you can redistribute it and/or modify55- * it under the terms of the GNU General Public License version 2 as66- * published by the Free Software Foundation.77- */88-#include <linux/unistd.h>99-1010-int kernel_execve(const char *file,1111- const char *const *argv,1212- const char *const *envp)1313-{1414- register long scno asm("r8") = __NR_execve;1515- register long sc1 asm("r12") = (long)file;1616- register long sc2 asm("r11") = (long)argv;1717- register long sc3 asm("r10") = (long)envp;1818-1919- asm volatile("scall"2020- : "=r"(sc1)2121- : "r"(scno), "0"(sc1), "r"(sc2), "r"(sc3)2222- : "cc", "memory");2323- return sc1;2424-}
···4545 select ARCH_USES_GETTIMEOFFSET if !GENERIC_CLOCKEVENTS4646 select HAVE_MOD_ARCH_SPECIFIC4747 select MODULES_USE_ELF_RELA4848+ select GENERIC_KERNEL_THREAD4949+ select GENERIC_KERNEL_EXECVE48504951config GENERIC_CSUM5052 def_bool y
-2
arch/blackfin/include/asm/processor.h
···7575{7676}77777878-extern int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags);7979-8078/*8179 * Free current thread data structures etc..8280 */
···1414 * more details.1515 */16161717-#define __ARCH_WANT_KERNEL_EXECVE1817#define __ARCH_WANT_SYS_EXECVE19182019/* Use the standard ABI for syscalls. */
+1-11
arch/c6x/kernel/entry.S
···4134130:414414 B .S2 B10 /* call fn */415415 LDW .D2T1 *+SP(REGS_A1+8),A4 /* get arg */416416- MVKL .S2 sys_exit,B11417417- MVKH .S2 sys_exit,B11418418- ADDKPC .S2 0f,B3,1419419-0:420420- BNOP .S2 B11,5 /* jump to sys_exit */416416+ ADDKPC .S2 ret_from_fork_2,B3,3421417ENDPROC(ret_from_kernel_thread)422422-423423-ENTRY(ret_from_kernel_execve)424424- GET_THREAD_INFO A12425425- BNOP .S2 syscall_exit,4426426- ADD .D2X A4,-8,SP427427-ENDPROC(ret_from_kernel_execve)428418429419 ;;430420 ;; These are the interrupt handlers, responsible for calling __do_IRQ()
+2
arch/cris/Kconfig
···4949 select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V325050 select GENERIC_CMOS_UPDATE5151 select MODULES_USE_ELF_RELA5252+ select GENERIC_KERNEL_THREAD5353+ select GENERIC_KERNEL_EXECVE52545355config HZ5456 int
+9-8
arch/cris/arch-v10/kernel/entry.S
···3535 .globl system_call3636 .globl ret_from_intr3737 .globl ret_from_fork3838+ .globl ret_from_kernel_thread3839 .globl resume3940 .globl multiple_interrupt4041 .globl hwbreakpoint···8281 jsr schedule_tail8382 ba ret_from_sys_call8483 nop8585-8484+8585+ret_from_kernel_thread:8686+ jsr schedule_tail8787+ move.d $r2, $r10 ; argument is here8888+ jsr $r1 ; call the payload8989+ moveq 0, $r9 ; no syscall restarts, TYVM...9090+ ba ret_from_sys_call9191+8692ret_from_intr:8793 ;; check for resched if preemptive kernel or if we're going back to user-mode 8894 ;; this test matches the user_regs(regs) macro···593585 pop $r0 ; Restore r0. 594586 ba do_sigtrap ; SIGTRAP the offending process. 595587 pop $dccr ; Restore dccr in delay slot.596596-597597- .global kernel_execve598598-kernel_execve:599599- move.d __NR_execve, $r9600600- break 13601601- ret602602- nop603588604589 .data605590
+24-82
arch/cris/arch-v10/kernel/process.c
···1717#include <arch/svinto.h>1818#include <linux/init.h>1919#include <arch/system.h>2020+#include <asm/ptrace.h>20212122#ifdef CONFIG_ETRAX_GPIO2223void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */···8281 return task_pt_regs(t)->irp;8382}84838585-static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)8686-{8787- fn(arg);8888- do_exit(-1); /* Should never be called, return bad exit value */8989-}9090-9191-/*9292- * Create a kernel thread9393- */9494-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)9595-{9696- struct pt_regs regs;9797-9898- memset(®s, 0, sizeof(regs));9999-100100- /* Don't use r10 since that is set to 0 in copy_thread */101101- regs.r11 = (unsigned long)fn;102102- regs.r12 = (unsigned long)arg;103103- regs.irp = (unsigned long)kernel_thread_helper;104104- regs.dccr = 1 << I_DCCR_BITNR;105105-106106- /* Ok, create the new process.. */107107- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);108108-}109109-11084/* setup the child's kernel stack with a pt_regs and switch_stack on it.11185 * it will be un-nested during _resume and _ret_from_sys_call when the11286 * new thread is scheduled.···91115 *92116 */93117asmlinkage void ret_from_fork(void);118118+asmlinkage void ret_from_kernel_thread(void);9411995120int copy_thread(unsigned long clone_flags, unsigned long usp,9696- unsigned long unused,121121+ unsigned long arg,97122 struct task_struct *p, struct pt_regs *regs)98123{9999- struct pt_regs * childregs;100100- struct switch_stack *swstack;124124+ struct pt_regs *childregs = task_pt_regs(p);125125+ struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1;101126102127 /* put the pt_regs structure at the end of the new kernel stack page and fix it up103128 * remember that the task_struct doubles as the kernel stack for the task104129 */105130106106- childregs = task_pt_regs(p);107107-131131+ if (unlikely(p->flags & PF_KTHREAD)) {132132+ memset(swstack, 0,133133+ sizeof(struct switch_stack) + sizeof(struct pt_regs));134134+ swstack->r1 = usp;135135+ swstack->r2 = arg;136136+ childregs->dccr = 1 << I_DCCR_BITNR;137137+ swstack->return_ip = (unsigned long) ret_from_kernel_thread;138138+ p->thread.ksp = (unsigned long) swstack;139139+ p->thread.usp = 0;140140+ return 0;141141+ }108142 *childregs = *regs; /* struct copy of pt_regs */109109-110110- p->set_child_tid = p->clear_child_tid = NULL;111143112144 childregs->r10 = 0; /* child returns 0 after a fork/clone */113113-114114- /* put the switch stack right below the pt_regs */115145116116- swstack = ((struct switch_stack *)childregs) - 1;146146+ /* put the switch stack right below the pt_regs */117147118148 swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */119149···129147130148 /* fix the user-mode stackpointer */131149132132- p->thread.usp = usp; 150150+ p->thread.usp = usp;133151134152 /* and the kernel-mode one */135153···143161 return 0;144162}145163146146-/* 147147- * Be aware of the "magic" 7th argument in the four system-calls below.148148- * They need the latest stackframe, which is put as the 7th argument by149149- * entry.S. The previous arguments are dummies or actually used, but need150150- * to be defined to reach the 7th argument.151151- *152152- * N.B.: Another method to get the stackframe is to use current_regs(). But153153- * it returns the latest stack-frame stacked when going from _user mode_ and154154- * some of these (at least sys_clone) are called from kernel-mode sometimes155155- * (for example during kernel_thread, above) and thus cannot use it. Thus,156156- * to be sure not to get any surprises, we use the method for the other calls157157- * as well.158158- */159159-160160-asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,161161- struct pt_regs *regs)164164+asmlinkage int sys_fork(void)162165{163163- return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);166166+ return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);164167}165168166169/* if newusp is 0, we just grab the old usp */167170/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */168171asmlinkage int sys_clone(unsigned long newusp, unsigned long flags,169169- int* parent_tid, int* child_tid, long mof, long srp,170170- struct pt_regs *regs)172172+ int* parent_tid, int* child_tid)171173{172174 if (!newusp)173175 newusp = rdusp();174174- return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);176176+ return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid);175177}176178177179/* vfork is a system call in i386 because of register-pressure - maybe178180 * we can remove it and handle it in libc but we put it here until then.179181 */180182181181-asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,182182- struct pt_regs *regs)183183+asmlinkage int sys_vfork(void)183184{184184- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);185185-}186186-187187-/*188188- * sys_execve() executes a new program.189189- */190190-asmlinkage int sys_execve(const char *fname,191191- const char *const *argv,192192- const char *const *envp,193193- long r13, long mof, long srp, 194194- struct pt_regs *regs)195195-{196196- int error;197197- struct filename *filename;198198-199199- filename = getname(fname);200200- error = PTR_ERR(filename);201201-202202- if (IS_ERR(filename))203203- goto out;204204- error = do_execve(filename->name, argv, envp, regs);205205- putname(filename);206206- out:207207- return error;185185+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);208186}209187210188unsigned long get_wchan(struct task_struct *p)
···1616#include <hwregs/reg_map.h>1717#include <hwregs/timer_defs.h>1818#include <hwregs/intr_vect_defs.h>1919+#include <asm/ptrace.h>19202021extern void stop_watchdog(void);2122···9594 return task_pt_regs(t)->erp;9695}97969898-static void9999-kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg)100100-{101101- fn(arg);102102- do_exit(-1); /* Should never be called, return bad exit value. */103103-}104104-105105-/* Create a kernel thread. */106106-int107107-kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)108108-{109109- struct pt_regs regs;110110-111111- memset(®s, 0, sizeof(regs));112112-113113- /* Don't use r10 since that is set to 0 in copy_thread. */114114- regs.r11 = (unsigned long) fn;115115- regs.r12 = (unsigned long) arg;116116- regs.erp = (unsigned long) kernel_thread_helper;117117- regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);118118-119119- /* Create the new process. */120120- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);121121-}122122-12397/*12498 * Setup the child's kernel stack with a pt_regs and call switch_stack() on it.12599 * It will be unnested during _resume and _ret_from_sys_call when the new thread···105129 */106130107131extern asmlinkage void ret_from_fork(void);132132+extern asmlinkage void ret_from_kernel_thread(void);108133109134int110135copy_thread(unsigned long clone_flags, unsigned long usp,111111- unsigned long unused,136136+ unsigned long arg,112137 struct task_struct *p, struct pt_regs *regs)113138{114114- struct pt_regs *childregs;115115- struct switch_stack *swstack;139139+ struct pt_regs *childregs = task_pt_regs(p);140140+ struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1;116141117142 /*118143 * Put the pt_regs structure at the end of the new kernel stack page and119144 * fix it up. Note: the task_struct doubles as the kernel stack for the120145 * task.121146 */122122- childregs = task_pt_regs(p);147147+ if (unlikely(p->flags & PF_KTHREAD)) {148148+ memset(swstack, 0,149149+ sizeof(struct switch_stack) + sizeof(struct pt_regs));150150+ swstack->r1 = usp;151151+ swstack->r2 = arg;152152+ childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT);153153+ swstack->return_ip = (unsigned long) ret_from_kernel_thread;154154+ p->thread.ksp = (unsigned long) swstack;155155+ p->thread.usp = 0;156156+ return 0;157157+ }123158 *childregs = *regs; /* Struct copy of pt_regs. */124124- p->set_child_tid = p->clear_child_tid = NULL;125159 childregs->r10 = 0; /* Child returns 0 after a fork/clone. */126160127161 /* Set a new TLS ?···142156 }143157144158 /* Put the switch stack right below the pt_regs. */145145- swstack = ((struct switch_stack *) childregs) - 1;146159147160 /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */148161 swstack->r9 = 0;···159174 return 0;160175}161176162162-/*163163- * Be aware of the "magic" 7th argument in the four system-calls below.164164- * They need the latest stackframe, which is put as the 7th argument by165165- * entry.S. The previous arguments are dummies or actually used, but need166166- * to be defined to reach the 7th argument.167167- *168168- * N.B.: Another method to get the stackframe is to use current_regs(). But169169- * it returns the latest stack-frame stacked when going from _user mode_ and170170- * some of these (at least sys_clone) are called from kernel-mode sometimes171171- * (for example during kernel_thread, above) and thus cannot use it. Thus,172172- * to be sure not to get any surprises, we use the method for the other calls173173- * as well.174174- */175177asmlinkage int176176-sys_fork(long r10, long r11, long r12, long r13, long mof, long srp,177177- struct pt_regs *regs)178178+sys_fork(void)178179{179179- return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL);180180+ return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);180181}181182182183/* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */183184asmlinkage int184185sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid,185185- unsigned long tls, long srp, struct pt_regs *regs)186186+ unsigned long tls)186187{187188 if (!newusp)188189 newusp = rdusp();189190190190- return do_fork(flags, newusp, regs, 0, parent_tid, child_tid);191191+ return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid);191192}192193193194/*···181210 * we can remove it and handle it in libc but we put it here until then.182211 */183212asmlinkage int184184-sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp,185185- struct pt_regs *regs)213213+sys_vfork(void)186214{187187- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL);188188-}189189-190190-/* sys_execve() executes a new program. */191191-asmlinkage int192192-sys_execve(const char *fname,193193- const char *const *argv,194194- const char *const *envp, long r13, long mof, long srp,195195- struct pt_regs *regs)196196-{197197- int error;198198- struct filename *filename;199199-200200- filename = getname(fname);201201- error = PTR_ERR(filename);202202-203203- if (IS_ERR(filename))204204- goto out;205205-206206- error = do_execve(filename->name, argv, envp, regs);207207- putname(filename);208208- out:209209- return error;215215+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL);210216}211217212218unsigned long
-2
arch/cris/include/asm/processor.h
···4949#define task_pt_regs(task) user_regs(task_thread_info(task))5050#define current_regs() task_pt_regs(current)51515252-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);5353-5452unsigned long get_wchan(struct task_struct *p);55535654#define KSTK_ESP(tsk) ((tsk) == current ? rdusp() : (tsk)->thread.usp)
···107107{108108}109109110110-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);111111-112110/*113111 * Free current thread data structures etc..114112 */
···4646 ((regs->pc)&0xffffff)-2,regs->orig_er0,regs->er1,regs->er2,regs->er3,regs->er0);4747}4848#endif4949-5050-/*5151- * Do a system call from kernel instead of calling sys_execve so we5252- * end up with proper pt_regs.5353- */5454-asmlinkage5555-int kernel_execve(const char *filename,5656- const char *const argv[],5757- const char *const envp[])5858-{5959- register long res __asm__("er0");6060- register const char *const *_c __asm__("er3") = envp;6161- register const char *const *_b __asm__("er2") = argv;6262- register const char * _a __asm__("er1") = filename;6363- __asm__ __volatile__ ("mov.l %1,er0\n\t"6464- "trapa #0\n\t"6565- : "=r" (res)6666- : "g" (__NR_execve),6767- "g" (_a),6868- "g" (_b),6969- "g" (_c)7070- : "cc", "memory");7171- return res;7272-}7373-7474-
+2
arch/hexagon/Kconfig
···3131 select GENERIC_CLOCKEVENTS3232 select GENERIC_CLOCKEVENTS_BROADCAST3333 select MODULES_USE_ELF_RELA3434+ select GENERIC_KERNEL_THREAD3535+ select GENERIC_KERNEL_EXECVE3436 ---help---3537 Qualcomm Hexagon is a processor architecture designed for high3638 performance and low power across a wide variety of applications.
-1
arch/hexagon/include/asm/processor.h
···3434struct task_struct;35353636/* this is defined in arch/process.c */3737-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);3837extern unsigned long thread_saved_pc(struct task_struct *tsk);39384039extern void start_thread(struct pt_regs *, unsigned long, unsigned long);
···2626#include <linux/slab.h>27272828/*2929- * Kernel thread creation. The desired kernel function is "wrapped"3030- * in the kernel_thread_helper function, which does cleanup3131- * afterwards.3232- */3333-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))3434-{3535- do_exit(fn(arg));3636-}3737-3838-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)3939-{4040- struct pt_regs regs;4141-4242- memset(®s, 0, sizeof(regs));4343- /*4444- * Yes, we're exploting illicit knowledge of the ABI here.4545- */4646- regs.r00 = (unsigned long) arg;4747- regs.r01 = (unsigned long) fn;4848- pt_set_elr(®s, (unsigned long)kernel_thread_helper);4949- pt_set_kmode(®s);5050-5151- return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);5252-}5353-EXPORT_SYMBOL(kernel_thread);5454-5555-/*5629 * Program thread launch. Often defined as a macro in processor.h,5730 * but we're shooting for a small footprint and it's not an inner-loop5831 * performance-critical operation.···87114 * Copy architecture-specific thread state88115 */89116int copy_thread(unsigned long clone_flags, unsigned long usp,9090- unsigned long unused, struct task_struct *p,117117+ unsigned long arg, struct task_struct *p,91118 struct pt_regs *regs)92119{93120 struct thread_info *ti = task_thread_info(p);···98125 childregs = (struct pt_regs *) (((unsigned long) ti + THREAD_SIZE) -99126 sizeof(*childregs));100127101101- memcpy(childregs, regs, sizeof(*childregs));102128 ti->regs = childregs;103129104130 /*105131 * Establish kernel stack pointer and initial PC for new thread132132+ * Note that unlike the usual situation, we do not copy the133133+ * parent's callee-saved here; those are in pt_regs and whatever134134+ * we leave here will be overridden on return to userland.106135 */107136 ss = (struct hexagon_switch_stack *) ((unsigned long) childregs -108137 sizeof(*ss));109138 ss->lr = (unsigned long)ret_from_fork;110139 p->thread.switch_sp = ss;111111-112112- /* If User mode thread, set pt_reg stack pointer as per parameter */113113- if (user_mode(childregs)) {114114- pt_set_rte_sp(childregs, usp);115115-116116- /* Child sees zero return value */117117- childregs->r00 = 0;118118-119119- /*120120- * The clone syscall has the C signature:121121- * int [r0] clone(int flags [r0],122122- * void *child_frame [r1],123123- * void *parent_tid [r2],124124- * void *child_tid [r3],125125- * void *thread_control_block [r4]);126126- * ugp is used to provide TLS support.127127- */128128- if (clone_flags & CLONE_SETTLS)129129- childregs->ugp = childregs->r04;130130-131131- /*132132- * Parent sees new pid -- not necessary, not even possible at133133- * this point in the fork process134134- * Might also want to set things like ti->addr_limit135135- */136136- } else {137137- /*138138- * If kernel thread, resume stack is kernel stack base.139139- * Note that this is pointer arithmetic on pt_regs *140140- */141141- pt_set_rte_sp(childregs, (unsigned long)(childregs + 1));142142- /*143143- * We need the current thread_info fast path pointer144144- * set up in pt_regs. The register to be used is145145- * parametric for assembler code, but the mechanism146146- * doesn't drop neatly into C. Needs to be fixed.147147- */148148- childregs->THREADINFO_REG = (unsigned long) ti;140140+ if (unlikely(p->flags & PF_KTHREAD)) {141141+ memset(childregs, 0, sizeof(struct pt_regs));142142+ /* r24 <- fn, r25 <- arg */143143+ ss->r2524 = usp | ((u64)arg << 32);144144+ pt_set_kmode(childregs);145145+ return 0;149146 }147147+ memcpy(childregs, regs, sizeof(*childregs));148148+ ss->r2524 = 0;149149+150150+ pt_set_rte_sp(childregs, usp);151151+152152+ /* Child sees zero return value */153153+ childregs->r00 = 0;150154151155 /*152152- * thread_info pointer is pulled out of task_struct "stack"153153- * field on switch_to.156156+ * The clone syscall has the C signature:157157+ * int [r0] clone(int flags [r0],158158+ * void *child_frame [r1],159159+ * void *parent_tid [r2],160160+ * void *child_tid [r3],161161+ * void *thread_control_block [r4]);162162+ * ugp is used to provide TLS support.154163 */155155- p->stack = (void *)ti;164164+ if (clone_flags & CLONE_SETTLS)165165+ childregs->ugp = childregs->r04;166166+167167+ /*168168+ * Parent sees new pid -- not necessary, not even possible at169169+ * this point in the fork process170170+ * Might also want to set things like ti->addr_limit171171+ */156172157173 return 0;158174}
···4242 select GENERIC_TIME_VSYSCALL_OLD4343 select HAVE_MOD_ARCH_SPECIFIC4444 select MODULES_USE_ELF_RELA4545+ select GENERIC_KERNEL_THREAD4646+ select GENERIC_KERNEL_EXECVE4547 default y4648 help4749 The Itanium Processor Family is Intel's 64-bit successor to
-16
arch/ia64/include/asm/processor.h
···340340 */341341#define release_thread(dead_task)342342343343-/*344344- * This is the mechanism for creating a new kernel thread.345345- *346346- * NOTE 1: Only a kernel-only process (ie the swapper or direct347347- * descendants who haven't done an "execve()") should use this: it348348- * will work within a system call from a "real" process, but the349349- * process memory space will not be free'd until both the parent and350350- * the child have exited.351351- *352352- * NOTE 2: This MUST NOT be an inlined function. Otherwise, we get353353- * into trouble in init/main.c when the child thread returns to354354- * do_basic_setup() and the timing is such that free_initmem() has355355- * been called already.356356- */357357-extern pid_t kernel_thread (int (*fn)(void *), void *arg, unsigned long flags);358358-359343/* Get wait channel for task P. */360344extern unsigned long get_wchan (struct task_struct *p);361345
···118118/* Free all resources held by a thread. */119119extern void release_thread(struct task_struct *);120120121121-/*122122- * create a kernel thread without removing it from tasklists123123- */124124-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);125125-126121/* Copy and release all segment info associated with a VM */127122extern void copy_segments(struct task_struct *p, struct mm_struct * mm);128123extern void release_segments(struct mm_struct * mm);
···293293 swi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)) /* save stack */294294 addi r14, r14, 4 /* return address is 4 byte after call */295295296296- mfs r1, rmsr297297- nop298298- andi r1, r1, MSR_UMS299299- bnei r1, 1f300300-301301-/* Kernel-mode state save - kernel execve */302302- lwi r1, r0, TOPHYS(PER_CPU(ENTRY_SP)); /* Reload kernel stack-ptr*/303303- tophys(r1,r1);304304-305305- addik r1, r1, -PT_SIZE; /* Make room on the stack. */306306- SAVE_REGS307307-308308- swi r1, r1, PT_MODE; /* pt_regs -> kernel mode */309309- brid 2f;310310- nop; /* Fill delay slot */311311-312312-/* User-mode state save. */313313-1:314296 lwi r1, r0, TOPHYS(PER_CPU(CURRENT_SAVE)); /* get saved current */315297 tophys(r1,r1);316298 lwi r1, r1, TS_THREAD_INFO; /* get stack from task_struct */···461479 saved context). */462480C_ENTRY(ret_from_fork):463481 bralid r15, schedule_tail; /* ...which is schedule_tail's arg */464464- add r3, r5, r0; /* switch_thread returns the prev task */482482+ add r5, r3, r0; /* switch_thread returns the prev task */465483 /* ( in the delay slot ) */466484 brid ret_from_trap; /* Do normal trap return */467485 add r3, r0, r0; /* Child's fork call should return 0. */486486+487487+C_ENTRY(ret_from_kernel_thread):488488+ bralid r15, schedule_tail; /* ...which is schedule_tail's arg */489489+ add r5, r3, r0; /* switch_thread returns the prev task */490490+ /* ( in the delay slot ) */491491+ brald r15, r20 /* fn was left in r20 */492492+ addk r5, r0, r19 /* ... and argument - in r19 */493493+ brid ret_from_trap494494+ add r3, r0, r0468495469496C_ENTRY(sys_vfork):470497 brid microblaze_vfork /* Do real work (tail-call) */···488497 /* do_fork will pick up TLS from regs->r10. */489498 brid do_fork /* Do real work (tail-call) */490499 add r8, r0, r0; /* Arg 3: (unused) */491491-492492-C_ENTRY(sys_execve):493493- brid microblaze_execve; /* Do real work (tail-call).*/494494- addik r8, r1, 0; /* add user context as 4th arg */495500496501C_ENTRY(sys_rt_sigreturn_wrapper):497502 brid sys_rt_sigreturn /* Do real work */
+21-51
arch/microblaze/kernel/process.c
···119119}120120121121int copy_thread(unsigned long clone_flags, unsigned long usp,122122- unsigned long unused,122122+ unsigned long arg,123123 struct task_struct *p, struct pt_regs *regs)124124{125125 struct pt_regs *childregs = task_pt_regs(p);126126 struct thread_info *ti = task_thread_info(p);127127128128+ if (unlikely(p->flags & PF_KTHREAD)) {129129+ /* if we're creating a new kernel thread then just zeroing all130130+ * the registers. That's OK for a brand new thread.*/131131+ memset(childregs, 0, sizeof(struct pt_regs));132132+ memset(&ti->cpu_context, 0, sizeof(struct cpu_context));133133+ ti->cpu_context.r1 = (unsigned long)childregs;134134+ ti->cpu_context.r20 = (unsigned long)usp; /* fn */135135+ ti->cpu_context.r19 = (unsigned long)arg;136136+ childregs->pt_mode = 1;137137+ local_save_flags(childregs->msr);138138+#ifdef CONFIG_MMU139139+ ti->cpu_context.msr = childregs->msr & ~MSR_IE;140140+#endif141141+ ti->cpu_context.r15 = (unsigned long)ret_from_kernel_thread - 8;142142+ return 0;143143+ }128144 *childregs = *regs;129129- if (user_mode(regs))130130- childregs->r1 = usp;131131- else132132- childregs->r1 = ((unsigned long) ti) + THREAD_SIZE;145145+ childregs->r1 = usp;133146134134-#ifndef CONFIG_MMU135147 memset(&ti->cpu_context, 0, sizeof(struct cpu_context));136148 ti->cpu_context.r1 = (unsigned long)childregs;149149+#ifndef CONFIG_MMU137150 ti->cpu_context.msr = (unsigned long)childregs->msr;138151#else152152+ childregs->msr |= MSR_UMS;139153140140- /* if creating a kernel thread then update the current reg (we don't141141- * want to use the parent's value when restoring by POP_STATE) */142142- if (kernel_mode(regs))143143- /* save new current on stack to use POP_STATE */144144- childregs->CURRENT_TASK = (unsigned long)p;145145- /* if returning to user then use the parent's value of this register */146146-147147- /* if we're creating a new kernel thread then just zeroing all148148- * the registers. That's OK for a brand new thread.*/149149- /* Pls. note that some of them will be restored in POP_STATE */150150- if (kernel_mode(regs))151151- memset(&ti->cpu_context, 0, sizeof(struct cpu_context));152152- /* if this thread is created for fork/vfork/clone, then we want to153153- * restore all the parent's context */154154- /* in addition to the registers which will be restored by POP_STATE */155155- else {156156- ti->cpu_context = *(struct cpu_context *)regs;157157- childregs->msr |= MSR_UMS;158158- }159159-160160- /* FIXME STATE_SAVE_PT_OFFSET; */161161- ti->cpu_context.r1 = (unsigned long)childregs;162154 /* we should consider the fact that childregs is a copy of the parent163155 * regs which were saved immediately after entering the kernel state164156 * before enabling VM. This MSR will be restored in switch_to and···201209}202210#endif203211204204-static void kernel_thread_helper(int (*fn)(void *), void *arg)205205-{206206- fn(arg);207207- do_exit(-1);208208-}209209-210210-int kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)211211-{212212- struct pt_regs regs;213213-214214- memset(®s, 0, sizeof(regs));215215- /* store them in non-volatile registers */216216- regs.r5 = (unsigned long)fn;217217- regs.r6 = (unsigned long)arg;218218- local_save_flags(regs.msr);219219- regs.pc = (unsigned long)kernel_thread_helper;220220- regs.pt_mode = 1;221221-222222- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,223223- ®s, 0, NULL, NULL);224224-}225225-EXPORT_SYMBOL_GPL(kernel_thread);226226-227212unsigned long get_wchan(struct task_struct *p)228213{229214/* TBD (used by procfs) */···215246 regs->pt_mode = 0;216247#ifdef CONFIG_MMU217248 regs->msr |= MSR_UMS;249249+ regs->msr &= ~MSR_VM;218250#endif219251}220252
-39
arch/microblaze/kernel/sys_microblaze.c
···4848 return do_fork(flags, stack, regs, 0, NULL, NULL);4949}50505151-asmlinkage long microblaze_execve(const char __user *filenamei,5252- const char __user *const __user *argv,5353- const char __user *const __user *envp,5454- struct pt_regs *regs)5555-{5656- int error;5757- struct filename *filename;5858-5959- filename = getname(filenamei);6060- error = PTR_ERR(filename);6161- if (IS_ERR(filename))6262- goto out;6363- error = do_execve(filename->name, argv, envp, regs);6464- putname(filename);6565-out:6666- return error;6767-}6868-6951asmlinkage long sys_mmap(unsigned long addr, unsigned long len,7052 unsigned long prot, unsigned long flags,7153 unsigned long fd, off_t pgoff)···5674 return -EINVAL;57755876 return sys_mmap_pgoff(addr, len, prot, flags, fd, pgoff >> PAGE_SHIFT);5959-}6060-6161-/*6262- * Do a system call from kernel instead of calling sys_execve so we6363- * end up with proper pt_regs.6464- */6565-int kernel_execve(const char *filename,6666- const char *const argv[],6767- const char *const envp[])6868-{6969- register const char *__a __asm__("r5") = filename;7070- register const void *__b __asm__("r6") = argv;7171- register const void *__c __asm__("r7") = envp;7272- register unsigned long __syscall __asm__("r12") = __NR_execve;7373- register unsigned long __ret __asm__("r3");7474- __asm__ __volatile__ ("brki r14, 0x8"7575- : "=r" (__ret), "=r" (__syscall)7676- : "1" (__syscall), "r" (__a), "r" (__b), "r" (__c)7777- : "r4", "r8", "r9",7878- "r10", "r11", "r14", "cc", "memory");7979- return __ret;8077}
···310310/* Free all resources held by a thread. */311311#define release_thread(thread) do { } while(0)312312313313-extern long kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);314314-315313extern unsigned long thread_saved_pc(struct task_struct *tsk);316314317315/*
···33 *44 * Copyright (C) 2000 Silicon Graphics, Inc.55 * Written by Ulf Carlsson (ulfc@engr.sgi.com)66- * sys32_execve from ia64/ia32 code, Feb 2000, Kanoj Sarcar (kanoj@sgi.com)76 */87#include <linux/compiler.h>98#include <linux/mm.h>···7273 goto out;7374 error = sys_mmap_pgoff(addr, len, prot, flags, fd,7475 pgoff >> (PAGE_SHIFT-12));7575-out:7676- return error;7777-}7878-7979-/*8080- * sys_execve() executes a new program.8181- */8282-asmlinkage int sys32_execve(nabi_no_regargs struct pt_regs regs)8383-{8484- int error;8585- struct filename *filename;8686-8787- filename = getname(compat_ptr(regs.regs[4]));8888- error = PTR_ERR(filename);8989- if (IS_ERR(filename))9090- goto out;9191- error = compat_do_execve(filename->name, compat_ptr(regs.regs[5]),9292- compat_ptr(regs.regs[6]), ®s);9393- putname(filename);9494-9576out:9677 return error;9778}
-2
arch/mips/kernel/mips_ksyms.c
···3232EXPORT_SYMBOL(memcpy);3333EXPORT_SYMBOL(memmove);34343535-EXPORT_SYMBOL(kernel_thread);3636-3735/*3836 * Functions that operate on entire pages. Mostly used by memory management.3937 */
+22-40
arch/mips/kernel/process.c
···8484}85858686asmlinkage void ret_from_fork(void);8787+asmlinkage void ret_from_kernel_thread(void);87888889void start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)8990{···114113}115114116115int copy_thread(unsigned long clone_flags, unsigned long usp,117117- unsigned long unused, struct task_struct *p, struct pt_regs *regs)116116+ unsigned long arg, struct task_struct *p, struct pt_regs *regs)118117{119118 struct thread_info *ti = task_thread_info(p);120119 struct pt_regs *childregs;···137136 childregs = (struct pt_regs *) childksp - 1;138137 /* Put the stack after the struct pt_regs. */139138 childksp = (unsigned long) childregs;139139+ p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);140140+ if (unlikely(p->flags & PF_KTHREAD)) {141141+ unsigned long status = p->thread.cp0_status;142142+ memset(childregs, 0, sizeof(struct pt_regs));143143+ ti->addr_limit = KERNEL_DS;144144+ p->thread.reg16 = usp; /* fn */145145+ p->thread.reg17 = arg;146146+ p->thread.reg29 = childksp;147147+ p->thread.reg31 = (unsigned long) ret_from_kernel_thread;148148+#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)149149+ status = (status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |150150+ ((status & (ST0_KUC | ST0_IEC)) << 2);151151+#else152152+ status |= ST0_EXL;153153+#endif154154+ childregs->cp0_status = status;155155+ return 0;156156+ }140157 *childregs = *regs;141158 childregs->regs[7] = 0; /* Clear error flag */142142-143159 childregs->regs[2] = 0; /* Child gets zero as return value */160160+ childregs->regs[29] = usp;161161+ ti->addr_limit = USER_DS;144162145145- if (childregs->cp0_status & ST0_CU0) {146146- childregs->regs[28] = (unsigned long) ti;147147- childregs->regs[29] = childksp;148148- ti->addr_limit = KERNEL_DS;149149- } else {150150- childregs->regs[29] = usp;151151- ti->addr_limit = USER_DS;152152- }153163 p->thread.reg29 = (unsigned long) childregs;154164 p->thread.reg31 = (unsigned long) ret_from_fork;155165···168156 * New tasks lose permission to use the fpu. This accelerates context169157 * switching for most programs since they don't use the fpu.170158 */171171- p->thread.cp0_status = read_c0_status() & ~(ST0_CU2|ST0_CU1);172159 childregs->cp0_status &= ~(ST0_CU2|ST0_CU1);173160174161#ifdef CONFIG_MIPS_MT_SMTC···230219 memcpy(fpr, &t->thread.fpu, sizeof(current->thread.fpu));231220232221 return 1;233233-}234234-235235-/*236236- * Create a kernel thread237237- */238238-static void __noreturn kernel_thread_helper(void *arg, int (*fn)(void *))239239-{240240- do_exit(fn(arg));241241-}242242-243243-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)244244-{245245- struct pt_regs regs;246246-247247- memset(®s, 0, sizeof(regs));248248-249249- regs.regs[4] = (unsigned long) arg;250250- regs.regs[5] = (unsigned long) fn;251251- regs.cp0_epc = (unsigned long) kernel_thread_helper;252252- regs.cp0_status = read_c0_status();253253-#if defined(CONFIG_CPU_R3000) || defined(CONFIG_CPU_TX39XX)254254- regs.cp0_status = (regs.cp0_status & ~(ST0_KUP | ST0_IEP | ST0_IEC)) |255255- ((regs.cp0_status & (ST0_KUC | ST0_IEC)) << 2);256256-#else257257- regs.cp0_status |= ST0_EXL;258258-#endif259259-260260- /* Ok, create the new process.. */261261- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL);262222}263223264224/*
···894894 l.jal schedule_tail895895 l.nop896896897897+ /* Check if we are a kernel thread */898898+ l.sfeqi r20,0899899+ l.bf 1f900900+ l.nop901901+902902+ /* ...we are a kernel thread so invoke the requested callback */903903+ l.jalr r20904904+ l.or r3,r22,r0905905+906906+1:897907 /* _syscall_returns expect r11 to contain return value */898908 l.lwz r11,PT_GPR11(r1)899909···924914925915 l.j _syscall_return926916 l.nop927927-928928-/* Since syscalls don't save call-clobbered registers, the args to929929- * kernel_thread_helper will need to be passed through callee-saved930930- * registers and copied to the parameter registers when the thread931931- * begins running.932932- *933933- * See arch/openrisc/kernel/process.c:934934- * The args are passed as follows:935935- * arg1 (r3) : passed in r20936936- * arg2 (r4) : passed in r22937937- */938938-939939-ENTRY(_kernel_thread_helper)940940- l.or r3,r20,r0941941- l.or r4,r22,r0942942- l.movhi r31,hi(kernel_thread_helper)943943- l.ori r31,r31,lo(kernel_thread_helper)944944- l.jr r31945945- l.nop946946-947917948918/* ========================================================[ switch ] === */949919···10341044 /* Unwind stack to pre-switch state */10351045 l.addi r1,r1,(INT_FRAME_SIZE)1036104610371037- /* Return via the link-register back to where we 'came from', where that can be10381038- * either schedule() or return_from_fork()... */10471047+ /* Return via the link-register back to where we 'came from', where10481048+ * that may be either schedule(), ret_from_fork(), or10491049+ * ret_from_kernel_thread(). If we are returning to a new thread,10501050+ * we are expected to have set up the arg to schedule_tail already,10511051+ * hence we do so here unconditionally:10521052+ */10531053+ l.lwz r3,TI_STACK(r3) /* Load 'prev' as schedule_tail arg */10391054 l.jr r910401055 l.nop10411056···10821087 l.ori r29,r29,lo(_sys_fork)10831088 l.j _fork_save_extra_regs_and_call10841089 l.addi r3,r1,010851085-10861086-ENTRY(sys_execve)10871087- l.j _sys_execve10881088- l.addi r6,r1,01089109010901091ENTRY(sys_sigaltstack)10911092 l.j _sys_sigaltstack
+57-108
arch/openrisc/kernel/process.c
···109109 */110110extern asmlinkage void ret_from_fork(void);111111112112+/*113113+ * copy_thread114114+ * @clone_flags: flags115115+ * @usp: user stack pointer or fn for kernel thread116116+ * @arg: arg to fn for kernel thread; always NULL for userspace thread117117+ * @p: the newly created task118118+ * @regs: CPU context to copy for userspace thread; always NULL for kthread119119+ *120120+ * At the top of a newly initialized kernel stack are two stacked pt_reg121121+ * structures. The first (topmost) is the userspace context of the thread.122122+ * The second is the kernelspace context of the thread.123123+ *124124+ * A kernel thread will not be returning to userspace, so the topmost pt_regs125125+ * struct can be uninitialized; it _does_ need to exist, though, because126126+ * a kernel thread can become a userspace thread by doing a kernel_execve, in127127+ * which case the topmost context will be initialized and used for 'returning'128128+ * to userspace.129129+ *130130+ * The second pt_reg struct needs to be initialized to 'return' to131131+ * ret_from_fork. A kernel thread will need to set r20 to the address of132132+ * a function to call into (with arg in r22); userspace threads need to set133133+ * r20 to NULL in which case ret_from_fork will just continue a return to134134+ * userspace.135135+ *136136+ * A kernel thread 'fn' may return; this is effectively what happens when137137+ * kernel_execve is called. In that case, the userspace pt_regs must have138138+ * been initialized (which kernel_execve takes care of, see start_thread139139+ * below); ret_from_fork will then continue its execution causing the140140+ * 'kernel thread' to return to userspace as a userspace thread.141141+ */142142+112143int113144copy_thread(unsigned long clone_flags, unsigned long usp,114114- unsigned long unused, struct task_struct *p, struct pt_regs *regs)145145+ unsigned long arg, struct task_struct *p, struct pt_regs *regs)115146{116116- struct pt_regs *childregs;147147+ struct pt_regs *userregs;117148 struct pt_regs *kregs;118149 unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;119119- struct thread_info *ti;120150 unsigned long top_of_kernel_stack;121151122152 top_of_kernel_stack = sp;123153124154 p->set_child_tid = p->clear_child_tid = NULL;125155126126- /* Copy registers */127127- /* redzone */128128- sp -= STACK_FRAME_OVERHEAD;156156+ /* Locate userspace context on stack... */157157+ sp -= STACK_FRAME_OVERHEAD; /* redzone */129158 sp -= sizeof(struct pt_regs);130130- childregs = (struct pt_regs *)sp;159159+ userregs = (struct pt_regs *) sp;131160132132- /* Copy parent registers */133133- *childregs = *regs;134134-135135- if ((childregs->sr & SPR_SR_SM) == 1) {136136- /* for kernel thread, set `current_thread_info'137137- * and stackptr in new task138138- */139139- childregs->sp = (unsigned long)task_stack_page(p) + THREAD_SIZE;140140- childregs->gpr[10] = (unsigned long)task_thread_info(p);141141- } else {142142- childregs->sp = usp;143143- }144144-145145- childregs->gpr[11] = 0; /* Result from fork() */146146-147147- /*148148- * The way this works is that at some point in the future149149- * some task will call _switch to switch to the new task.150150- * That will pop off the stack frame created below and start151151- * the new task running at ret_from_fork. The new task will152152- * do some house keeping and then return from the fork or clone153153- * system call, using the stack frame created above.154154- */155155- /* redzone */156156- sp -= STACK_FRAME_OVERHEAD;161161+ /* ...and kernel context */162162+ sp -= STACK_FRAME_OVERHEAD; /* redzone */157163 sp -= sizeof(struct pt_regs);158164 kregs = (struct pt_regs *)sp;159165160160- ti = task_thread_info(p);161161- ti->ksp = sp;166166+ if (unlikely(p->flags & PF_KTHREAD)) {167167+ memset(kregs, 0, sizeof(struct pt_regs));168168+ kregs->gpr[20] = usp; /* fn, kernel thread */169169+ kregs->gpr[22] = arg;170170+ } else {171171+ *userregs = *regs;162172163163- /* kregs->sp must store the location of the 'pre-switch' kernel stack164164- * pointer... for a newly forked process, this is simply the top of165165- * the kernel stack.173173+ userregs->sp = usp;174174+ userregs->gpr[11] = 0; /* Result from fork() */175175+176176+ kregs->gpr[20] = 0; /* Userspace thread */177177+ }178178+179179+ /*180180+ * _switch wants the kernel stack page in pt_regs->sp so that it181181+ * can restore it to thread_info->ksp... see _switch for details.166182 */167183 kregs->sp = top_of_kernel_stack;168168- kregs->gpr[3] = (unsigned long)current; /* arg to schedule_tail */169169- kregs->gpr[10] = (unsigned long)task_thread_info(p);170184 kregs->gpr[9] = (unsigned long)ret_from_fork;185185+186186+ task_thread_info(p)->ksp = (unsigned long)kregs;171187172188 return 0;173189}···193177 */194178void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)195179{196196- unsigned long sr = regs->sr & ~SPR_SR_SM;180180+ unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM;197181198182 set_fs(USER_DS);199199- memset(regs->gpr, 0, sizeof(regs->gpr));183183+ memset(regs, 0, sizeof(struct pt_regs));200184201185 regs->pc = pc;202186 regs->sr = sr;203187 regs->sp = sp;204204-205205-/* printk("start thread, ksp = %lx\n", current_thread_info()->ksp);*/206188}207189208190/* Fill in the fpu structure for a core dump. */···251237 dest[35] = 0;252238}253239254254-extern void _kernel_thread_helper(void);255255-256256-void __noreturn kernel_thread_helper(int (*fn) (void *), void *arg)257257-{258258- do_exit(fn(arg));259259-}260260-261261-/*262262- * Create a kernel thread.263263- */264264-int kernel_thread(int (*fn) (void *), void *arg, unsigned long flags)265265-{266266- struct pt_regs regs;267267-268268- memset(®s, 0, sizeof(regs));269269-270270- regs.gpr[20] = (unsigned long)fn;271271- regs.gpr[22] = (unsigned long)arg;272272- regs.sr = mfspr(SPR_SR);273273- regs.pc = (unsigned long)_kernel_thread_helper;274274-275275- return do_fork(flags | CLONE_VM | CLONE_UNTRACED,276276- 0, ®s, 0, NULL, NULL);277277-}278278-279279-/*280280- * sys_execve() executes a new program.281281- */282282-asmlinkage long _sys_execve(const char __user *name,283283- const char __user * const __user *argv,284284- const char __user * const __user *envp,285285- struct pt_regs *regs)286286-{287287- int error;288288- struct filename *filename;289289-290290- filename = getname(name);291291- error = PTR_ERR(filename);292292-293293- if (IS_ERR(filename))294294- goto out;295295-296296- error = do_execve(filename->name, argv, envp, regs);297297- putname(filename);298298-299299-out:300300- return error;301301-}302302-303240unsigned long get_wchan(struct task_struct *p)304241{305242 /* TODO */306243307244 return 0;308308-}309309-310310-int kernel_execve(const char *filename, char *const argv[], char *const envp[])311311-{312312- register long __res asm("r11") = __NR_execve;313313- register long __a asm("r3") = (long)(filename);314314- register long __b asm("r4") = (long)(argv);315315- register long __c asm("r5") = (long)(envp);316316- __asm__ volatile ("l.sys 1"317317- : "=r" (__res), "=r"(__a), "=r"(__b), "=r"(__c)318318- : "0"(__res), "1"(__a), "2"(__b), "3"(__c)319319- : "r6", "r7", "r8", "r12", "r13", "r15",320320- "r17", "r19", "r21", "r23", "r25", "r27",321321- "r29", "r31");322322- __asm__ volatile ("l.nop");323323- return __res;324245}
+2
arch/parisc/Kconfig
···2222 select GENERIC_STRNCPY_FROM_USER2323 select HAVE_MOD_ARCH_SPECIFIC2424 select MODULES_USE_ELF_RELA2525+ select GENERIC_KERNEL_THREAD2626+ select GENERIC_KERNEL_EXECVE25272628 help2729 The PA-RISC microprocessor is designed by Hewlett-Packard and used
···708708 .import do_cpu_irq_mask,code709709710710 /*711711- * r26 = function to be called712712- * r25 = argument to pass in713713- * r24 = flags for do_fork()714714- *715715- * Kernel threads don't ever return, so they don't need716716- * a true register context. We just save away the arguments717717- * for copy_thread/ret_ to properly set up the child.718718- */719719-720720-#define CLONE_VM 0x100 /* Must agree with <linux/sched.h> */721721-#define CLONE_UNTRACED 0x00800000722722-723723- .import do_fork724724-ENTRY(__kernel_thread)725725- STREG %r2, -RP_OFFSET(%r30)726726-727727- copy %r30, %r1728728- ldo PT_SZ_ALGN(%r30),%r30729729-#ifdef CONFIG_64BIT730730- /* Yo, function pointers in wide mode are little structs... -PB */731731- ldd 24(%r26), %r2732732- STREG %r2, PT_GR27(%r1) /* Store childs %dp */733733- ldd 16(%r26), %r26734734-735735- STREG %r22, PT_GR22(%r1) /* save r22 (arg5) */736736- copy %r0, %r22 /* user_tid */737737-#endif738738- STREG %r26, PT_GR26(%r1) /* Store function & argument for child */739739- STREG %r25, PT_GR25(%r1)740740- ldil L%CLONE_UNTRACED, %r26741741- ldo CLONE_VM(%r26), %r26 /* Force CLONE_VM since only init_mm */742742- or %r26, %r24, %r26 /* will have kernel mappings. */743743- ldi 1, %r25 /* stack_start, signals kernel thread */744744- stw %r0, -52(%r30) /* user_tid */745745-#ifdef CONFIG_64BIT746746- ldo -16(%r30),%r29 /* Reference param save area */747747-#endif748748- BL do_fork, %r2749749- copy %r1, %r24 /* pt_regs */750750-751751- /* Parent Returns here */752752-753753- LDREG -PT_SZ_ALGN-RP_OFFSET(%r30), %r2754754- ldo -PT_SZ_ALGN(%r30), %r30755755- bv %r0(%r2)756756- nop757757-ENDPROC(__kernel_thread)758758-759759- /*760711 * Child Returns here761712 *762762- * copy_thread moved args from temp save area set up above763763- * into task save area.713713+ * copy_thread moved args into task save area.764714 */765715766716ENTRY(ret_from_kernel_thread)···719769 BL schedule_tail, %r2720770 nop721771722722- LDREG TI_TASK-THREAD_SZ_ALGN(%r30), %r1772772+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r1723773 LDREG TASK_PT_GR25(%r1), %r26724774#ifdef CONFIG_64BIT725775 LDREG TASK_PT_GR27(%r1), %r27726726- LDREG TASK_PT_GR22(%r1), %r22727776#endif728777 LDREG TASK_PT_GR26(%r1), %r1729778 ble 0(%sr7, %r1)730779 copy %r31, %r2731731-732732-#ifdef CONFIG_64BIT733733- ldo -16(%r30),%r29 /* Reference param save area */734734- loadgp /* Thread could have been in a module */735735-#endif736736-#ifndef CONFIG_64BIT737737- b sys_exit738738-#else739739- load32 sys_exit, %r1740740- bv %r0(%r1)741741-#endif742742- ldi 0, %r26743743-ENDPROC(ret_from_kernel_thread)744744-745745- .import sys_execve, code746746-ENTRY(__execve)747747- copy %r2, %r15748748- copy %r30, %r16749749- ldo PT_SZ_ALGN(%r30), %r30750750- STREG %r26, PT_GR26(%r16)751751- STREG %r25, PT_GR25(%r16)752752- STREG %r24, PT_GR24(%r16)753753-#ifdef CONFIG_64BIT754754- ldo -16(%r30),%r29 /* Reference param save area */755755-#endif756756- BL sys_execve, %r2757757- copy %r16, %r26758758-759759- cmpib,=,n 0,%r28,intr_return /* forward */760760-761761- /* yes, this will trap and die. */762762- copy %r15, %r2763763- copy %r16, %r30764764- bv %r0(%r2)780780+ b finish_child_return765781 nop766766-ENDPROC(__execve)782782+ENDPROC(ret_from_kernel_thread)767783768784769785 /*···16921776 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r116931777 ldo TASK_REGS(%r1),%r116941778 reg_save %r116951695- mfctl %cr27, %r316961696- STREG %r3, PT_CR27(%r1)16971697-16981698- STREG %r2,-RP_OFFSET(%r30)16991699- ldo FRAME_SIZE(%r30),%r3017001700-#ifdef CONFIG_64BIT17011701- ldo -16(%r30),%r29 /* Reference param save area */17021702-#endif17031703-17041704- /* These are call-clobbered registers and therefore17051705- also syscall-clobbered (we hope). */17061706- STREG %r2,PT_GR19(%r1) /* save for child */17071707- STREG %r30,PT_GR21(%r1)17791779+ mfctl %cr27, %r2817801780+ STREG %r28, PT_CR27(%r1)1708178117091782 LDREG PT_GR30(%r1),%r2517101783 copy %r1,%r2417111711- BL sys_clone,%r217841784+ b sys_clone17121785 ldi SIGCHLD,%r2617131713-17141714- LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r217151715-wrapper_exit:17161716- ldo -FRAME_SIZE(%r30),%r30 /* get the stackframe */17171717- LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r117181718- ldo TASK_REGS(%r1),%r1 /* get pt regs */17191719-17201720- LDREG PT_CR27(%r1), %r317211721- mtctl %r3, %cr2717221722- reg_restore %r117231723-17241724- /* strace expects syscall # to be preserved in r20 */17251725- ldi __NR_fork,%r2017261726- bv %r0(%r2)17271727- STREG %r20,PT_GR20(%r1)17281786ENDPROC(sys_fork_wrapper)1729178717301788 /* Set the return value for the child */17311789ENTRY(child_return)17321790 BL schedule_tail, %r217331791 nop17921792+finish_child_return:17931793+ LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30), %r117941794+ ldo TASK_REGS(%r1),%r1 /* get pt regs */1734179517351735- LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE-FRAME_SIZE(%r30), %r117361736- LDREG TASK_PT_GR19(%r1),%r217371737- b wrapper_exit17961796+ LDREG PT_CR27(%r1), %r317971797+ mtctl %r3, %cr2717981798+ reg_restore %r117991799+ b syscall_exit17381800 copy %r0,%r2817391801ENDPROC(child_return)17401802···17211827 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r117221828 ldo TASK_REGS(%r1),%r1 /* get pt regs */17231829 reg_save %r117241724- mfctl %cr27, %r317251725- STREG %r3, PT_CR27(%r1)17261726-17271727- STREG %r2,-RP_OFFSET(%r30)17281728- ldo FRAME_SIZE(%r30),%r3017291729-#ifdef CONFIG_64BIT17301730- ldo -16(%r30),%r29 /* Reference param save area */17311731-#endif17321732-17331733- /* WARNING - Clobbers r19 and r21, userspace must save these! */17341734- STREG %r2,PT_GR19(%r1) /* save for child */17351735- STREG %r30,PT_GR21(%r1)17361736- BL sys_clone,%r218301830+ mfctl %cr27, %r2818311831+ STREG %r28, PT_CR27(%r1)18321832+ b sys_clone17371833 copy %r1,%r2417381738-17391739- b wrapper_exit17401740- LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r217411834ENDPROC(sys_clone_wrapper)1742183517431836···17321851 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r117331852 ldo TASK_REGS(%r1),%r1 /* get pt regs */17341853 reg_save %r117351735- mfctl %cr27, %r317361736- STREG %r3, PT_CR27(%r1)18541854+ mfctl %cr27, %r2818551855+ STREG %r28, PT_CR27(%r1)1737185617381738- STREG %r2,-RP_OFFSET(%r30)17391739- ldo FRAME_SIZE(%r30),%r3017401740-#ifdef CONFIG_64BIT17411741- ldo -16(%r30),%r29 /* Reference param save area */17421742-#endif17431743-17441744- STREG %r2,PT_GR19(%r1) /* save for child */17451745- STREG %r30,PT_GR21(%r1)17461746-17471747- BL sys_vfork,%r218571857+ b sys_vfork17481858 copy %r1,%r2617491749-17501750- b wrapper_exit17511751- LDREG -RP_OFFSET-FRAME_SIZE(%r30),%r217521859ENDPROC(sys_vfork_wrapper)175318601754186117551755- .macro execve_wrapper execve17561756- LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r117571757- ldo TASK_REGS(%r1),%r1 /* get pt regs */17581758-17591759- /*17601760- * Do we need to save/restore r3-r18 here?17611761- * I don't think so. why would new thread need old17621762- * threads registers?17631763- */17641764-17651765- /* %arg0 - %arg3 are already saved for us. */17661766-17671767- STREG %r2,-RP_OFFSET(%r30)17681768- ldo FRAME_SIZE(%r30),%r3017691769-#ifdef CONFIG_64BIT17701770- ldo -16(%r30),%r29 /* Reference param save area */17711771-#endif17721772- BL \execve,%r217731773- copy %r1,%arg017741774-17751775- ldo -FRAME_SIZE(%r30),%r3017761776- LDREG -RP_OFFSET(%r30),%r217771777-17781778- /* If exec succeeded we need to load the args */17791779-17801780- ldo -1024(%r0),%r117811781- cmpb,>>= %r28,%r1,error_\execve17821782- copy %r2,%r1917831783-17841784-error_\execve:17851785- bv %r0(%r19)17861786- nop17871787- .endm17881788-17891789- .import sys_execve17901790-ENTRY(sys_execve_wrapper)17911791- execve_wrapper sys_execve17921792-ENDPROC(sys_execve_wrapper)17931793-17941794-#ifdef CONFIG_64BIT17951795- .import sys32_execve17961796-ENTRY(sys32_execve_wrapper)17971797- execve_wrapper sys32_execve17981798-ENDPROC(sys32_execve_wrapper)17991799-#endif18001800-18011862ENTRY(sys_rt_sigreturn_wrapper)18021863 LDREG TI_TASK-THREAD_SZ_ALGN-FRAME_SIZE(%r30),%r2618031864 ldo TASK_REGS(%r26),%r26 /* get pt regs */
+15-81
arch/parisc/kernel/process.c
···52525353#include <asm/io.h>5454#include <asm/asm-offsets.h>5555+#include <asm/assembly.h>5556#include <asm/pdc.h>5657#include <asm/pdc_chassis.h>5758#include <asm/pgalloc.h>···166165EXPORT_SYMBOL(pm_power_off);167166168167/*169169- * Create a kernel thread170170- */171171-172172-extern pid_t __kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);173173-pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)174174-{175175-176176- /*177177- * FIXME: Once we are sure we don't need any debug here,178178- * kernel_thread can become a #define.179179- */180180-181181- return __kernel_thread(fn, arg, flags);182182-}183183-EXPORT_SYMBOL(kernel_thread);184184-185185-/*186168 * Free current thread data structures etc..187169 */188170void exit_thread(void)···240256241257int242258copy_thread(unsigned long clone_flags, unsigned long usp,243243- unsigned long unused, /* in ia64 this is "user_stack_size" */244244- struct task_struct * p, struct pt_regs * pregs)259259+ unsigned long arg,260260+ struct task_struct *p, struct pt_regs *pregs)245261{246262 struct pt_regs * cregs = &(p->thread.regs);247263 void *stack = task_stack_page(p);···254270#ifdef CONFIG_HPUX255271 extern void * const hpux_child_return;256272#endif273273+ if (unlikely(p->flags & PF_KTHREAD)) {274274+ memset(cregs, 0, sizeof(struct pt_regs));275275+ if (!usp) /* idle thread */276276+ return 0;257277258258- *cregs = *pregs;259259-260260- /* Set the return value for the child. Note that this is not261261- actually restored by the syscall exit path, but we put it262262- here for consistency in case of signals. */263263- cregs->gr[28] = 0; /* child */264264-265265- /*266266- * We need to differentiate between a user fork and a267267- * kernel fork. We can't use user_mode, because the268268- * the syscall path doesn't save iaoq. Right now269269- * We rely on the fact that kernel_thread passes270270- * in zero for usp.271271- */272272- if (usp == 1) {273278 /* kernel thread */274274- cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN;275279 /* Must exit via ret_from_kernel_thread in order276280 * to call schedule_tail()277281 */282282+ cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;278283 cregs->kpc = (unsigned long) &ret_from_kernel_thread;279284 /*280285 * Copy function and argument to be called from281286 * ret_from_kernel_thread.282287 */283288#ifdef CONFIG_64BIT284284- cregs->gr[27] = pregs->gr[27];289289+ cregs->gr[27] = ((unsigned long *)usp)[3];290290+ cregs->gr[26] = ((unsigned long *)usp)[2];291291+#else292292+ cregs->gr[26] = usp;285293#endif286286- cregs->gr[26] = pregs->gr[26];287287- cregs->gr[25] = pregs->gr[25];294294+ cregs->gr[25] = arg;288295 } else {289296 /* user thread */290290- /*291291- * Note that the fork wrappers are responsible292292- * for setting gr[21].293293- */294294-295295- /* Use same stack depth as parent */296296- cregs->ksp = (unsigned long)stack297297- + (pregs->gr[21] & (THREAD_SIZE - 1));298297 cregs->gr[30] = usp;298298+ cregs->ksp = (unsigned long)stack + THREAD_SZ_ALGN + FRAME_SIZE;299299 if (personality(p->personality) == PER_HPUX) {300300#ifdef CONFIG_HPUX301301 cregs->kpc = (unsigned long) &hpux_child_return;···291323 }292324 /* Setup thread TLS area from the 4th parameter in clone */293325 if (clone_flags & CLONE_SETTLS)294294- cregs->cr27 = pregs->gr[23];295295-326326+ cregs->cr27 = pregs->gr[23];296327 }297328298329 return 0;···300333unsigned long thread_saved_pc(struct task_struct *t)301334{302335 return t->thread.regs.kpc;303303-}304304-305305-/*306306- * sys_execve() executes a new program.307307- */308308-309309-asmlinkage int sys_execve(struct pt_regs *regs)310310-{311311- int error;312312- struct filename *filename;313313-314314- filename = getname((const char __user *) regs->gr[26]);315315- error = PTR_ERR(filename);316316- if (IS_ERR(filename))317317- goto out;318318- error = do_execve(filename->name,319319- (const char __user *const __user *) regs->gr[25],320320- (const char __user *const __user *) regs->gr[24],321321- regs);322322- putname(filename);323323-out:324324-325325- return error;326326-}327327-328328-extern int __execve(const char *filename,329329- const char *const argv[],330330- const char *const envp[], struct task_struct *task);331331-int kernel_execve(const char *filename,332332- const char *const argv[],333333- const char *const envp[])334334-{335335- return __execve(filename, argv, envp, current);336336}337337338338unsigned long
-22
arch/parisc/kernel/sys_parisc32.c
···5353#define DBG(x)5454#endif55555656-/*5757- * sys32_execve() executes a new program.5858- */5959-6060-asmlinkage int sys32_execve(struct pt_regs *regs)6161-{6262- int error;6363- struct filename *filename;6464-6565- DBG(("sys32_execve(%p) r26 = 0x%lx\n", regs, regs->gr[26]));6666- filename = getname((const char __user *) regs->gr[26]);6767- error = PTR_ERR(filename);6868- if (IS_ERR(filename))6969- goto out;7070- error = compat_do_execve(filename->name, compat_ptr(regs->gr[25]),7171- compat_ptr(regs->gr[24]), regs);7272- putname(filename);7373-out:7474-7575- return error;7676-}7777-7856asmlinkage long sys32_unimplemented(int r26, int r25, int r24, int r23,7957 int r22, int r21, int r20)8058{
+1-1
arch/parisc/kernel/syscall_table.S
···6666 ENTRY_SAME(creat)6767 ENTRY_SAME(link)6868 ENTRY_SAME(unlink) /* 10 */6969- ENTRY_DIFF(execve_wrapper)6969+ ENTRY_COMP(execve)7070 ENTRY_SAME(chdir)7171 /* See comments in kernel/time.c!!! Maybe we don't need this? */7272 ENTRY_COMP(time)
···444444 PPC440EP_ERR42445445 blrl446446 li r3,0447447- b do_exit # no return448448-449449- .globl __ret_from_kernel_execve450450-__ret_from_kernel_execve:451451- addi r1,r3,-STACK_FRAME_OVERHEAD452447 b ret_from_syscall453448454449/* Traced system call support */
+1-7
arch/powerpc/kernel/entry_64.S
···373373_GLOBAL(ret_from_kernel_thread)374374 bl .schedule_tail375375 REST_NVGPRS(r1)376376- REST_GPR(2,r1)376376+ ld r14, 0(r14)377377 mtlr r14378378 mr r3,r15379379 blrl380380 li r3,0381381- b .do_exit # no return382382-383383-_GLOBAL(__ret_from_kernel_execve)384384- addi r1,r3,-STACK_FRAME_OVERHEAD385385- li r10,1386386- std r10,SOFTE(r1)387381 b syscall_exit388382389383 .section ".toc","aw"
+10-33
arch/powerpc/kernel/process.c
···745745 /* Copy registers */746746 sp -= sizeof(struct pt_regs);747747 childregs = (struct pt_regs *) sp;748748- if (!regs) {749749- /* for kernel thread, set `current' and stackptr in new task */748748+ if (unlikely(p->flags & PF_KTHREAD)) {749749+ struct thread_info *ti = (void *)task_stack_page(p);750750 memset(childregs, 0, sizeof(struct pt_regs));751751 childregs->gpr[1] = sp + sizeof(struct pt_regs);752752-#ifdef CONFIG_PPC64753753- childregs->gpr[14] = *(unsigned long *)usp;754754- childregs->gpr[2] = ((unsigned long *)usp)[1],755755- clear_tsk_thread_flag(p, TIF_32BIT);756756-#else757752 childregs->gpr[14] = usp; /* function */758758- childregs->gpr[2] = (unsigned long) p;753753+#ifdef CONFIG_PPC64754754+ clear_tsk_thread_flag(p, TIF_32BIT);755755+ childregs->softe = 1;759756#endif760757 childregs->gpr[15] = arg;761758 p->thread.regs = NULL; /* no user register state */759759+ ti->flags |= _TIF_RESTOREALL;762760 f = ret_from_kernel_thread;763761 } else {764762 CHECK_FULL_REGS(regs);765763 *childregs = *regs;766766- childregs->gpr[1] = usp;764764+ if (usp)765765+ childregs->gpr[1] = usp;767766 p->thread.regs = childregs;768767 childregs->gpr[3] = 0; /* Result from fork() */769768 if (clone_flags & CLONE_SETTLS) {···10261027 return put_user(tsk->thread.align_ctl, (unsigned int __user *)adr);10271028}1028102910291029-#define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff))10301030-10311030int sys_clone(unsigned long clone_flags, unsigned long usp,10321031 int __user *parent_tidp, void __user *child_threadptr,10331032 int __user *child_tidp, int p6,10341033 struct pt_regs *regs)10351034{10361036- CHECK_FULL_REGS(regs);10371037- if (usp == 0)10381038- usp = regs->gpr[1]; /* stack pointer for child */10391039-#ifdef CONFIG_PPC6410401040- if (is_32bit_task()) {10411041- parent_tidp = TRUNC_PTR(parent_tidp);10421042- child_tidp = TRUNC_PTR(child_tidp);10431043- }10441044-#endif10451035 return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp);10461036}10471037···10381050 unsigned long p4, unsigned long p5, unsigned long p6,10391051 struct pt_regs *regs)10401052{10411041- CHECK_FULL_REGS(regs);10421042- return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL);10531053+ return do_fork(SIGCHLD, 0, regs, 0, NULL, NULL);10431054}1044105510451056int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3,10461057 unsigned long p4, unsigned long p5, unsigned long p6,10471058 struct pt_regs *regs)10481059{10491049- CHECK_FULL_REGS(regs);10501050- return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1],10601060+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, 0,10511061 regs, 0, NULL, NULL);10521052-}10531053-10541054-void __ret_from_kernel_execve(struct pt_regs *normal)10551055-__noreturn;10561056-10571057-void ret_from_kernel_execve(struct pt_regs *normal)10581058-{10591059- set_thread_flag(TIF_RESTOREALL);10601060- __ret_from_kernel_execve(normal);10611062}1062106310631064static inline int valid_irq_stack(unsigned long sp, struct task_struct *p,
···330330 la %r11,STACK_FRAME_OVERHEAD(%r15)331331 l %r12,__LC_THREAD_INFO332332 l %r13,__LC_SVC_NEW_PSW+4333333+ l %r1,BASED(.Lschedule_tail)334334+ basr %r14,%r1 # call schedule_tail335335+ TRACE_IRQS_ON336336+ ssm __LC_SVC_NEW_PSW # reenable interrupts333337 tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?334334- je 1f335335- l %r1,BASED(.Lschedule_tail)336336- basr %r14,%r1 # call schedule_tail337337- TRACE_IRQS_ON338338- ssm __LC_SVC_NEW_PSW # reenable interrupts339339- j sysc_tracenogo340340-341341-1: # it's a kernel thread342342- st %r15,__PT_R15(%r11) # store stack pointer for new kthread343343- l %r1,BASED(.Lschedule_tail)344344- basr %r14,%r1 # call schedule_tail345345- TRACE_IRQS_ON346346- ssm __LC_SVC_NEW_PSW # reenable interrupts347347- lm %r9,%r11,__PT_R9(%r11) # load gprs338338+ jne sysc_tracenogo339339+ # it's a kernel thread340340+ lm %r9,%r10,__PT_R9(%r11) # load gprs348341ENTRY(kernel_thread_starter)349342 la %r2,0(%r10)350343 basr %r14,%r9351351- la %r2,0352352- br %r11 # do_exit353353-354354-#355355-# kernel_execve function needs to deal with pt_regs that is not356356-# at the usual place357357-#358358-ENTRY(ret_from_kernel_execve)359359- ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts360360- lr %r15,%r2361361- lr %r11,%r2362362- ahi %r15,-STACK_FRAME_OVERHEAD363363- xc __SF_BACKCHAIN(4,%r15),__SF_BACKCHAIN(%r15)364364- l %r12,__LC_THREAD_INFO365365- ssm __LC_SVC_NEW_PSW # reenable interrupts366366- j sysc_return344344+ j sysc_tracenogo367345368346/*369347 * Program check handler routine
+7-23
arch/s390/kernel/entry64.S
···352352ENTRY(ret_from_fork)353353 la %r11,STACK_FRAME_OVERHEAD(%r15)354354 lg %r12,__LC_THREAD_INFO355355+ brasl %r14,schedule_tail356356+ TRACE_IRQS_ON357357+ ssm __LC_SVC_NEW_PSW # reenable interrupts355358 tm __PT_PSW+1(%r11),0x01 # forking a kernel thread ?356356- je 1f357357- brasl %r14,schedule_tail358358- TRACE_IRQS_ON359359- ssm __LC_SVC_NEW_PSW # reenable interrupts360360- j sysc_tracenogo361361-1: # it's a kernel thread362362- stg %r15,__PT_R15(%r11) # store stack pointer for new kthread363363- brasl %r14,schedule_tail364364- TRACE_IRQS_ON365365- ssm __LC_SVC_NEW_PSW # reenable interrupts366366- lmg %r9,%r11,__PT_R9(%r11) # load gprs359359+ jne sysc_tracenogo360360+ # it's a kernel thread361361+ lmg %r9,%r10,__PT_R9(%r11) # load gprs367362ENTRY(kernel_thread_starter)368363 la %r2,0(%r10)369364 basr %r14,%r9370370- la %r2,0371371- br %r11 # do_exit372372-373373-ENTRY(ret_from_kernel_execve)374374- ssm __LC_PGM_NEW_PSW # disable I/O and ext. interrupts375375- lgr %r15,%r2376376- lgr %r11,%r2377377- aghi %r15,-STACK_FRAME_OVERHEAD378378- xc __SF_BACKCHAIN(8,%r15),__SF_BACKCHAIN(%r15)379379- lg %r12,__LC_THREAD_INFO380380- ssm __LC_SVC_NEW_PSW # reenable interrupts381381- j sysc_return365365+ j sysc_tracenogo382366383367/*384368 * Program check handler routine
···1313 */1414extern void (*cpu_wait)(void);15151616-extern long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags);1716extern unsigned long thread_saved_pc(struct task_struct *tsk);1817extern void start_thread(struct pt_regs *regs,1918 unsigned long pc, unsigned long sp);
-1
arch/score/include/asm/syscalls.h
···22#define _ASM_SCORE_SYSCALLS_H3344asmlinkage long score_clone(struct pt_regs *regs);55-asmlinkage long score_execve(struct pt_regs *regs);65asmlinkage long score_sigaltstack(struct pt_regs *regs);76asmlinkage long score_rt_sigreturn(struct pt_regs *regs);87
···6060}61616262void ret_from_fork(void);6363+void ret_from_kernel_thread(void);63646465void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)6566{···8786 * set up the kernel stack and exception frames for a new process8887 */8988int copy_thread(unsigned long clone_flags, unsigned long usp,9090- unsigned long unused,8989+ unsigned long arg,9190 struct task_struct *p, struct pt_regs *regs)9291{9392 struct thread_info *ti = task_thread_info(p);9493 struct pt_regs *childregs = task_pt_regs(p);95949696- p->set_child_tid = NULL;9797- p->clear_child_tid = NULL;9898-9999- *childregs = *regs;100100- childregs->regs[7] = 0; /* Clear error flag */101101- childregs->regs[4] = 0; /* Child gets zero as return value */102102- regs->regs[4] = p->pid;103103-104104- if (childregs->cp0_psr & 0x8) { /* test kernel fork or user fork */105105- childregs->regs[0] = usp; /* user fork */9595+ p->thread.reg0 = (unsigned long) childregs;9696+ if (unlikely(!regs)) {9797+ memset(childregs, 0, sizeof(struct pt_regs));9898+ p->thread->reg12 = usp;9999+ p->thread->reg13 = arg;100100+ p->thread.reg3 = (unsigned long) ret_from_kernel_thread;106101 } else {107107- childregs->regs[28] = (unsigned long) ti; /* kernel fork */108108- childregs->regs[0] = (unsigned long) childregs;102102+ *childregs = *regs;103103+ childregs->regs[7] = 0; /* Clear error flag */104104+ childregs->regs[4] = 0; /* Child gets zero as return value */105105+ childregs->regs[0] = usp; /* user fork */106106+ regs->regs[4] = p->pid; /* WTF? */107107+ p->thread.reg3 = (unsigned long) ret_from_fork;109108 }110109111111- p->thread.reg0 = (unsigned long) childregs;112112- p->thread.reg3 = (unsigned long) ret_from_fork;113110 p->thread.cp0_psr = 0;114111115112 return 0;···117118int dump_fpu(struct pt_regs *regs, elf_fpregset_t *r)118119{119120 return 1;120120-}121121-122122-static void __noreturn123123-kernel_thread_helper(void *unused0, int (*fn)(void *),124124- void *arg, void *unused1)125125-{126126- do_exit(fn(arg));127127-}128128-129129-/*130130- * Create a kernel thread.131131- */132132-long kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)133133-{134134- struct pt_regs regs;135135-136136- memset(®s, 0, sizeof(regs));137137-138138- regs.regs[6] = (unsigned long) arg;139139- regs.regs[5] = (unsigned long) fn;140140- regs.cp0_epc = (unsigned long) kernel_thread_helper;141141- regs.cp0_psr = (regs.cp0_psr & ~(0x1|0x4|0x8)) | \142142- ((regs.cp0_psr & 0x3) << 2);143143-144144- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, \145145- 0, ®s, 0, NULL, NULL);146121}147122148123unsigned long thread_saved_pc(struct task_struct *tsk)
-54
arch/score/kernel/sys_score.c
···8383 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD,8484 regs->regs[0], regs, 0, NULL, NULL);8585}8686-8787-/*8888- * sys_execve() executes a new program.8989- * This is called indirectly via a small wrapper9090- */9191-asmlinkage long9292-score_execve(struct pt_regs *regs)9393-{9494- int error;9595- struct filename *filename;9696-9797- filename = getname((char __user*)regs->regs[4]);9898- error = PTR_ERR(filename);9999- if (IS_ERR(filename))100100- return error;101101-102102- error = do_execve(filename->name,103103- (const char __user *const __user *)regs->regs[5],104104- (const char __user *const __user *)regs->regs[6],105105- regs);106106-107107- putname(filename);108108- return error;109109-}110110-111111-/*112112- * Do a system call from kernel instead of calling sys_execve so we113113- * end up with proper pt_regs.114114- */115115-asmlinkage116116-int kernel_execve(const char *filename,117117- const char *const argv[],118118- const char *const envp[])119119-{120120- register unsigned long __r4 asm("r4") = (unsigned long) filename;121121- register unsigned long __r5 asm("r5") = (unsigned long) argv;122122- register unsigned long __r6 asm("r6") = (unsigned long) envp;123123- register unsigned long __r7 asm("r7");124124-125125- __asm__ __volatile__ (" \n"126126- "ldi r27, %5 \n"127127- "syscall \n"128128- "mv %0, r4 \n"129129- "mv %1, r7 \n"130130- : "=&r" (__r4), "=r" (__r7)131131- : "r" (__r4), "r" (__r5), "r" (__r6), "i" (__NR_execve)132132- : "r8", "r9", "r10", "r11", "r22", "r23", "r24", "r25",133133- "r26", "r27", "memory");134134-135135- if (__r7 == 0)136136- return __r4;137137-138138- return -__r4;139139-}
+2
arch/sh/Kconfig
···4040 select GENERIC_STRNLEN_USER4141 select HAVE_MOD_ARCH_SPECIFIC if DWARF_UNWINDER4242 select MODULES_USE_ELF_RELA4343+ select GENERIC_KERNEL_THREAD4444+ select GENERIC_KERNEL_EXECVE4345 help4446 The SuperH is a RISC processor targeted for use in embedded systems4547 and consumer electronics; it was also used in the Sega Dreamcast
-5
arch/sh/include/asm/processor_32.h
···126126/* Free all resources held by a thread. */127127extern void release_thread(struct task_struct *);128128129129-/*130130- * create a kernel thread without removing it from tasklists131131- */132132-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);133133-134129/* Copy and release all segment info associated with a VM */135130#define copy_segments(p, mm) do { } while(0)136131#define release_segments(mm) do { } while(0)
-5
arch/sh/include/asm/processor_64.h
···159159160160/* Free all resources held by a thread. */161161extern void release_thread(struct task_struct *);162162-/*163163- * create a kernel thread without removing it from tasklists164164- */165165-extern int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);166166-167162168163/* Copy and release all segment info associated with a VM */169164#define copy_segments(p, mm) do { } while (0)
-4
arch/sh/include/asm/syscalls_32.h
···1919asmlinkage int sys_vfork(unsigned long r4, unsigned long r5,2020 unsigned long r6, unsigned long r7,2121 struct pt_regs __regs);2222-asmlinkage int sys_execve(const char __user *ufilename,2323- const char __user *const __user *uargv,2424- const char __user *const __user *uenvp,2525- unsigned long r7, struct pt_regs __regs);2622asmlinkage int sys_sigsuspend(old_sigset_t mask);2723asmlinkage int sys_sigaction(int sig, const struct old_sigaction __user *act,2824 struct old_sigaction __user *oact);
-4
arch/sh/include/asm/syscalls_64.h
···2121 unsigned long r4, unsigned long r5,2222 unsigned long r6, unsigned long r7,2323 struct pt_regs *pregs);2424-asmlinkage int sys_execve(const char *ufilename, char **uargv,2525- char **uenvp, unsigned long r5,2626- unsigned long r6, unsigned long r7,2727- struct pt_regs *pregs);28242925/* Misc syscall related bits */3026asmlinkage long long do_syscall_trace_enter(struct pt_regs *regs);
···285285}286286287287/*288288- * Create a kernel thread289289- */290290-__noreturn void kernel_thread_helper(void *arg, int (*fn)(void *))291291-{292292- do_exit(fn(arg));293293-}294294-295295-/*296296- * This is the mechanism for creating a new kernel thread.297297- *298298- * NOTE! Only a kernel-only process(ie the swapper or direct descendants299299- * who haven't done an "execve()") should use this: it will work within300300- * a system call from a "real" process, but the process memory space will301301- * not be freed until both the parent and the child have exited.302302- */303303-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)304304-{305305- struct pt_regs regs;306306-307307- memset(®s, 0, sizeof(regs));308308- regs.regs[2] = (unsigned long)arg;309309- regs.regs[3] = (unsigned long)fn;310310-311311- regs.pc = (unsigned long)kernel_thread_helper;312312- regs.sr = (1 << 30);313313-314314- /* Ok, create the new process.. */315315- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0,316316- ®s, 0, NULL, NULL);317317-}318318-EXPORT_SYMBOL(kernel_thread);319319-320320-/*321288 * Free current thread data structures etc..322289 */323290void exit_thread(void)···368401EXPORT_SYMBOL(dump_fpu);369402370403asmlinkage void ret_from_fork(void);404404+asmlinkage void ret_from_kernel_thread(void);371405372406int copy_thread(unsigned long clone_flags, unsigned long usp,373373- unsigned long unused,407407+ unsigned long arg,374408 struct task_struct *p, struct pt_regs *regs)375409{376410 struct pt_regs *childregs;377411378412#ifdef CONFIG_SH_FPU379379- if(last_task_used_math == current) {413413+ /* can't happen for a kernel thread */414414+ if (last_task_used_math == current) {380415 enable_fpu();381416 save_fpu(current);382417 disable_fpu();···388419#endif389420 /* Copy from sh version */390421 childregs = (struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1;422422+ p->thread.sp = (unsigned long) childregs;391423424424+ if (unlikely(p->flags & PF_KTHREAD)) {425425+ memset(childregs, 0, sizeof(struct pt_regs));426426+ childregs->regs[2] = (unsigned long)arg;427427+ childregs->regs[3] = (unsigned long)fn;428428+ childregs->sr = (1 << 30); /* not user_mode */429429+ childregs->sr |= SR_FD; /* Invalidate FPU flag */430430+ p->thread.pc = (unsigned long) ret_from_kernel_thread;431431+ return 0;432432+ }392433 *childregs = *regs;393434394435 /*···407428 * 32-bit wide and context switch must take care408429 * of NEFF sign extension.409430 */410410- if (user_mode(regs)) {411411- childregs->regs[15] = neff_sign_extend(usp);412412- p->thread.uregs = childregs;413413- } else {414414- childregs->regs[15] =415415- neff_sign_extend((unsigned long)task_stack_page(p) +416416- THREAD_SIZE);417417- }431431+ childregs->regs[15] = neff_sign_extend(usp);432432+ p->thread.uregs = childregs;418433419434 childregs->regs[9] = 0; /* Set return value for child */420435 childregs->sr |= SR_FD; /* Invalidate FPU flag */421436422422- p->thread.sp = (unsigned long) childregs;423437 p->thread.pc = (unsigned long) ret_from_fork;424438425439 return 0;···452480 struct pt_regs *pregs)453481{454482 return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, pregs->regs[15], pregs, 0, 0, 0);455455-}456456-457457-/*458458- * sys_execve() executes a new program.459459- */460460-asmlinkage int sys_execve(const char *ufilename, char **uargv,461461- char **uenvp, unsigned long r5,462462- unsigned long r6, unsigned long r7,463463- struct pt_regs *pregs)464464-{465465- int error;466466- struct filename *filename;467467-468468- filename = getname((char __user *)ufilename);469469- error = PTR_ERR(filename);470470- if (IS_ERR(filename))471471- goto out;472472-473473- error = do_execve(filename->name,474474- (const char __user *const __user *)uargv,475475- (const char __user *const __user *)uenvp,476476- pregs);477477- putname(filename);478478-out:479479- return error;480483}481484482485#ifdef CONFIG_FRAME_POINTER
-24
arch/sh/kernel/sys_sh32.c
···6060 (u64)len0 << 32 | len1, advice);6161#endif6262}6363-6464-#if defined(CONFIG_CPU_SH2) || defined(CONFIG_CPU_SH2A)6565-#define SYSCALL_ARG3 "trapa #0x23"6666-#else6767-#define SYSCALL_ARG3 "trapa #0x13"6868-#endif6969-7070-/*7171- * Do a system call from kernel instead of calling sys_execve so we7272- * end up with proper pt_regs.7373- */7474-int kernel_execve(const char *filename,7575- const char *const argv[],7676- const char *const envp[])7777-{7878- register long __sc0 __asm__ ("r3") = __NR_execve;7979- register long __sc4 __asm__ ("r4") = (long) filename;8080- register long __sc5 __asm__ ("r5") = (long) argv;8181- register long __sc6 __asm__ ("r6") = (long) envp;8282- __asm__ __volatile__ (SYSCALL_ARG3 : "=z" (__sc0)8383- : "0" (__sc0), "r" (__sc4), "r" (__sc5), "r" (__sc6)8484- : "memory");8585- return __sc0;8686-}
-50
arch/sh/kernel/sys_sh64.c
···11-/*22- * arch/sh/kernel/sys_sh64.c33- *44- * Copyright (C) 2000, 2001 Paolo Alberelli55- *66- * This file contains various random system calls that77- * have a non-standard calling sequence on the Linux/SH588- * platform.99- *1010- * This file is subject to the terms and conditions of the GNU General Public1111- * License. See the file "COPYING" in the main directory of this archive1212- * for more details.1313- */1414-#include <linux/errno.h>1515-#include <linux/rwsem.h>1616-#include <linux/sched.h>1717-#include <linux/mm.h>1818-#include <linux/fs.h>1919-#include <linux/smp.h>2020-#include <linux/sem.h>2121-#include <linux/msg.h>2222-#include <linux/shm.h>2323-#include <linux/stat.h>2424-#include <linux/mman.h>2525-#include <linux/file.h>2626-#include <linux/syscalls.h>2727-#include <linux/ipc.h>2828-#include <asm/uaccess.h>2929-#include <asm/ptrace.h>3030-#include <asm/unistd.h>3131-3232-/*3333- * Do a system call from kernel instead of calling sys_execve so we3434- * end up with proper pt_regs.3535- */3636-int kernel_execve(const char *filename,3737- const char *const argv[],3838- const char *const envp[])3939-{4040- register unsigned long __sc0 __asm__ ("r9") = ((0x13 << 16) | __NR_execve);4141- register unsigned long __sc2 __asm__ ("r2") = (unsigned long) filename;4242- register unsigned long __sc3 __asm__ ("r3") = (unsigned long) argv;4343- register unsigned long __sc4 __asm__ ("r4") = (unsigned long) envp;4444- __asm__ __volatile__ ("trapa %1 !\t\t\t execve(%2,%3,%4)"4545- : "=r" (__sc0)4646- : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) );4747- __asm__ __volatile__ ("!dummy %0 %1 %2 %3"4848- : : "r" (__sc0), "r" (__sc2), "r" (__sc3), "r" (__sc4) : "memory");4949- return __sc0;5050-}
···106106107107/* Free all resources held by a thread. */108108#define release_thread(tsk) do { } while(0)109109-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);110109111110extern unsigned long get_wchan(struct task_struct *);112111
+9-2
arch/sparc/include/asm/processor_64.h
···9494#ifndef __ASSEMBLY__95959696#include <linux/types.h>9797+#include <asm/fpumacro.h>97989899/* Return saved PC of a blocked thread. */99100struct task_struct;···144143 : \145144 : "r" (regs), "r" (sp - sizeof(struct reg_window) - STACK_BIAS), \146145 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \146146+ fprs_write(0); \147147+ current_thread_info()->xfsr[0] = 0; \148148+ current_thread_info()->fpsaved[0] = 0; \149149+ regs->tstate &= ~TSTATE_PEF; \147150} while (0)148151149152#define start_thread32(regs, pc, sp) \···188183 : \189184 : "r" (regs), "r" (sp - sizeof(struct reg_window32)), \190185 "i" ((const unsigned long)(&((struct pt_regs *)0)->u_regs[0]))); \186186+ fprs_write(0); \187187+ current_thread_info()->xfsr[0] = 0; \188188+ current_thread_info()->fpsaved[0] = 0; \189189+ regs->tstate &= ~TSTATE_PEF; \191190} while (0)192191193192/* Free all resources held by a thread. */194193#define release_thread(tsk) do { } while (0)195195-196196-extern pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags);197194198195extern unsigned long get_wchan(struct task_struct *task);199196
···2323 /* If you are tempted to conditionalize the following */ \2424 /* so that ASI is only written if it changes, think again. */ \2525 __asm__ __volatile__("wr %%g0, %0, %%asi" \2626- : : "r" (__thread_flag_byte_ptr(task_thread_info(next))[TI_FLAG_BYTE_CURRENT_DS]));\2626+ : : "r" (task_thread_info(next)->current_ds));\2727 trap_block[current_thread_info()->cpu].thread = \2828 task_thread_info(next); \2929 __asm__ __volatile__( \
-2
arch/sparc/include/asm/syscalls.h
···88 struct pt_regs *regs,99 unsigned long stack_size);10101111-extern asmlinkage int sparc_execve(struct pt_regs *regs);1212-1311#endif /* _SPARC64_SYSCALLS_H */
···316316 * XXX See comment above sys_vfork in sparc64. todo.317317 */318318extern void ret_from_fork(void);319319+extern void ret_from_kernel_thread(void);319320320321int copy_thread(unsigned long clone_flags, unsigned long sp,321321- unsigned long unused,322322+ unsigned long arg,322323 struct task_struct *p, struct pt_regs *regs)323324{324325 struct thread_info *ti = task_thread_info(p);···337336 }338337339338 /*340340- * p->thread_info new_stack childregs341341- * ! ! ! {if(PSR_PS) }342342- * V V (stk.fr.) V (pt_regs) { (stk.fr.) }343343- * +----- - - - - - ------+===========+============={+==========}+339339+ * p->thread_info new_stack childregs stack bottom340340+ * ! ! ! !341341+ * V V (stk.fr.) V (pt_regs) V342342+ * +----- - - - - - ------+===========+=============+344343 */345344 new_stack = task_stack_page(p) + THREAD_SIZE;346346- if (regs->psr & PSR_PS)347347- new_stack -= STACKFRAME_SZ;348345 new_stack -= STACKFRAME_SZ + TRACEREG_SZ;349349- memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);350346 childregs = (struct pt_regs *) (new_stack + STACKFRAME_SZ);351347352348 /*···354356 * Thus, kpsr|=PSR_PIL.355357 */356358 ti->ksp = (unsigned long) new_stack;359359+ p->thread.kregs = childregs;360360+361361+ if (unlikely(p->flags & PF_KTHREAD)) {362362+ extern int nwindows;363363+ unsigned long psr;364364+ memset(new_stack, 0, STACKFRAME_SZ + TRACEREG_SZ);365365+ p->thread.flags |= SPARC_FLAG_KTHREAD;366366+ p->thread.current_ds = KERNEL_DS;367367+ ti->kpc = (((unsigned long) ret_from_kernel_thread) - 0x8);368368+ childregs->u_regs[UREG_G1] = sp; /* function */369369+ childregs->u_regs[UREG_G2] = arg;370370+ psr = childregs->psr = get_psr();371371+ ti->kpsr = psr | PSR_PIL;372372+ ti->kwim = 1 << (((psr & PSR_CWP) + 1) % nwindows);373373+ return 0;374374+ }375375+ memcpy(new_stack, (char *)regs - STACKFRAME_SZ, STACKFRAME_SZ + TRACEREG_SZ);376376+ childregs->u_regs[UREG_FP] = sp;377377+ p->thread.flags &= ~SPARC_FLAG_KTHREAD;378378+ p->thread.current_ds = USER_DS;357379 ti->kpc = (((unsigned long) ret_from_fork) - 0x8);358380 ti->kpsr = current->thread.fork_kpsr | PSR_PIL;359381 ti->kwim = current->thread.fork_kwim;360382361361- if(regs->psr & PSR_PS) {362362- extern struct pt_regs fake_swapper_regs;383383+ if (sp != regs->u_regs[UREG_FP]) {384384+ struct sparc_stackf __user *childstack;385385+ struct sparc_stackf __user *parentstack;363386364364- p->thread.kregs = &fake_swapper_regs;365365- new_stack += STACKFRAME_SZ + TRACEREG_SZ;366366- childregs->u_regs[UREG_FP] = (unsigned long) new_stack;367367- p->thread.flags |= SPARC_FLAG_KTHREAD;368368- p->thread.current_ds = KERNEL_DS;369369- memcpy(new_stack, (void *)regs->u_regs[UREG_FP], STACKFRAME_SZ);370370- childregs->u_regs[UREG_G6] = (unsigned long) ti;371371- } else {372372- p->thread.kregs = childregs;373373- childregs->u_regs[UREG_FP] = sp;374374- p->thread.flags &= ~SPARC_FLAG_KTHREAD;375375- p->thread.current_ds = USER_DS;376376-377377- if (sp != regs->u_regs[UREG_FP]) {378378- struct sparc_stackf __user *childstack;379379- struct sparc_stackf __user *parentstack;380380-381381- /*382382- * This is a clone() call with supplied user stack.383383- * Set some valid stack frames to give to the child.384384- */385385- childstack = (struct sparc_stackf __user *)386386- (sp & ~0xfUL);387387- parentstack = (struct sparc_stackf __user *)388388- regs->u_regs[UREG_FP];387387+ /*388388+ * This is a clone() call with supplied user stack.389389+ * Set some valid stack frames to give to the child.390390+ */391391+ childstack = (struct sparc_stackf __user *)392392+ (sp & ~0xfUL);393393+ parentstack = (struct sparc_stackf __user *)394394+ regs->u_regs[UREG_FP];389395390396#if 0391391- printk("clone: parent stack:\n");392392- show_stackframe(parentstack);397397+ printk("clone: parent stack:\n");398398+ show_stackframe(parentstack);393399#endif394400395395- childstack = clone_stackframe(childstack, parentstack);396396- if (!childstack)397397- return -EFAULT;401401+ childstack = clone_stackframe(childstack, parentstack);402402+ if (!childstack)403403+ return -EFAULT;398404399405#if 0400400- printk("clone: child stack:\n");401401- show_stackframe(childstack);406406+ printk("clone: child stack:\n");407407+ show_stackframe(childstack);402408#endif403409404404- childregs->u_regs[UREG_FP] = (unsigned long)childstack;405405- }410410+ childregs->u_regs[UREG_FP] = (unsigned long)childstack;406411 }407412408413#ifdef CONFIG_SMP···475474 sizeof(struct fpq) * (32 - fpregs->pr_qcnt));476475 return 1;477476}478478-479479-/*480480- * sparc_execve() executes a new program after the asm stub has set481481- * things up for us. This should basically do what I want it to.482482- */483483-asmlinkage int sparc_execve(struct pt_regs *regs)484484-{485485- int error, base = 0;486486- struct filename *filename;487487-488488- /* Check for indirect call. */489489- if(regs->u_regs[UREG_G1] == 0)490490- base = 1;491491-492492- filename = getname((char __user *)regs->u_regs[base + UREG_I0]);493493- error = PTR_ERR(filename);494494- if(IS_ERR(filename))495495- goto out;496496- error = do_execve(filename->name,497497- (const char __user *const __user *)498498- regs->u_regs[base + UREG_I1],499499- (const char __user *const __user *)500500- regs->u_regs[base + UREG_I2],501501- regs);502502- putname(filename);503503-out:504504- return error;505505-}506506-507507-/*508508- * This is the mechanism for creating a new kernel thread.509509- *510510- * NOTE! Only a kernel-only process(ie the swapper or direct descendants511511- * who haven't done an "execve()") should use this: it will work within512512- * a system call from a "real" process, but the process memory space will513513- * not be freed until both the parent and the child have exited.514514- */515515-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)516516-{517517- long retval;518518-519519- __asm__ __volatile__("mov %4, %%g2\n\t" /* Set aside fn ptr... */520520- "mov %5, %%g3\n\t" /* and arg. */521521- "mov %1, %%g1\n\t"522522- "mov %2, %%o0\n\t" /* Clone flags. */523523- "mov 0, %%o1\n\t" /* usp arg == 0 */524524- "t 0x10\n\t" /* Linux/Sparc clone(). */525525- "cmp %%o1, 0\n\t"526526- "be 1f\n\t" /* The parent, just return. */527527- " nop\n\t" /* Delay slot. */528528- "jmpl %%g2, %%o7\n\t" /* Call the function. */529529- " mov %%g3, %%o0\n\t" /* Get back the arg in delay. */530530- "mov %3, %%g1\n\t"531531- "t 0x10\n\t" /* Linux/Sparc exit(). */532532- /* Notreached by child. */533533- "1: mov %%o0, %0\n\t" :534534- "=r" (retval) :535535- "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),536536- "i" (__NR_exit), "r" (fn), "r" (arg) :537537- "g1", "g2", "g3", "o0", "o1", "memory", "cc");538538- return retval;539539-}540540-EXPORT_SYMBOL(kernel_thread);541477542478unsigned long get_wchan(struct task_struct *task)543479{
+31-114
arch/sparc/kernel/process_64.c
···622622 * Child --> %o0 == parents pid, %o1 == 1623623 */624624int copy_thread(unsigned long clone_flags, unsigned long sp,625625- unsigned long unused,625625+ unsigned long arg,626626 struct task_struct *p, struct pt_regs *regs)627627{628628 struct thread_info *t = task_thread_info(p);629629 struct sparc_stackf *parent_sf;630630 unsigned long child_stack_sz;631631 char *child_trap_frame;632632- int kernel_thread;633633-634634- kernel_thread = (regs->tstate & TSTATE_PRIV) ? 1 : 0;635635- parent_sf = ((struct sparc_stackf *) regs) - 1;636632637633 /* Calculate offset to stack_frame & pt_regs */638638- child_stack_sz = ((STACKFRAME_SZ + TRACEREG_SZ) +639639- (kernel_thread ? STACKFRAME_SZ : 0));634634+ child_stack_sz = (STACKFRAME_SZ + TRACEREG_SZ);640635 child_trap_frame = (task_stack_page(p) +641636 (THREAD_SIZE - child_stack_sz));642642- memcpy(child_trap_frame, parent_sf, child_stack_sz);643637644644- t->flags = (t->flags & ~((0xffUL << TI_FLAG_CWP_SHIFT) |645645- (0xffUL << TI_FLAG_CURRENT_DS_SHIFT))) |646646- (((regs->tstate + 1) & TSTATE_CWP) << TI_FLAG_CWP_SHIFT);647638 t->new_child = 1;648639 t->ksp = ((unsigned long) child_trap_frame) - STACK_BIAS;649640 t->kregs = (struct pt_regs *) (child_trap_frame +650641 sizeof(struct sparc_stackf));651642 t->fpsaved[0] = 0;652643653653- if (kernel_thread) {654654- struct sparc_stackf *child_sf = (struct sparc_stackf *)655655- (child_trap_frame + (STACKFRAME_SZ + TRACEREG_SZ));656656-657657- /* Zero terminate the stack backtrace. */658658- child_sf->fp = NULL;659659- t->kregs->u_regs[UREG_FP] =660660- ((unsigned long) child_sf) - STACK_BIAS;661661-662662- t->flags |= ((long)ASI_P << TI_FLAG_CURRENT_DS_SHIFT);663663- t->kregs->u_regs[UREG_G6] = (unsigned long) t;664664- t->kregs->u_regs[UREG_G4] = (unsigned long) t->task;665665- } else {666666- if (t->flags & _TIF_32BIT) {667667- sp &= 0x00000000ffffffffUL;668668- regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;669669- }670670- t->kregs->u_regs[UREG_FP] = sp;671671- t->flags |= ((long)ASI_AIUS << TI_FLAG_CURRENT_DS_SHIFT);672672- if (sp != regs->u_regs[UREG_FP]) {673673- unsigned long csp;674674-675675- csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);676676- if (!csp)677677- return -EFAULT;678678- t->kregs->u_regs[UREG_FP] = csp;679679- }680680- if (t->utraps)681681- t->utraps[0]++;644644+ if (unlikely(p->flags & PF_KTHREAD)) {645645+ memset(child_trap_frame, 0, child_stack_sz);646646+ __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 647647+ (current_pt_regs()->tstate + 1) & TSTATE_CWP;648648+ t->current_ds = ASI_P;649649+ t->kregs->u_regs[UREG_G1] = sp; /* function */650650+ t->kregs->u_regs[UREG_G2] = arg;651651+ return 0;682652 }653653+654654+ parent_sf = ((struct sparc_stackf *) regs) - 1;655655+ memcpy(child_trap_frame, parent_sf, child_stack_sz);656656+ if (t->flags & _TIF_32BIT) {657657+ sp &= 0x00000000ffffffffUL;658658+ regs->u_regs[UREG_FP] &= 0x00000000ffffffffUL;659659+ }660660+ t->kregs->u_regs[UREG_FP] = sp;661661+ __thread_flag_byte_ptr(t)[TI_FLAG_BYTE_CWP] = 662662+ (regs->tstate + 1) & TSTATE_CWP;663663+ t->current_ds = ASI_AIUS;664664+ if (sp != regs->u_regs[UREG_FP]) {665665+ unsigned long csp;666666+667667+ csp = clone_stackframe(sp, regs->u_regs[UREG_FP]);668668+ if (!csp)669669+ return -EFAULT;670670+ t->kregs->u_regs[UREG_FP] = csp;671671+ }672672+ if (t->utraps)673673+ t->utraps[0]++;683674684675 /* Set the return value for the child. */685676 t->kregs->u_regs[UREG_I0] = current->pid;···684693685694 return 0;686695}687687-688688-/*689689- * This is the mechanism for creating a new kernel thread.690690- *691691- * NOTE! Only a kernel-only process(ie the swapper or direct descendants692692- * who haven't done an "execve()") should use this: it will work within693693- * a system call from a "real" process, but the process memory space will694694- * not be freed until both the parent and the child have exited.695695- */696696-pid_t kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)697697-{698698- long retval;699699-700700- /* If the parent runs before fn(arg) is called by the child,701701- * the input registers of this function can be clobbered.702702- * So we stash 'fn' and 'arg' into global registers which703703- * will not be modified by the parent.704704- */705705- __asm__ __volatile__("mov %4, %%g2\n\t" /* Save FN into global */706706- "mov %5, %%g3\n\t" /* Save ARG into global */707707- "mov %1, %%g1\n\t" /* Clone syscall nr. */708708- "mov %2, %%o0\n\t" /* Clone flags. */709709- "mov 0, %%o1\n\t" /* usp arg == 0 */710710- "t 0x6d\n\t" /* Linux/Sparc clone(). */711711- "brz,a,pn %%o1, 1f\n\t" /* Parent, just return. */712712- " mov %%o0, %0\n\t"713713- "jmpl %%g2, %%o7\n\t" /* Call the function. */714714- " mov %%g3, %%o0\n\t" /* Set arg in delay. */715715- "mov %3, %%g1\n\t"716716- "t 0x6d\n\t" /* Linux/Sparc exit(). */717717- /* Notreached by child. */718718- "1:" :719719- "=r" (retval) :720720- "i" (__NR_clone), "r" (flags | CLONE_VM | CLONE_UNTRACED),721721- "i" (__NR_exit), "r" (fn), "r" (arg) :722722- "g1", "g2", "g3", "o0", "o1", "memory", "cc");723723- return retval;724724-}725725-EXPORT_SYMBOL(kernel_thread);726696727697typedef struct {728698 union {···750798 return 1;751799}752800EXPORT_SYMBOL(dump_fpu);753753-754754-/*755755- * sparc_execve() executes a new program after the asm stub has set756756- * things up for us. This should basically do what I want it to.757757- */758758-asmlinkage int sparc_execve(struct pt_regs *regs)759759-{760760- int error, base = 0;761761- struct filename *filename;762762-763763- /* User register window flush is done by entry.S */764764-765765- /* Check for indirect call. */766766- if (regs->u_regs[UREG_G1] == 0)767767- base = 1;768768-769769- filename = getname((char __user *)regs->u_regs[base + UREG_I0]);770770- error = PTR_ERR(filename);771771- if (IS_ERR(filename))772772- goto out;773773- error = do_execve(filename->name,774774- (const char __user *const __user *)775775- regs->u_regs[base + UREG_I1],776776- (const char __user *const __user *)777777- regs->u_regs[base + UREG_I2], regs);778778- putname(filename);779779- if (!error) {780780- fprs_write(0);781781- current_thread_info()->xfsr[0] = 0;782782- current_thread_info()->fpsaved[0] = 0;783783- regs->tstate &= ~TSTATE_PEF;784784- }785785-out:786786- return error;787787-}788801789802unsigned long get_wchan(struct task_struct *task)790803{
-36
arch/sparc/kernel/sys_sparc32.c
···396396 return ret;397397}398398399399-/*400400- * sparc32_execve() executes a new program after the asm stub has set401401- * things up for us. This should basically do what I want it to.402402- */403403-asmlinkage long sparc32_execve(struct pt_regs *regs)404404-{405405- int error, base = 0;406406- struct filename *filename;407407-408408- /* User register window flush is done by entry.S */409409-410410- /* Check for indirect call. */411411- if ((u32)regs->u_regs[UREG_G1] == 0)412412- base = 1;413413-414414- filename = getname(compat_ptr(regs->u_regs[base + UREG_I0]));415415- error = PTR_ERR(filename);416416- if (IS_ERR(filename))417417- goto out;418418-419419- error = compat_do_execve(filename->name,420420- compat_ptr(regs->u_regs[base + UREG_I1]),421421- compat_ptr(regs->u_regs[base + UREG_I2]), regs);422422-423423- putname(filename);424424-425425- if (!error) {426426- fprs_write(0);427427- current_thread_info()->xfsr[0] = 0;428428- current_thread_info()->fpsaved[0] = 0;429429- regs->tstate &= ~TSTATE_PEF;430430- }431431-out:432432- return error;433433-}434434-435399#ifdef CONFIG_MODULES436400437401asmlinkage long sys32_init_module(void __user *umod, u32 len,
-24
arch/sparc/kernel/sys_sparc_32.c
···258258 up_read(&uts_sem);259259 return err;260260}261261-262262-/*263263- * Do a system call from kernel instead of calling sys_execve so we264264- * end up with proper pt_regs.265265- */266266-int kernel_execve(const char *filename,267267- const char *const argv[],268268- const char *const envp[])269269-{270270- long __res;271271- register long __g1 __asm__ ("g1") = __NR_execve;272272- register long __o0 __asm__ ("o0") = (long)(filename);273273- register long __o1 __asm__ ("o1") = (long)(argv);274274- register long __o2 __asm__ ("o2") = (long)(envp);275275- asm volatile ("t 0x10\n\t"276276- "bcc 1f\n\t"277277- "mov %%o0, %0\n\t"278278- "sub %%g0, %%o0, %0\n\t"279279- "1:\n\t"280280- : "=r" (__res), "=&r" (__o0)281281- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)282282- : "cc");283283- return __res;284284-}
-22
arch/sparc/kernel/sys_sparc_64.c
···730730 return ret;731731}732732733733-/*734734- * Do a system call from kernel instead of calling sys_execve so we735735- * end up with proper pt_regs.736736- */737737-int kernel_execve(const char *filename,738738- const char *const argv[],739739- const char *const envp[])740740-{741741- long __res;742742- register long __g1 __asm__ ("g1") = __NR_execve;743743- register long __o0 __asm__ ("o0") = (long)(filename);744744- register long __o1 __asm__ ("o1") = (long)(argv);745745- register long __o2 __asm__ ("o2") = (long)(envp);746746- asm volatile ("t 0x6d\n\t"747747- "sub %%g0, %%o0, %0\n\t"748748- "movcc %%xcc, %%o0, %0\n\t"749749- : "=r" (__res), "=&r" (__o0)750750- : "1" (__o0), "r" (__o1), "r" (__o2), "r" (__g1)751751- : "cc");752752- return __res;753753-}754754-755733asmlinkage long sys_kern_features(void)756734{757735 return KERN_FEATURE_MIXED_MODE_STACK;
···211211{212212 regs->pc = pc;213213 regs->sp = usp;214214+ single_step_execve();214215}215216216217/* Free all resources held by a thread. */···240239#define KSTK_TOP(task) (task_ksp0(task) - STACK_TOP_DELTA)241240#define task_pt_regs(task) \242241 ((struct pt_regs *)(task_ksp0(task) - KSTK_PTREGS_GAP) - 1)242242+#define current_pt_regs() \243243+ ((struct pt_regs *)((stack_pointer | (THREAD_SIZE - 1)) - \244244+ (KSTK_PTREGS_GAP - 1)) - 1)243245#define task_sp(task) (task_pt_regs(task)->sp)244246#define task_pc(task) (task_pt_regs(task)->pc)245247/* Aliases for pc and sp (used in fs/proc/array.c) */
+4-1
arch/tile/include/asm/switch_to.h
···6868/* Support function for forking a new task. */6969void ret_from_fork(void);70707171-/* Called from ret_from_fork() when a new process starts up. */7171+/* Support function for forking a new kernel thread. */7272+void ret_from_kernel_thread(void *fn, void *arg);7373+7474+/* Called from ret_from_xxx() when a new process starts up. */7275struct task_struct *sim_notify_fork(struct task_struct *prev);73767477#endif /* !__ASSEMBLY__ */
+14-6
arch/tile/include/asm/syscalls.h
···51515252#ifndef __tilegx__5353/* mm/fault.c */5454-long sys_cmpxchg_badaddr(unsigned long address, struct pt_regs *);5555-long _sys_cmpxchg_badaddr(unsigned long address);5454+long sys_cmpxchg_badaddr(unsigned long address);5655#endif57565857#ifdef CONFIG_COMPAT···6263long sys_ftruncate64(unsigned int fd, loff_t length);6364#endif64656666+/* Provide versions of standard syscalls that use current_pt_regs(). */6767+long sys_clone(unsigned long clone_flags, unsigned long newsp,6868+ void __user *parent_tid, void __user *child_tid);6969+long sys_execve(const char __user *filename,7070+ const char __user *const __user *argv,7171+ const char __user *const __user *envp);7272+long sys_rt_sigreturn(void);7373+long sys_sigaltstack(const stack_t __user *, stack_t __user *);7474+#define sys_clone sys_clone7575+#define sys_execve sys_execve7676+#define sys_rt_sigreturn sys_rt_sigreturn7777+#define sys_sigaltstack sys_sigaltstack7878+6579/* These are the intvec*.S trampolines. */6666-long _sys_sigaltstack(const stack_t __user *, stack_t __user *);6780long _sys_rt_sigreturn(void);6881long _sys_clone(unsigned long clone_flags, unsigned long newsp,6982 void __user *parent_tid, void __user *child_tid);7070-long _sys_execve(const char __user *filename,7171- const char __user *const __user *argv,7272- const char __user *const __user *envp);73837484#include <asm-generic/syscalls.h>7585
···102102#define compat_sys_fadvise64_64 sys32_fadvise64_64103103#define compat_sys_readahead sys32_readahead104104105105-/* Call the trampolines to manage pt_regs where necessary. */106106-#define compat_sys_execve _compat_sys_execve107107-#define compat_sys_sigaltstack _compat_sys_sigaltstack105105+/* Call the assembly trampolines where necessary. */108106#define compat_sys_rt_sigreturn _compat_sys_rt_sigreturn107107+#undef sys_clone109108#define sys_clone _sys_clone110109111110/*
+5-5
arch/tile/kernel/compat_signal.c
···197197}198198199199long compat_sys_sigaltstack(const struct compat_sigaltstack __user *uss_ptr,200200- struct compat_sigaltstack __user *uoss_ptr,201201- struct pt_regs *regs)200200+ struct compat_sigaltstack __user *uoss_ptr)202201{203202 stack_t uss, uoss;204203 int ret;···218219 set_fs(KERNEL_DS);219220 ret = do_sigaltstack(uss_ptr ? (stack_t __user __force *)&uss : NULL,220221 (stack_t __user __force *)&uoss,221221- (unsigned long)compat_ptr(regs->sp));222222+ (unsigned long)compat_ptr(current_pt_regs()->sp));222223 set_fs(seg);223224 if (ret >= 0 && uoss_ptr) {224225 if (!access_ok(VERIFY_WRITE, uoss_ptr, sizeof(*uoss_ptr)) ||···231232}232233233234/* The assembly shim for this function arranges to ignore the return value. */234234-long compat_sys_rt_sigreturn(struct pt_regs *regs)235235+long compat_sys_rt_sigreturn(void)235236{237237+ struct pt_regs *regs = current_pt_regs();236238 struct compat_rt_sigframe __user *frame =237239 (struct compat_rt_sigframe __user *) compat_ptr(regs->sp);238240 sigset_t set;···248248 if (restore_sigcontext(regs, &frame->uc.uc_mcontext))249249 goto badframe;250250251251- if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL, regs) != 0)251251+ if (compat_sys_sigaltstack(&frame->uc.uc_stack, NULL) == -EFAULT)252252 goto badframe;253253254254 return 0;
-11
arch/tile/kernel/entry.S
···2828 STD_ENDPROC(current_text_addr)29293030/*3131- * Implement execve(). The i386 code has a note that forking from kernel3232- * space results in no copy on write until the execve, so we should be3333- * careful not to write to the stack here.3434- */3535-STD_ENTRY(kernel_execve)3636- moveli TREG_SYSCALL_NR_NAME, __NR_execve3737- swint13838- jrp lr3939- STD_ENDPROC(kernel_execve)4040-4141-/*4231 * We don't run this function directly, but instead copy it to a page4332 * we map into every user process. See vdso_setup().4433 *
+16-13
arch/tile/kernel/intvec_32.S
···12911291 }12921292 STD_ENDPROC(ret_from_fork)1293129312941294+STD_ENTRY(ret_from_kernel_thread)12951295+ jal sim_notify_fork12961296+ jal schedule_tail12971297+ FEEDBACK_REENTER(ret_from_fork)12981298+ {12991299+ move r0, r3113001300+ jalr r3013011301+ }13021302+ FEEDBACK_REENTER(ret_from_kernel_thread)13031303+ {13041304+ movei r30, 0 /* not an NMI */13051305+ j .Lresume_userspace /* jump into middle of interrupt_return */13061306+ }13071307+ STD_ENDPROC(ret_from_kernel_thread)13081308+12941309 /*12951310 * Code for ill interrupt.12961311 */···14521437 panic "Unhandled interrupt %#x: PC %#lx"14531438 STD_ENDPROC(bad_intr)1454143914551455-/* Put address of pt_regs in reg and jump. */14561456-#define PTREGS_SYSCALL(x, reg) \14571457- STD_ENTRY(_##x); \14581458- { \14591459- PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \14601460- j x \14611461- }; \14621462- STD_ENDPROC(_##x)14631463-14641440/*14651441 * Special-case sigreturn to not write r0 to the stack on return.14661442 * This is technically more efficient, but it also avoids difficulties···14671461 }; \14681462 STD_ENDPROC(_##x)1469146314701470-PTREGS_SYSCALL(sys_execve, r3)14711471-PTREGS_SYSCALL(sys_sigaltstack, r2)14721464PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)14731473-PTREGS_SYSCALL(sys_cmpxchg_badaddr, r1)1474146514751475-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */14661466+/* Save additional callee-saves to pt_regs and jump to standard function. */14761467STD_ENTRY(_sys_clone)14771468 push_extra_callee_saves r414781469 j sys_clone
+16-14
arch/tile/kernel/intvec_64.S
···11501150 }11511151 STD_ENDPROC(ret_from_fork)1152115211531153+STD_ENTRY(ret_from_kernel_thread)11541154+ jal sim_notify_fork11551155+ jal schedule_tail11561156+ FEEDBACK_REENTER(ret_from_fork)11571157+ {11581158+ move r0, r3111591159+ jalr r3011601160+ }11611161+ FEEDBACK_REENTER(ret_from_kernel_thread)11621162+ {11631163+ movei r30, 0 /* not an NMI */11641164+ j .Lresume_userspace /* jump into middle of interrupt_return */11651165+ }11661166+ STD_ENDPROC(ret_from_kernel_thread)11671167+11531168/* Various stub interrupt handlers and syscall handlers */1154116911551170STD_ENTRY_LOCAL(_kernel_double_fault)···11811166 panic "Unhandled interrupt %#x: PC %#lx"11821167 STD_ENDPROC(bad_intr)1183116811841184-/* Put address of pt_regs in reg and jump. */11851185-#define PTREGS_SYSCALL(x, reg) \11861186- STD_ENTRY(_##x); \11871187- { \11881188- PTREGS_PTR(reg, PTREGS_OFFSET_BASE); \11891189- j x \11901190- }; \11911191- STD_ENDPROC(_##x)11921192-11931169/*11941170 * Special-case sigreturn to not write r0 to the stack on return.11951171 * This is technically more efficient, but it also avoids difficulties···11961190 }; \11971191 STD_ENDPROC(_##x)1198119211991199-PTREGS_SYSCALL(sys_execve, r3)12001200-PTREGS_SYSCALL(sys_sigaltstack, r2)12011193PTREGS_SYSCALL_SIGRETURN(sys_rt_sigreturn, r0)12021194#ifdef CONFIG_COMPAT12031203-PTREGS_SYSCALL(compat_sys_execve, r3)12041204-PTREGS_SYSCALL(compat_sys_sigaltstack, r2)12051195PTREGS_SYSCALL_SIGRETURN(compat_sys_rt_sigreturn, r0)12061196#endif1207119712081208-/* Save additional callee-saves to pt_regs, put address in r4 and jump. */11981198+/* Save additional callee-saves to pt_regs and jump to standard function. */12091199STD_ENTRY(_sys_clone)12101200 push_extra_callee_saves r412111201 j sys_clone
+51-123
arch/tile/kernel/process.c
···157157static void save_arch_state(struct thread_struct *t);158158159159int copy_thread(unsigned long clone_flags, unsigned long sp,160160- unsigned long stack_size,161161- struct task_struct *p, struct pt_regs *regs)160160+ unsigned long arg,161161+ struct task_struct *p, struct pt_regs *unused)162162{163163- struct pt_regs *childregs;163163+ struct pt_regs *childregs = task_pt_regs(p);164164 unsigned long ksp;165165+ unsigned long *callee_regs;165166166167 /*167167- * When creating a new kernel thread we pass sp as zero.168168- * Assign it to a reasonable value now that we have the stack.168168+ * Set up the stack and stack pointer appropriately for the169169+ * new child to find itself woken up in __switch_to().170170+ * The callee-saved registers must be on the stack to be read;171171+ * the new task will then jump to assembly support to handle172172+ * calling schedule_tail(), etc., and (for userspace tasks)173173+ * returning to the context set up in the pt_regs.169174 */170170- if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0))171171- sp = KSTK_TOP(p);175175+ ksp = (unsigned long) childregs;176176+ ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */177177+ ((long *)ksp)[0] = ((long *)ksp)[1] = 0;178178+ ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);179179+ callee_regs = (unsigned long *)ksp;180180+ ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */181181+ ((long *)ksp)[0] = ((long *)ksp)[1] = 0;182182+ p->thread.ksp = ksp;183183+184184+ /* Record the pid of the task that created this one. */185185+ p->thread.creator_pid = current->pid;186186+187187+ if (unlikely(p->flags & PF_KTHREAD)) {188188+ /* kernel thread */189189+ memset(childregs, 0, sizeof(struct pt_regs));190190+ memset(&callee_regs[2], 0,191191+ (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long));192192+ callee_regs[0] = sp; /* r30 = function */193193+ callee_regs[1] = arg; /* r31 = arg */194194+ childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0);195195+ p->thread.pc = (unsigned long) ret_from_kernel_thread;196196+ return 0;197197+ }198198+199199+ /*200200+ * Start new thread in ret_from_fork so it schedules properly201201+ * and then return from interrupt like the parent.202202+ */203203+ p->thread.pc = (unsigned long) ret_from_fork;172204173205 /*174206 * Do not clone step state from the parent; each thread···209177 task_thread_info(p)->step_state = NULL;210178211179 /*212212- * Start new thread in ret_from_fork so it schedules properly213213- * and then return from interrupt like the parent.214214- */215215- p->thread.pc = (unsigned long) ret_from_fork;216216-217217- /* Save user stack top pointer so we can ID the stack vm area later. */218218- p->thread.usp0 = sp;219219-220220- /* Record the pid of the process that created this one. */221221- p->thread.creator_pid = current->pid;222222-223223- /*224180 * Copy the registers onto the kernel stack so the225181 * return-from-interrupt code will reload it into registers.226182 */227227- childregs = task_pt_regs(p);228228- *childregs = *regs;183183+ *childregs = *current_pt_regs();229184 childregs->regs[0] = 0; /* return value is zero */230230- childregs->sp = sp; /* override with new user stack pointer */185185+ if (sp)186186+ childregs->sp = sp; /* override with new user stack pointer */187187+ memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG],188188+ CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));189189+190190+ /* Save user stack top pointer so we can ID the stack vm area later. */191191+ p->thread.usp0 = childregs->sp;231192232193 /*233194 * If CLONE_SETTLS is set, set "tp" in the new task to "r4",234195 * which is passed in as arg #5 to sys_clone().235196 */236197 if (clone_flags & CLONE_SETTLS)237237- childregs->tp = regs->regs[4];198198+ childregs->tp = childregs->regs[4];238199239239- /*240240- * Copy the callee-saved registers from the passed pt_regs struct241241- * into the context-switch callee-saved registers area.242242- * This way when we start the interrupt-return sequence, the243243- * callee-save registers will be correctly in registers, which244244- * is how we assume the compiler leaves them as we start doing245245- * the normal return-from-interrupt path after calling C code.246246- * Zero out the C ABI save area to mark the top of the stack.247247- */248248- ksp = (unsigned long) childregs;249249- ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */250250- ((long *)ksp)[0] = ((long *)ksp)[1] = 0;251251- ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);252252- memcpy((void *)ksp, ®s->regs[CALLEE_SAVED_FIRST_REG],253253- CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));254254- ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */255255- ((long *)ksp)[0] = ((long *)ksp)[1] = 0;256256- p->thread.ksp = ksp;257200258201#if CHIP_HAS_TILE_DMA()259202 /*···585578}586579587580/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */588588-SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,589589- void __user *, parent_tidptr, void __user *, child_tidptr,590590- struct pt_regs *, regs)581581+SYSCALL_DEFINE4(clone, unsigned long, clone_flags, unsigned long, newsp,582582+ void __user *, parent_tidptr, void __user *, child_tidptr)591583{592592- if (!newsp)593593- newsp = regs->sp;594594- return do_fork(clone_flags, newsp, regs, 0,584584+ return do_fork(clone_flags, newsp, current_pt_regs(), 0,595585 parent_tidptr, child_tidptr);596586}597597-598598-/*599599- * sys_execve() executes a new program.600600- */601601-SYSCALL_DEFINE4(execve, const char __user *, path,602602- const char __user *const __user *, argv,603603- const char __user *const __user *, envp,604604- struct pt_regs *, regs)605605-{606606- long error;607607- struct filename *filename;608608-609609- filename = getname(path);610610- error = PTR_ERR(filename);611611- if (IS_ERR(filename))612612- goto out;613613- error = do_execve(filename->name, argv, envp, regs);614614- putname(filename);615615- if (error == 0)616616- single_step_execve();617617-out:618618- return error;619619-}620620-621621-#ifdef CONFIG_COMPAT622622-long compat_sys_execve(const char __user *path,623623- compat_uptr_t __user *argv,624624- compat_uptr_t __user *envp,625625- struct pt_regs *regs)626626-{627627- long error;628628- struct filename *filename;629629-630630- filename = getname(path);631631- error = PTR_ERR(filename);632632- if (IS_ERR(filename))633633- goto out;634634- error = compat_do_execve(filename->name, argv, envp, regs);635635- putname(filename);636636- if (error == 0)637637- single_step_execve();638638-out:639639- return error;640640-}641641-#endif642587643588unsigned long get_wchan(struct task_struct *p)644589{···608649609650 return 0;610651}611611-612612-/*613613- * We pass in lr as zero (cleared in kernel_thread) and the caller614614- * part of the backtrace ABI on the stack also zeroed (in copy_thread)615615- * so that backtraces will stop with this function.616616- * Note that we don't use r0, since copy_thread() clears it.617617- */618618-static void start_kernel_thread(int dummy, int (*fn)(int), int arg)619619-{620620- do_exit(fn(arg));621621-}622622-623623-/*624624- * Create a kernel thread625625- */626626-int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)627627-{628628- struct pt_regs regs;629629-630630- memset(®s, 0, sizeof(regs));631631- regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */632632- regs.pc = (long) start_kernel_thread;633633- regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */634634- regs.regs[1] = (long) fn; /* function pointer */635635- regs.regs[2] = (long) arg; /* parameter register */636636-637637- /* Ok, create the new process.. */638638- return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s,639639- 0, NULL, NULL);640640-}641641-EXPORT_SYMBOL(kernel_thread);642652643653/* Flush thread state. */644654void flush_thread(void)
···106106#define sys_readahead sys32_readahead107107#endif108108109109-/* Call the trampolines to manage pt_regs where necessary. */110110-#define sys_execve _sys_execve111111-#define sys_sigaltstack _sys_sigaltstack109109+/* Call the assembly trampolines where necessary. */110110+#undef sys_rt_sigreturn112111#define sys_rt_sigreturn _sys_rt_sigreturn112112+#undef sys_clone113113#define sys_clone _sys_clone114114-#ifndef __tilegx__115115-#define sys_cmpxchg_badaddr _sys_cmpxchg_badaddr116116-#endif117114118115/*119116 * Note that we can't include <linux/unistd.h> here since the header
+3-2
arch/tile/mm/fault.c
···7070 * Synthesize the fault a PL0 process would get by doing a word-load of7171 * an unaligned address or a high kernel address.7272 */7373-SYSCALL_DEFINE2(cmpxchg_badaddr, unsigned long, address,7474- struct pt_regs *, regs)7373+SYSCALL_DEFINE1(cmpxchg_badaddr, unsigned long, address)7574{7575+ struct pt_regs *regs = current_pt_regs();7676+7677 if (address >= PAGE_OFFSET)7778 force_sig_info_fault("atomic segfault", SIGSEGV, SEGV_MAPERR,7879 address, INT_DTLB_MISS, current, regs);