Loading arch/cris/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ config CRIS select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 select GENERIC_CMOS_UPDATE select MODULES_USE_ELF_RELA select GENERIC_KERNEL_THREAD config HZ int Loading arch/cris/arch-v10/kernel/entry.S +9 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl hwbreakpoint Loading Loading @@ -82,6 +83,13 @@ ret_from_fork: ba ret_from_sys_call nop ret_from_kernel_thread: jsr schedule_tail move.d $r2, $r10 ; argument is here jsr $r1 ; call the payload moveq 0, $r10 jsr sys_exit ; never returns ret_from_intr: ;; check for resched if preemptive kernel or if we're going back to user-mode ;; this test matches the user_regs(regs) macro Loading arch/cris/arch-v10/kernel/process.c +24 −59 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <arch/svinto.h> #include <linux/init.h> #include <arch/system.h> #include <asm/ptrace.h> #ifdef CONFIG_ETRAX_GPIO void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ Loading Loading @@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->irp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) { fn(arg); do_exit(-1); /* Should never be called, return bad exit value */ } /* * Create a kernel thread */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); /* Don't use r10 since that is set to 0 in copy_thread */ regs.r11 = (unsigned long)fn; regs.r12 = (unsigned long)arg; regs.irp = (unsigned long)kernel_thread_helper; regs.dccr = 1 << I_DCCR_BITNR; /* Ok, create the new process.. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* setup the child's kernel stack with a pt_regs and switch_stack on it. * it will be un-nested during _resume and _ret_from_sys_call when the * new thread is scheduled. Loading @@ -115,30 +91,36 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) * */ asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long unused, unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs * childregs; struct switch_stack *swstack; struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; /* put the pt_regs structure at the end of the new kernel stack page and fix it up * remember that the task_struct doubles as the kernel stack for the task */ childregs = task_pt_regs(p); if (unlikely(p->flags & PF_KTHREAD)) { memset(swstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); swstack->r1 = usp; swstack->r2 = arg; childregs->dccr = 1 << I_DCCR_BITNR; swstack->return_ip = (unsigned long) ret_from_kernel_thread; p->thread.ksp = (unsigned long) swstack; p->thread.usp = 0; return 0; } *childregs = *regs; /* struct copy of pt_regs */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* child returns 0 after a fork/clone */ /* put the switch stack right below the pt_regs */ swstack = ((struct switch_stack *)childregs) - 1; swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ /* we want to return into ret_from_sys_call after the _resume */ Loading @@ -161,45 +143,28 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } /* * Be aware of the "magic" 7th argument in the four system-calls below. * They need the latest stackframe, which is put as the 7th argument by * entry.S. The previous arguments are dummies or actually used, but need * to be defined to reach the 7th argument. * * N.B.: Another method to get the stackframe is to use current_regs(). But * it returns the latest stack-frame stacked when going from _user mode_ and * some of these (at least sys_clone) are called from kernel-mode sometimes * (for example during kernel_thread, above) and thus cannot use it. Thus, * to be sure not to get any surprises, we use the method for the other calls * as well. */ asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) asmlinkage int sys_fork(void) { return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* if newusp is 0, we just grab the old usp */ /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, int* parent_tid, int* child_tid, long mof, long srp, struct pt_regs *regs) int* parent_tid, int* child_tid) { if (!newusp) newusp = rdusp(); return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* vfork is a system call in i386 because of register-pressure - maybe * we can remove it and handle it in libc but we put it here until then. */ asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) asmlinkage int sys_vfork(void) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* Loading arch/cris/arch-v32/kernel/entry.S +13 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl nmi_interrupt Loading Loading @@ -84,6 +85,18 @@ ret_from_fork: nop .size ret_from_fork, . - ret_from_fork .type ret_from_kernel_thread,@function ret_from_kernel_thread: jsr schedule_tail nop move.d $r2, $r10 jsr $r1 nop moveq 0, $r10 jsr sys_exit nop .size ret_from_kernel_thread, . - ret_from_kernel_thread .type ret_from_intr,@function ret_from_intr: ;; Check for resched if preemptive kernel, or if we're going back to Loading arch/cris/arch-v32/kernel/process.c +22 −52 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <hwregs/reg_map.h> #include <hwregs/timer_defs.h> #include <hwregs/intr_vect_defs.h> #include <asm/ptrace.h> extern void stop_watchdog(void); Loading Loading @@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->erp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) { fn(arg); do_exit(-1); /* Should never be called, return bad exit value. */ } /* Create a kernel thread. */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); /* Don't use r10 since that is set to 0 in copy_thread. */ regs.r11 = (unsigned long) fn; regs.r12 = (unsigned long) arg; regs.erp = (unsigned long) kernel_thread_helper; regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); /* Create the new process. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. * It will be unnested during _resume and _ret_from_sys_call when the new thread Loading @@ -129,23 +105,33 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ extern asmlinkage void ret_from_fork(void); extern asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long unused, unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; struct switch_stack *swstack; struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; /* * Put the pt_regs structure at the end of the new kernel stack page and * fix it up. Note: the task_struct doubles as the kernel stack for the * task. */ childregs = task_pt_regs(p); if (unlikely(p->flags & PF_KTHREAD)) { memset(swstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); swstack->r1 = usp; swstack->r2 = arg; childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); swstack->return_ip = (unsigned long) ret_from_kernel_thread; p->thread.ksp = (unsigned long) swstack; p->thread.usp = 0; return 0; } *childregs = *regs; /* Struct copy of pt_regs. */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ /* Set a new TLS ? Loading @@ -156,7 +142,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Put the switch stack right below the pt_regs. */ swstack = ((struct switch_stack *) childregs) - 1; /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ swstack->r9 = 0; Loading @@ -174,35 +159,21 @@ copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } /* * Be aware of the "magic" 7th argument in the four system-calls below. * They need the latest stackframe, which is put as the 7th argument by * entry.S. The previous arguments are dummies or actually used, but need * to be defined to reach the 7th argument. * * N.B.: Another method to get the stackframe is to use current_regs(). But * it returns the latest stack-frame stacked when going from _user mode_ and * some of these (at least sys_clone) are called from kernel-mode sometimes * (for example during kernel_thread, above) and thus cannot use it. Thus, * to be sure not to get any surprises, we use the method for the other calls * as well. */ asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) sys_fork(void) { return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid, unsigned long tls, long srp, struct pt_regs *regs) unsigned long tls) { if (!newusp) newusp = rdusp(); return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* Loading @@ -210,10 +181,9 @@ sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child * we can remove it and handle it in libc but we put it here until then. */ asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) sys_vfork(void) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* sys_execve() executes a new program. */ Loading Loading
arch/cris/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -49,6 +49,7 @@ config CRIS select GENERIC_SMP_IDLE_THREAD if ETRAX_ARCH_V32 select GENERIC_CMOS_UPDATE select MODULES_USE_ELF_RELA select GENERIC_KERNEL_THREAD config HZ int Loading
arch/cris/arch-v10/kernel/entry.S +9 −1 Original line number Diff line number Diff line Loading @@ -35,6 +35,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl hwbreakpoint Loading Loading @@ -82,6 +83,13 @@ ret_from_fork: ba ret_from_sys_call nop ret_from_kernel_thread: jsr schedule_tail move.d $r2, $r10 ; argument is here jsr $r1 ; call the payload moveq 0, $r10 jsr sys_exit ; never returns ret_from_intr: ;; check for resched if preemptive kernel or if we're going back to user-mode ;; this test matches the user_regs(regs) macro Loading
arch/cris/arch-v10/kernel/process.c +24 −59 Original line number Diff line number Diff line Loading @@ -17,6 +17,7 @@ #include <arch/svinto.h> #include <linux/init.h> #include <arch/system.h> #include <asm/ptrace.h> #ifdef CONFIG_ETRAX_GPIO void etrax_gpio_wake_up_check(void); /* drivers/gpio.c */ Loading Loading @@ -81,31 +82,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->irp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) { fn(arg); do_exit(-1); /* Should never be called, return bad exit value */ } /* * Create a kernel thread */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); /* Don't use r10 since that is set to 0 in copy_thread */ regs.r11 = (unsigned long)fn; regs.r12 = (unsigned long)arg; regs.irp = (unsigned long)kernel_thread_helper; regs.dccr = 1 << I_DCCR_BITNR; /* Ok, create the new process.. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* setup the child's kernel stack with a pt_regs and switch_stack on it. * it will be un-nested during _resume and _ret_from_sys_call when the * new thread is scheduled. Loading @@ -115,30 +91,36 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) * */ asmlinkage void ret_from_fork(void); asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long unused, unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs * childregs; struct switch_stack *swstack; struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *)childregs) - 1; /* put the pt_regs structure at the end of the new kernel stack page and fix it up * remember that the task_struct doubles as the kernel stack for the task */ childregs = task_pt_regs(p); if (unlikely(p->flags & PF_KTHREAD)) { memset(swstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); swstack->r1 = usp; swstack->r2 = arg; childregs->dccr = 1 << I_DCCR_BITNR; swstack->return_ip = (unsigned long) ret_from_kernel_thread; p->thread.ksp = (unsigned long) swstack; p->thread.usp = 0; return 0; } *childregs = *regs; /* struct copy of pt_regs */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* child returns 0 after a fork/clone */ /* put the switch stack right below the pt_regs */ swstack = ((struct switch_stack *)childregs) - 1; swstack->r9 = 0; /* parameter to ret_from_sys_call, 0 == dont restart the syscall */ /* we want to return into ret_from_sys_call after the _resume */ Loading @@ -161,45 +143,28 @@ int copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } /* * Be aware of the "magic" 7th argument in the four system-calls below. * They need the latest stackframe, which is put as the 7th argument by * entry.S. The previous arguments are dummies or actually used, but need * to be defined to reach the 7th argument. * * N.B.: Another method to get the stackframe is to use current_regs(). But * it returns the latest stack-frame stacked when going from _user mode_ and * some of these (at least sys_clone) are called from kernel-mode sometimes * (for example during kernel_thread, above) and thus cannot use it. Thus, * to be sure not to get any surprises, we use the method for the other calls * as well. */ asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) asmlinkage int sys_fork(void) { return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* if newusp is 0, we just grab the old usp */ /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, int* parent_tid, int* child_tid, long mof, long srp, struct pt_regs *regs) int* parent_tid, int* child_tid) { if (!newusp) newusp = rdusp(); return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* vfork is a system call in i386 because of register-pressure - maybe * we can remove it and handle it in libc but we put it here until then. */ asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) asmlinkage int sys_vfork(void) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* Loading
arch/cris/arch-v32/kernel/entry.S +13 −0 Original line number Diff line number Diff line Loading @@ -31,6 +31,7 @@ .globl system_call .globl ret_from_intr .globl ret_from_fork .globl ret_from_kernel_thread .globl resume .globl multiple_interrupt .globl nmi_interrupt Loading Loading @@ -84,6 +85,18 @@ ret_from_fork: nop .size ret_from_fork, . - ret_from_fork .type ret_from_kernel_thread,@function ret_from_kernel_thread: jsr schedule_tail nop move.d $r2, $r10 jsr $r1 nop moveq 0, $r10 jsr sys_exit nop .size ret_from_kernel_thread, . - ret_from_kernel_thread .type ret_from_intr,@function ret_from_intr: ;; Check for resched if preemptive kernel, or if we're going back to Loading
arch/cris/arch-v32/kernel/process.c +22 −52 Original line number Diff line number Diff line Loading @@ -16,6 +16,7 @@ #include <hwregs/reg_map.h> #include <hwregs/timer_defs.h> #include <hwregs/intr_vect_defs.h> #include <asm/ptrace.h> extern void stop_watchdog(void); Loading Loading @@ -94,31 +95,6 @@ unsigned long thread_saved_pc(struct task_struct *t) return task_pt_regs(t)->erp; } static void kernel_thread_helper(void* dummy, int (*fn)(void *), void * arg) { fn(arg); do_exit(-1); /* Should never be called, return bad exit value. */ } /* Create a kernel thread. */ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) { struct pt_regs regs; memset(®s, 0, sizeof(regs)); /* Don't use r10 since that is set to 0 in copy_thread. */ regs.r11 = (unsigned long) fn; regs.r12 = (unsigned long) arg; regs.erp = (unsigned long) kernel_thread_helper; regs.ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); /* Create the new process. */ return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, ®s, 0, NULL, NULL); } /* * Setup the child's kernel stack with a pt_regs and call switch_stack() on it. * It will be unnested during _resume and _ret_from_sys_call when the new thread Loading @@ -129,23 +105,33 @@ kernel_thread(int (*fn)(void *), void * arg, unsigned long flags) */ extern asmlinkage void ret_from_fork(void); extern asmlinkage void ret_from_kernel_thread(void); int copy_thread(unsigned long clone_flags, unsigned long usp, unsigned long unused, unsigned long arg, struct task_struct *p, struct pt_regs *regs) { struct pt_regs *childregs; struct switch_stack *swstack; struct pt_regs *childregs = task_pt_regs(p); struct switch_stack *swstack = ((struct switch_stack *) childregs) - 1; /* * Put the pt_regs structure at the end of the new kernel stack page and * fix it up. Note: the task_struct doubles as the kernel stack for the * task. */ childregs = task_pt_regs(p); if (unlikely(p->flags & PF_KTHREAD)) { memset(swstack, 0, sizeof(struct switch_stack) + sizeof(struct pt_regs)); swstack->r1 = usp; swstack->r2 = arg; childregs->ccs = 1 << (I_CCS_BITNR + CCS_SHIFT); swstack->return_ip = (unsigned long) ret_from_kernel_thread; p->thread.ksp = (unsigned long) swstack; p->thread.usp = 0; return 0; } *childregs = *regs; /* Struct copy of pt_regs. */ p->set_child_tid = p->clear_child_tid = NULL; childregs->r10 = 0; /* Child returns 0 after a fork/clone. */ /* Set a new TLS ? Loading @@ -156,7 +142,6 @@ copy_thread(unsigned long clone_flags, unsigned long usp, } /* Put the switch stack right below the pt_regs. */ swstack = ((struct switch_stack *) childregs) - 1; /* Parameter to ret_from_sys_call. 0 is don't restart the syscall. */ swstack->r9 = 0; Loading @@ -174,35 +159,21 @@ copy_thread(unsigned long clone_flags, unsigned long usp, return 0; } /* * Be aware of the "magic" 7th argument in the four system-calls below. * They need the latest stackframe, which is put as the 7th argument by * entry.S. The previous arguments are dummies or actually used, but need * to be defined to reach the 7th argument. * * N.B.: Another method to get the stackframe is to use current_regs(). But * it returns the latest stack-frame stacked when going from _user mode_ and * some of these (at least sys_clone) are called from kernel-mode sometimes * (for example during kernel_thread, above) and thus cannot use it. Thus, * to be sure not to get any surprises, we use the method for the other calls * as well. */ asmlinkage int sys_fork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) sys_fork(void) { return do_fork(SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* FIXME: Is parent_tid/child_tid really third/fourth argument? Update lib? */ asmlinkage int sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child_tid, unsigned long tls, long srp, struct pt_regs *regs) unsigned long tls) { if (!newusp) newusp = rdusp(); return do_fork(flags, newusp, regs, 0, parent_tid, child_tid); return do_fork(flags, newusp, current_pt_regs(), 0, parent_tid, child_tid); } /* Loading @@ -210,10 +181,9 @@ sys_clone(unsigned long newusp, unsigned long flags, int *parent_tid, int *child * we can remove it and handle it in libc but we put it here until then. */ asmlinkage int sys_vfork(long r10, long r11, long r12, long r13, long mof, long srp, struct pt_regs *regs) sys_vfork(void) { return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), regs, 0, NULL, NULL); return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(), current_pt_regs(), 0, NULL, NULL); } /* sys_execve() executes a new program. */ Loading