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, ¤t->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