aboutsummaryrefslogtreecommitdiffstats
path: root/arch/tile/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/tile/kernel/process.c')
-rw-r--r--arch/tile/kernel/process.c171
1 files changed, 45 insertions, 126 deletions
diff --git a/arch/tile/kernel/process.c b/arch/tile/kernel/process.c
index 307d010696c9..0e5661e7d00d 100644
--- a/arch/tile/kernel/process.c
+++ b/arch/tile/kernel/process.c
@@ -157,24 +157,43 @@ void arch_release_thread_info(struct thread_info *info)
157static void save_arch_state(struct thread_struct *t); 157static void save_arch_state(struct thread_struct *t);
158 158
159int copy_thread(unsigned long clone_flags, unsigned long sp, 159int copy_thread(unsigned long clone_flags, unsigned long sp,
160 unsigned long stack_size, 160 unsigned long arg, struct task_struct *p)
161 struct task_struct *p, struct pt_regs *regs)
162{ 161{
163 struct pt_regs *childregs; 162 struct pt_regs *childregs = task_pt_regs(p), *regs = current_pt_regs();
164 unsigned long ksp; 163 unsigned long ksp;
164 unsigned long *callee_regs;
165 165
166 /* 166 /*
167 * When creating a new kernel thread we pass sp as zero. 167 * Set up the stack and stack pointer appropriately for the
168 * Assign it to a reasonable value now that we have the stack. 168 * new child to find itself woken up in __switch_to().
169 * The callee-saved registers must be on the stack to be read;
170 * the new task will then jump to assembly support to handle
171 * calling schedule_tail(), etc., and (for userspace tasks)
172 * returning to the context set up in the pt_regs.
169 */ 173 */
170 if (sp == 0 && regs->ex1 == PL_ICS_EX1(KERNEL_PL, 0)) 174 ksp = (unsigned long) childregs;
171 sp = KSTK_TOP(p); 175 ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */
176 ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
177 ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
178 callee_regs = (unsigned long *)ksp;
179 ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */
180 ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
181 p->thread.ksp = ksp;
172 182
173 /* 183 /* Record the pid of the task that created this one. */
174 * Do not clone step state from the parent; each thread 184 p->thread.creator_pid = current->pid;
175 * must make its own lazily. 185
176 */ 186 if (unlikely(p->flags & PF_KTHREAD)) {
177 task_thread_info(p)->step_state = NULL; 187 /* kernel thread */
188 memset(childregs, 0, sizeof(struct pt_regs));
189 memset(&callee_regs[2], 0,
190 (CALLEE_SAVED_REGS_COUNT - 2) * sizeof(unsigned long));
191 callee_regs[0] = sp; /* r30 = function */
192 callee_regs[1] = arg; /* r31 = arg */
193 childregs->ex1 = PL_ICS_EX1(KERNEL_PL, 0);
194 p->thread.pc = (unsigned long) ret_from_kernel_thread;
195 return 0;
196 }
178 197
179 /* 198 /*
180 * Start new thread in ret_from_fork so it schedules properly 199 * Start new thread in ret_from_fork so it schedules properly
@@ -182,46 +201,33 @@ int copy_thread(unsigned long clone_flags, unsigned long sp,
182 */ 201 */
183 p->thread.pc = (unsigned long) ret_from_fork; 202 p->thread.pc = (unsigned long) ret_from_fork;
184 203
185 /* Save user stack top pointer so we can ID the stack vm area later. */ 204 /*
186 p->thread.usp0 = sp; 205 * Do not clone step state from the parent; each thread
187 206 * must make its own lazily.
188 /* Record the pid of the process that created this one. */ 207 */
189 p->thread.creator_pid = current->pid; 208 task_thread_info(p)->step_state = NULL;
190 209
191 /* 210 /*
192 * Copy the registers onto the kernel stack so the 211 * Copy the registers onto the kernel stack so the
193 * return-from-interrupt code will reload it into registers. 212 * return-from-interrupt code will reload it into registers.
194 */ 213 */
195 childregs = task_pt_regs(p); 214 *childregs = *current_pt_regs();
196 *childregs = *regs;
197 childregs->regs[0] = 0; /* return value is zero */ 215 childregs->regs[0] = 0; /* return value is zero */
198 childregs->sp = sp; /* override with new user stack pointer */ 216 if (sp)
217 childregs->sp = sp; /* override with new user stack pointer */
218 memcpy(callee_regs, &childregs->regs[CALLEE_SAVED_FIRST_REG],
219 CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
220
221 /* Save user stack top pointer so we can ID the stack vm area later. */
222 p->thread.usp0 = childregs->sp;
199 223
200 /* 224 /*
201 * If CLONE_SETTLS is set, set "tp" in the new task to "r4", 225 * If CLONE_SETTLS is set, set "tp" in the new task to "r4",
202 * which is passed in as arg #5 to sys_clone(). 226 * which is passed in as arg #5 to sys_clone().
203 */ 227 */
204 if (clone_flags & CLONE_SETTLS) 228 if (clone_flags & CLONE_SETTLS)
205 childregs->tp = regs->regs[4]; 229 childregs->tp = childregs->regs[4];
206 230
207 /*
208 * Copy the callee-saved registers from the passed pt_regs struct
209 * into the context-switch callee-saved registers area.
210 * This way when we start the interrupt-return sequence, the
211 * callee-save registers will be correctly in registers, which
212 * is how we assume the compiler leaves them as we start doing
213 * the normal return-from-interrupt path after calling C code.
214 * Zero out the C ABI save area to mark the top of the stack.
215 */
216 ksp = (unsigned long) childregs;
217 ksp -= C_ABI_SAVE_AREA_SIZE; /* interrupt-entry save area */
218 ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
219 ksp -= CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long);
220 memcpy((void *)ksp, &regs->regs[CALLEE_SAVED_FIRST_REG],
221 CALLEE_SAVED_REGS_COUNT * sizeof(unsigned long));
222 ksp -= C_ABI_SAVE_AREA_SIZE; /* __switch_to() save area */
223 ((long *)ksp)[0] = ((long *)ksp)[1] = 0;
224 p->thread.ksp = ksp;
225 231
226#if CHIP_HAS_TILE_DMA() 232#if CHIP_HAS_TILE_DMA()
227 /* 233 /*
@@ -577,62 +583,6 @@ int do_work_pending(struct pt_regs *regs, u32 thread_info_flags)
577 panic("work_pending: bad flags %#x\n", thread_info_flags); 583 panic("work_pending: bad flags %#x\n", thread_info_flags);
578} 584}
579 585
580/* Note there is an implicit fifth argument if (clone_flags & CLONE_SETTLS). */
581SYSCALL_DEFINE5(clone, unsigned long, clone_flags, unsigned long, newsp,
582 void __user *, parent_tidptr, void __user *, child_tidptr,
583 struct pt_regs *, regs)
584{
585 if (!newsp)
586 newsp = regs->sp;
587 return do_fork(clone_flags, newsp, regs, 0,
588 parent_tidptr, child_tidptr);
589}
590
591/*
592 * sys_execve() executes a new program.
593 */
594SYSCALL_DEFINE4(execve, const char __user *, path,
595 const char __user *const __user *, argv,
596 const char __user *const __user *, envp,
597 struct pt_regs *, regs)
598{
599 long error;
600 struct filename *filename;
601
602 filename = getname(path);
603 error = PTR_ERR(filename);
604 if (IS_ERR(filename))
605 goto out;
606 error = do_execve(filename->name, argv, envp, regs);
607 putname(filename);
608 if (error == 0)
609 single_step_execve();
610out:
611 return error;
612}
613
614#ifdef CONFIG_COMPAT
615long compat_sys_execve(const char __user *path,
616 compat_uptr_t __user *argv,
617 compat_uptr_t __user *envp,
618 struct pt_regs *regs)
619{
620 long error;
621 struct filename *filename;
622
623 filename = getname(path);
624 error = PTR_ERR(filename);
625 if (IS_ERR(filename))
626 goto out;
627 error = compat_do_execve(filename->name, argv, envp, regs);
628 putname(filename);
629 if (error == 0)
630 single_step_execve();
631out:
632 return error;
633}
634#endif
635
636unsigned long get_wchan(struct task_struct *p) 586unsigned long get_wchan(struct task_struct *p)
637{ 587{
638 struct KBacktraceIterator kbt; 588 struct KBacktraceIterator kbt;
@@ -650,37 +600,6 @@ unsigned long get_wchan(struct task_struct *p)
650 return 0; 600 return 0;
651} 601}
652 602
653/*
654 * We pass in lr as zero (cleared in kernel_thread) and the caller
655 * part of the backtrace ABI on the stack also zeroed (in copy_thread)
656 * so that backtraces will stop with this function.
657 * Note that we don't use r0, since copy_thread() clears it.
658 */
659static void start_kernel_thread(int dummy, int (*fn)(int), int arg)
660{
661 do_exit(fn(arg));
662}
663
664/*
665 * Create a kernel thread
666 */
667int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
668{
669 struct pt_regs regs;
670
671 memset(&regs, 0, sizeof(regs));
672 regs.ex1 = PL_ICS_EX1(KERNEL_PL, 0); /* run at kernel PL, no ICS */
673 regs.pc = (long) start_kernel_thread;
674 regs.flags = PT_FLAGS_CALLER_SAVES; /* need to restore r1 and r2 */
675 regs.regs[1] = (long) fn; /* function pointer */
676 regs.regs[2] = (long) arg; /* parameter register */
677
678 /* Ok, create the new process.. */
679 return do_fork(flags | CLONE_VM | CLONE_UNTRACED, 0, &regs,
680 0, NULL, NULL);
681}
682EXPORT_SYMBOL(kernel_thread);
683
684/* Flush thread state. */ 603/* Flush thread state. */
685void flush_thread(void) 604void flush_thread(void)
686{ 605{