aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm64/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm64/kernel/process.c')
-rw-r--r--arch/arm64/kernel/process.c101
1 files changed, 30 insertions, 71 deletions
diff --git a/arch/arm64/kernel/process.c b/arch/arm64/kernel/process.c
index f22965ea1cfc..8a5f3341861e 100644
--- a/arch/arm64/kernel/process.c
+++ b/arch/arm64/kernel/process.c
@@ -240,27 +240,41 @@ int copy_thread(unsigned long clone_flags, unsigned long stack_start,
240 struct pt_regs *childregs = task_pt_regs(p); 240 struct pt_regs *childregs = task_pt_regs(p);
241 unsigned long tls = p->thread.tp_value; 241 unsigned long tls = p->thread.tp_value;
242 242
243 *childregs = *regs; 243 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
244 childregs->regs[0] = 0;
245 244
246 if (is_compat_thread(task_thread_info(p))) 245 if (likely(regs)) {
247 childregs->compat_sp = stack_start; 246 *childregs = *regs;
248 else { 247 childregs->regs[0] = 0;
248 if (is_compat_thread(task_thread_info(p))) {
249 if (stack_start)
250 childregs->compat_sp = stack_start;
251 } else {
252 /*
253 * Read the current TLS pointer from tpidr_el0 as it may be
254 * out-of-sync with the saved value.
255 */
256 asm("mrs %0, tpidr_el0" : "=r" (tls));
257 if (stack_start) {
258 /* 16-byte aligned stack mandatory on AArch64 */
259 if (stack_start & 15)
260 return -EINVAL;
261 childregs->sp = stack_start;
262 }
263 }
249 /* 264 /*
250 * Read the current TLS pointer from tpidr_el0 as it may be 265 * If a TLS pointer was passed to clone (4th argument), use it
251 * out-of-sync with the saved value. 266 * for the new thread.
252 */ 267 */
253 asm("mrs %0, tpidr_el0" : "=r" (tls)); 268 if (clone_flags & CLONE_SETTLS)
254 childregs->sp = stack_start; 269 tls = regs->regs[3];
270 } else {
271 memset(childregs, 0, sizeof(struct pt_regs));
272 childregs->pstate = PSR_MODE_EL1h;
273 p->thread.cpu_context.x19 = stack_start;
274 p->thread.cpu_context.x20 = stk_sz;
255 } 275 }
256
257 memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context));
258 p->thread.cpu_context.sp = (unsigned long)childregs;
259 p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 276 p->thread.cpu_context.pc = (unsigned long)ret_from_fork;
260 277 p->thread.cpu_context.sp = (unsigned long)childregs;
261 /* If a TLS pointer was passed to clone, use that for the new thread. */
262 if (clone_flags & CLONE_SETTLS)
263 tls = regs->regs[3];
264 p->thread.tp_value = tls; 278 p->thread.tp_value = tls;
265 279
266 ptrace_hw_copy_thread(p); 280 ptrace_hw_copy_thread(p);
@@ -309,61 +323,6 @@ struct task_struct *__switch_to(struct task_struct *prev,
309 return last; 323 return last;
310} 324}
311 325
312/*
313 * Fill in the task's elfregs structure for a core dump.
314 */
315int dump_task_regs(struct task_struct *t, elf_gregset_t *elfregs)
316{
317 elf_core_copy_regs(elfregs, task_pt_regs(t));
318 return 1;
319}
320
321/*
322 * fill in the fpe structure for a core dump...
323 */
324int dump_fpu (struct pt_regs *regs, struct user_fp *fp)
325{
326 return 0;
327}
328EXPORT_SYMBOL(dump_fpu);
329
330/*
331 * Shuffle the argument into the correct register before calling the
332 * thread function. x1 is the thread argument, x2 is the pointer to
333 * the thread function, and x3 points to the exit function.
334 */
335extern void kernel_thread_helper(void);
336asm( ".section .text\n"
337" .align\n"
338" .type kernel_thread_helper, #function\n"
339"kernel_thread_helper:\n"
340" mov x0, x1\n"
341" mov x30, x3\n"
342" br x2\n"
343" .size kernel_thread_helper, . - kernel_thread_helper\n"
344" .previous");
345
346#define kernel_thread_exit do_exit
347
348/*
349 * Create a kernel thread.
350 */
351pid_t kernel_thread(int (*fn)(void *), void *arg, unsigned long flags)
352{
353 struct pt_regs regs;
354
355 memset(&regs, 0, sizeof(regs));
356
357 regs.regs[1] = (unsigned long)arg;
358 regs.regs[2] = (unsigned long)fn;
359 regs.regs[3] = (unsigned long)kernel_thread_exit;
360 regs.pc = (unsigned long)kernel_thread_helper;
361 regs.pstate = PSR_MODE_EL1h;
362
363 return do_fork(flags|CLONE_VM|CLONE_UNTRACED, 0, &regs, 0, NULL, NULL);
364}
365EXPORT_SYMBOL(kernel_thread);
366
367unsigned long get_wchan(struct task_struct *p) 326unsigned long get_wchan(struct task_struct *p)
368{ 327{
369 struct stackframe frame; 328 struct stackframe frame;