xref: /linux/arch/csky/kernel/process.c (revision 9a87ffc99ec8eb8d35eed7c4f816d75f5cc9662e)
1e9564df7SGuo Ren // SPDX-License-Identifier: GPL-2.0
2e9564df7SGuo Ren // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd.
3e9564df7SGuo Ren 
4e9564df7SGuo Ren #include <linux/module.h>
5e9564df7SGuo Ren #include <linux/sched.h>
6e9564df7SGuo Ren #include <linux/sched/task_stack.h>
7e9564df7SGuo Ren #include <linux/sched/debug.h>
8e9564df7SGuo Ren #include <linux/delay.h>
9e9564df7SGuo Ren #include <linux/kallsyms.h>
10e9564df7SGuo Ren #include <linux/uaccess.h>
11e9564df7SGuo Ren #include <linux/ptrace.h>
12*bdbadfccSAl Viro #include <linux/elfcore.h>
13e9564df7SGuo Ren 
14e9564df7SGuo Ren #include <asm/elf.h>
15e9564df7SGuo Ren #include <abi/reg_ops.h>
16e9564df7SGuo Ren 
17e9564df7SGuo Ren struct cpuinfo_csky cpu_data[NR_CPUS];
18e9564df7SGuo Ren 
192f78c73fSMao Han #ifdef CONFIG_STACKPROTECTOR
202f78c73fSMao Han #include <linux/stackprotector.h>
212f78c73fSMao Han unsigned long __stack_chk_guard __read_mostly;
222f78c73fSMao Han EXPORT_SYMBOL(__stack_chk_guard);
232f78c73fSMao Han #endif
242f78c73fSMao Han 
25e9564df7SGuo Ren asmlinkage void ret_from_fork(void);
26e9564df7SGuo Ren asmlinkage void ret_from_kernel_thread(void);
27e9564df7SGuo Ren 
28e9564df7SGuo Ren /*
29e9564df7SGuo Ren  * Some archs flush debug and FPU info here
30e9564df7SGuo Ren  */
flush_thread(void)31e9564df7SGuo Ren void flush_thread(void){}
32e9564df7SGuo Ren 
copy_thread(struct task_struct * p,const struct kernel_clone_args * args)33c5febea0SEric W. Biederman int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
34e9564df7SGuo Ren {
35c5febea0SEric W. Biederman 	unsigned long clone_flags = args->flags;
36c5febea0SEric W. Biederman 	unsigned long usp = args->stack;
37c5febea0SEric W. Biederman 	unsigned long tls = args->tls;
38e9564df7SGuo Ren 	struct switch_stack *childstack;
39e9564df7SGuo Ren 	struct pt_regs *childregs = task_pt_regs(p);
40e9564df7SGuo Ren 
41e9564df7SGuo Ren #ifdef CONFIG_CPU_HAS_FPU
42e9564df7SGuo Ren 	save_to_user_fp(&p->thread.user_fp);
43e9564df7SGuo Ren #endif
44e9564df7SGuo Ren 
45e9564df7SGuo Ren 	childstack = ((struct switch_stack *) childregs) - 1;
46e9564df7SGuo Ren 	memset(childstack, 0, sizeof(struct switch_stack));
47e9564df7SGuo Ren 
4867002814SGuo Ren 	/* setup thread.sp for switch_to !!! */
4967002814SGuo Ren 	p->thread.sp = (unsigned long)childstack;
50e9564df7SGuo Ren 
515bd2e97cSEric W. Biederman 	if (unlikely(args->fn)) {
52e9564df7SGuo Ren 		memset(childregs, 0, sizeof(struct pt_regs));
53e9564df7SGuo Ren 		childstack->r15 = (unsigned long) ret_from_kernel_thread;
545bd2e97cSEric W. Biederman 		childstack->r10 = (unsigned long) args->fn_arg;
555bd2e97cSEric W. Biederman 		childstack->r9 = (unsigned long) args->fn;
56e9564df7SGuo Ren 		childregs->sr = mfcr("psr");
57e9564df7SGuo Ren 	} else {
58e9564df7SGuo Ren 		*childregs = *(current_pt_regs());
59e9564df7SGuo Ren 		if (usp)
60e9564df7SGuo Ren 			childregs->usp = usp;
61e9564df7SGuo Ren 		if (clone_flags & CLONE_SETTLS)
62e9564df7SGuo Ren 			task_thread_info(p)->tp_value = childregs->tls
630b9f386cSGuo Ren 						      = tls;
64e9564df7SGuo Ren 
65e9564df7SGuo Ren 		childregs->a0 = 0;
66e9564df7SGuo Ren 		childstack->r15 = (unsigned long) ret_from_fork;
67e9564df7SGuo Ren 	}
68e9564df7SGuo Ren 
69e9564df7SGuo Ren 	return 0;
70e9564df7SGuo Ren }
71e9564df7SGuo Ren 
72e9564df7SGuo Ren /* Fill in the fpu structure for a core dump.  */
elf_core_copy_task_fpregs(struct task_struct * t,elf_fpregset_t * fpu)73*bdbadfccSAl Viro int elf_core_copy_task_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
74e9564df7SGuo Ren {
75e9564df7SGuo Ren 	memcpy(fpu, &current->thread.user_fp, sizeof(*fpu));
76e9564df7SGuo Ren 	return 1;
77e9564df7SGuo Ren }
78e9564df7SGuo Ren 
dump_task_regs(struct task_struct * tsk,elf_gregset_t * pr_regs)79e9564df7SGuo Ren int dump_task_regs(struct task_struct *tsk, elf_gregset_t *pr_regs)
80e9564df7SGuo Ren {
81e9564df7SGuo Ren 	struct pt_regs *regs = task_pt_regs(tsk);
82e9564df7SGuo Ren 
83e9564df7SGuo Ren 	/* NOTE: usp is error value. */
84e9564df7SGuo Ren 	ELF_CORE_COPY_REGS((*pr_regs), regs)
85e9564df7SGuo Ren 
86e9564df7SGuo Ren 	return 1;
87e9564df7SGuo Ren }
88e9564df7SGuo Ren 
89e9564df7SGuo Ren #ifndef CONFIG_CPU_PM_NONE
arch_cpu_idle(void)90e9564df7SGuo Ren void arch_cpu_idle(void)
91e9564df7SGuo Ren {
92e9564df7SGuo Ren #ifdef CONFIG_CPU_PM_WAIT
93e9564df7SGuo Ren 	asm volatile("wait\n");
94e9564df7SGuo Ren #endif
95e9564df7SGuo Ren 
96e9564df7SGuo Ren #ifdef CONFIG_CPU_PM_DOZE
97e9564df7SGuo Ren 	asm volatile("doze\n");
98e9564df7SGuo Ren #endif
99e9564df7SGuo Ren 
100e9564df7SGuo Ren #ifdef CONFIG_CPU_PM_STOP
101e9564df7SGuo Ren 	asm volatile("stop\n");
102e9564df7SGuo Ren #endif
103e9564df7SGuo Ren }
104e9564df7SGuo Ren #endif
105