xref: /linux-6.15/arch/nios2/kernel/process.c (revision 89b30987)
171995e4dSLey Foon Tan /*
271995e4dSLey Foon Tan  * Architecture-dependent parts of process handling.
371995e4dSLey Foon Tan  *
471995e4dSLey Foon Tan  * Copyright (C) 2013 Altera Corporation
571995e4dSLey Foon Tan  * Copyright (C) 2010 Tobias Klauser <[email protected]>
671995e4dSLey Foon Tan  * Copyright (C) 2009 Wind River Systems Inc
771995e4dSLey Foon Tan  *   Implemented by [email protected] and [email protected]
871995e4dSLey Foon Tan  * Copyright (C) 2004 Microtronix Datacom Ltd
971995e4dSLey Foon Tan  *
1071995e4dSLey Foon Tan  * This file is subject to the terms and conditions of the GNU General Public
1171995e4dSLey Foon Tan  * License.  See the file "COPYING" in the main directory of this archive
1271995e4dSLey Foon Tan  * for more details.
1371995e4dSLey Foon Tan  */
1471995e4dSLey Foon Tan 
1571995e4dSLey Foon Tan #include <linux/export.h>
1671995e4dSLey Foon Tan #include <linux/sched.h>
17b17b0153SIngo Molnar #include <linux/sched/debug.h>
1829930025SIngo Molnar #include <linux/sched/task.h>
1968db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
20589ee628SIngo Molnar #include <linux/mm_types.h>
2171995e4dSLey Foon Tan #include <linux/tick.h>
2271995e4dSLey Foon Tan #include <linux/uaccess.h>
2371995e4dSLey Foon Tan 
2471995e4dSLey Foon Tan #include <asm/unistd.h>
2571995e4dSLey Foon Tan #include <asm/traps.h>
2671995e4dSLey Foon Tan #include <asm/cpuinfo.h>
2771995e4dSLey Foon Tan 
2871995e4dSLey Foon Tan asmlinkage void ret_from_fork(void);
2971995e4dSLey Foon Tan asmlinkage void ret_from_kernel_thread(void);
3071995e4dSLey Foon Tan 
3171995e4dSLey Foon Tan void (*pm_power_off)(void) = NULL;
3271995e4dSLey Foon Tan EXPORT_SYMBOL(pm_power_off);
3371995e4dSLey Foon Tan 
arch_cpu_idle(void)3471995e4dSLey Foon Tan void arch_cpu_idle(void)
3571995e4dSLey Foon Tan {
3671995e4dSLey Foon Tan }
3771995e4dSLey Foon Tan 
3871995e4dSLey Foon Tan /*
3971995e4dSLey Foon Tan  * The development boards have no way to pull a board reset. Just jump to the
4071995e4dSLey Foon Tan  * cpu reset address and let the boot loader or the code in head.S take care of
4171995e4dSLey Foon Tan  * resetting peripherals.
4271995e4dSLey Foon Tan  */
machine_restart(char * __unused)4371995e4dSLey Foon Tan void machine_restart(char *__unused)
4471995e4dSLey Foon Tan {
4571995e4dSLey Foon Tan 	pr_notice("Machine restart (%08x)...\n", cpuinfo.reset_addr);
4671995e4dSLey Foon Tan 	local_irq_disable();
4771995e4dSLey Foon Tan 	__asm__ __volatile__ (
4871995e4dSLey Foon Tan 	"jmp	%0\n\t"
4971995e4dSLey Foon Tan 	:
5071995e4dSLey Foon Tan 	: "r" (cpuinfo.reset_addr)
5171995e4dSLey Foon Tan 	: "r4");
5271995e4dSLey Foon Tan }
5371995e4dSLey Foon Tan 
machine_halt(void)5471995e4dSLey Foon Tan void machine_halt(void)
5571995e4dSLey Foon Tan {
5671995e4dSLey Foon Tan 	pr_notice("Machine halt...\n");
5771995e4dSLey Foon Tan 	local_irq_disable();
5871995e4dSLey Foon Tan 	for (;;)
5971995e4dSLey Foon Tan 		;
6071995e4dSLey Foon Tan }
6171995e4dSLey Foon Tan 
6271995e4dSLey Foon Tan /*
6371995e4dSLey Foon Tan  * There is no way to power off the development boards. So just spin for now. If
6471995e4dSLey Foon Tan  * we ever have a way of resetting a board using a GPIO we should add that here.
6571995e4dSLey Foon Tan  */
machine_power_off(void)6671995e4dSLey Foon Tan void machine_power_off(void)
6771995e4dSLey Foon Tan {
6871995e4dSLey Foon Tan 	pr_notice("Machine power off...\n");
6971995e4dSLey Foon Tan 	local_irq_disable();
7071995e4dSLey Foon Tan 	for (;;)
7171995e4dSLey Foon Tan 		;
7271995e4dSLey Foon Tan }
7371995e4dSLey Foon Tan 
show_regs(struct pt_regs * regs)7471995e4dSLey Foon Tan void show_regs(struct pt_regs *regs)
7571995e4dSLey Foon Tan {
7671995e4dSLey Foon Tan 	pr_notice("\n");
7771995e4dSLey Foon Tan 	show_regs_print_info(KERN_DEFAULT);
7871995e4dSLey Foon Tan 
7971995e4dSLey Foon Tan 	pr_notice("r1: %08lx r2: %08lx r3: %08lx r4: %08lx\n",
8071995e4dSLey Foon Tan 		regs->r1,  regs->r2,  regs->r3,  regs->r4);
8171995e4dSLey Foon Tan 
8271995e4dSLey Foon Tan 	pr_notice("r5: %08lx r6: %08lx r7: %08lx r8: %08lx\n",
8371995e4dSLey Foon Tan 		regs->r5,  regs->r6,  regs->r7,  regs->r8);
8471995e4dSLey Foon Tan 
8571995e4dSLey Foon Tan 	pr_notice("r9: %08lx r10: %08lx r11: %08lx r12: %08lx\n",
8671995e4dSLey Foon Tan 		regs->r9,  regs->r10, regs->r11, regs->r12);
8771995e4dSLey Foon Tan 
8871995e4dSLey Foon Tan 	pr_notice("r13: %08lx r14: %08lx r15: %08lx\n",
8971995e4dSLey Foon Tan 		regs->r13, regs->r14, regs->r15);
9071995e4dSLey Foon Tan 
9171995e4dSLey Foon Tan 	pr_notice("ra: %08lx fp:  %08lx sp: %08lx gp: %08lx\n",
9271995e4dSLey Foon Tan 		regs->ra,  regs->fp,  regs->sp,  regs->gp);
9371995e4dSLey Foon Tan 
9471995e4dSLey Foon Tan 	pr_notice("ea: %08lx estatus: %08lx\n",
9571995e4dSLey Foon Tan 		regs->ea,  regs->estatus);
9671995e4dSLey Foon Tan }
9771995e4dSLey Foon Tan 
flush_thread(void)9871995e4dSLey Foon Tan void flush_thread(void)
9971995e4dSLey Foon Tan {
10071995e4dSLey Foon Tan }
10171995e4dSLey Foon Tan 
copy_thread(struct task_struct * p,const struct kernel_clone_args * args)102c5febea0SEric W. Biederman int copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
10371995e4dSLey Foon Tan {
104c5febea0SEric W. Biederman 	unsigned long clone_flags = args->flags;
105c5febea0SEric W. Biederman 	unsigned long usp = args->stack;
106c5febea0SEric W. Biederman 	unsigned long tls = args->tls;
10771995e4dSLey Foon Tan 	struct pt_regs *childregs = task_pt_regs(p);
10871995e4dSLey Foon Tan 	struct pt_regs *regs;
10971995e4dSLey Foon Tan 	struct switch_stack *stack;
11071995e4dSLey Foon Tan 	struct switch_stack *childstack =
11171995e4dSLey Foon Tan 		((struct switch_stack *)childregs) - 1;
11271995e4dSLey Foon Tan 
113*5bd2e97cSEric W. Biederman 	if (unlikely(args->fn)) {
11471995e4dSLey Foon Tan 		memset(childstack, 0,
11571995e4dSLey Foon Tan 			sizeof(struct switch_stack) + sizeof(struct pt_regs));
11671995e4dSLey Foon Tan 
117*5bd2e97cSEric W. Biederman 		childstack->r16 = (unsigned long) args->fn;
118*5bd2e97cSEric W. Biederman 		childstack->r17 = (unsigned long) args->fn_arg;
11971995e4dSLey Foon Tan 		childstack->ra = (unsigned long) ret_from_kernel_thread;
12071995e4dSLey Foon Tan 		childregs->estatus = STATUS_PIE;
12171995e4dSLey Foon Tan 		childregs->sp = (unsigned long) childstack;
12271995e4dSLey Foon Tan 
12371995e4dSLey Foon Tan 		p->thread.ksp = (unsigned long) childstack;
12471995e4dSLey Foon Tan 		p->thread.kregs = childregs;
12571995e4dSLey Foon Tan 		return 0;
12671995e4dSLey Foon Tan 	}
12771995e4dSLey Foon Tan 
12871995e4dSLey Foon Tan 	regs = current_pt_regs();
12971995e4dSLey Foon Tan 	*childregs = *regs;
13071995e4dSLey Foon Tan 	childregs->r2 = 0;	/* Set the return value for the child. */
13171995e4dSLey Foon Tan 	childregs->r7 = 0;
13271995e4dSLey Foon Tan 
13371995e4dSLey Foon Tan 	stack = ((struct switch_stack *) regs) - 1;
13471995e4dSLey Foon Tan 	*childstack = *stack;
13571995e4dSLey Foon Tan 	childstack->ra = (unsigned long)ret_from_fork;
13671995e4dSLey Foon Tan 	p->thread.kregs = childregs;
13771995e4dSLey Foon Tan 	p->thread.ksp = (unsigned long) childstack;
13871995e4dSLey Foon Tan 
13971995e4dSLey Foon Tan 	if (usp)
14071995e4dSLey Foon Tan 		childregs->sp = usp;
14171995e4dSLey Foon Tan 
14271995e4dSLey Foon Tan 	/* Initialize tls register. */
14371995e4dSLey Foon Tan 	if (clone_flags & CLONE_SETTLS)
14404bd52fbSChristian Brauner 		childstack->r23 = tls;
14571995e4dSLey Foon Tan 
14671995e4dSLey Foon Tan 	return 0;
14771995e4dSLey Foon Tan }
14871995e4dSLey Foon Tan 
14971995e4dSLey Foon Tan /*
15071995e4dSLey Foon Tan  *	Generic dumping code. Used for panic and debug.
15171995e4dSLey Foon Tan  */
dump(struct pt_regs * fp)15271995e4dSLey Foon Tan void dump(struct pt_regs *fp)
15371995e4dSLey Foon Tan {
15471995e4dSLey Foon Tan 	unsigned long	*sp;
15571995e4dSLey Foon Tan 	unsigned char	*tp;
15671995e4dSLey Foon Tan 	int		i;
15771995e4dSLey Foon Tan 
15871995e4dSLey Foon Tan 	pr_emerg("\nCURRENT PROCESS:\n\n");
15971995e4dSLey Foon Tan 	pr_emerg("COMM=%s PID=%d\n", current->comm, current->pid);
16071995e4dSLey Foon Tan 
16171995e4dSLey Foon Tan 	if (current->mm) {
16271995e4dSLey Foon Tan 		pr_emerg("TEXT=%08x-%08x DATA=%08x-%08x BSS=%08x-%08x\n",
16371995e4dSLey Foon Tan 			(int) current->mm->start_code,
16471995e4dSLey Foon Tan 			(int) current->mm->end_code,
16571995e4dSLey Foon Tan 			(int) current->mm->start_data,
16671995e4dSLey Foon Tan 			(int) current->mm->end_data,
16771995e4dSLey Foon Tan 			(int) current->mm->end_data,
16871995e4dSLey Foon Tan 			(int) current->mm->brk);
16971995e4dSLey Foon Tan 		pr_emerg("USER-STACK=%08x  KERNEL-STACK=%08x\n\n",
17071995e4dSLey Foon Tan 			(int) current->mm->start_stack,
17171995e4dSLey Foon Tan 			(int)(((unsigned long) current) + THREAD_SIZE));
17271995e4dSLey Foon Tan 	}
17371995e4dSLey Foon Tan 
17471995e4dSLey Foon Tan 	pr_emerg("PC: %08lx\n", fp->ea);
17571995e4dSLey Foon Tan 	pr_emerg("SR: %08lx    SP: %08lx\n",
17671995e4dSLey Foon Tan 		(long) fp->estatus, (long) fp);
17771995e4dSLey Foon Tan 
17871995e4dSLey Foon Tan 	pr_emerg("r1: %08lx    r2: %08lx    r3: %08lx\n",
17971995e4dSLey Foon Tan 		fp->r1, fp->r2, fp->r3);
18071995e4dSLey Foon Tan 
18171995e4dSLey Foon Tan 	pr_emerg("r4: %08lx    r5: %08lx    r6: %08lx    r7: %08lx\n",
18271995e4dSLey Foon Tan 		fp->r4, fp->r5, fp->r6, fp->r7);
18371995e4dSLey Foon Tan 	pr_emerg("r8: %08lx    r9: %08lx    r10: %08lx    r11: %08lx\n",
18471995e4dSLey Foon Tan 		fp->r8, fp->r9, fp->r10, fp->r11);
18571995e4dSLey Foon Tan 	pr_emerg("r12: %08lx  r13: %08lx    r14: %08lx    r15: %08lx\n",
18671995e4dSLey Foon Tan 		fp->r12, fp->r13, fp->r14, fp->r15);
18771995e4dSLey Foon Tan 	pr_emerg("or2: %08lx   ra: %08lx     fp: %08lx    sp: %08lx\n",
18871995e4dSLey Foon Tan 		fp->orig_r2, fp->ra, fp->fp, fp->sp);
18971995e4dSLey Foon Tan 	pr_emerg("\nUSP: %08x   TRAPFRAME: %08x\n",
19071995e4dSLey Foon Tan 		(unsigned int) fp->sp, (unsigned int) fp);
19171995e4dSLey Foon Tan 
19271995e4dSLey Foon Tan 	pr_emerg("\nCODE:");
19371995e4dSLey Foon Tan 	tp = ((unsigned char *) fp->ea) - 0x20;
19471995e4dSLey Foon Tan 	for (sp = (unsigned long *) tp, i = 0; (i < 0x40);  i += 4) {
19571995e4dSLey Foon Tan 		if ((i % 0x10) == 0)
19671995e4dSLey Foon Tan 			pr_emerg("\n%08x: ", (int) (tp + i));
19771995e4dSLey Foon Tan 		pr_emerg("%08x ", (int) *sp++);
19871995e4dSLey Foon Tan 	}
19971995e4dSLey Foon Tan 	pr_emerg("\n");
20071995e4dSLey Foon Tan 
20171995e4dSLey Foon Tan 	pr_emerg("\nKERNEL STACK:");
20271995e4dSLey Foon Tan 	tp = ((unsigned char *) fp) - 0x40;
20371995e4dSLey Foon Tan 	for (sp = (unsigned long *) tp, i = 0; (i < 0xc0); i += 4) {
20471995e4dSLey Foon Tan 		if ((i % 0x10) == 0)
20571995e4dSLey Foon Tan 			pr_emerg("\n%08x: ", (int) (tp + i));
20671995e4dSLey Foon Tan 		pr_emerg("%08x ", (int) *sp++);
20771995e4dSLey Foon Tan 	}
20871995e4dSLey Foon Tan 	pr_emerg("\n");
20971995e4dSLey Foon Tan 	pr_emerg("\n");
21071995e4dSLey Foon Tan 
21171995e4dSLey Foon Tan 	pr_emerg("\nUSER STACK:");
21271995e4dSLey Foon Tan 	tp = (unsigned char *) (fp->sp - 0x10);
21371995e4dSLey Foon Tan 	for (sp = (unsigned long *) tp, i = 0; (i < 0x80); i += 4) {
21471995e4dSLey Foon Tan 		if ((i % 0x10) == 0)
21571995e4dSLey Foon Tan 			pr_emerg("\n%08x: ", (int) (tp + i));
21671995e4dSLey Foon Tan 		pr_emerg("%08x ", (int) *sp++);
21771995e4dSLey Foon Tan 	}
21871995e4dSLey Foon Tan 	pr_emerg("\n\n");
21971995e4dSLey Foon Tan }
22071995e4dSLey Foon Tan 
__get_wchan(struct task_struct * p)22142a20f86SKees Cook unsigned long __get_wchan(struct task_struct *p)
22271995e4dSLey Foon Tan {
22371995e4dSLey Foon Tan 	unsigned long fp, pc;
22471995e4dSLey Foon Tan 	unsigned long stack_page;
22571995e4dSLey Foon Tan 	int count = 0;
22671995e4dSLey Foon Tan 
22771995e4dSLey Foon Tan 	stack_page = (unsigned long)p;
22871995e4dSLey Foon Tan 	fp = ((struct switch_stack *)p->thread.ksp)->fp;	/* ;dgt2 */
22971995e4dSLey Foon Tan 	do {
23071995e4dSLey Foon Tan 		if (fp < stack_page+sizeof(struct task_struct) ||
23171995e4dSLey Foon Tan 			fp >= 8184+stack_page)	/* ;dgt2;tmp */
23271995e4dSLey Foon Tan 			return 0;
23371995e4dSLey Foon Tan 		pc = ((unsigned long *)fp)[1];
23471995e4dSLey Foon Tan 		if (!in_sched_functions(pc))
23571995e4dSLey Foon Tan 			return pc;
23671995e4dSLey Foon Tan 		fp = *(unsigned long *) fp;
23771995e4dSLey Foon Tan 	} while (count++ < 16);		/* ;dgt2;tmp */
23871995e4dSLey Foon Tan 	return 0;
23971995e4dSLey Foon Tan }
24071995e4dSLey Foon Tan 
24171995e4dSLey Foon Tan /*
24271995e4dSLey Foon Tan  * Do necessary setup to start up a newly executed thread.
24371995e4dSLey Foon Tan  * Will startup in user mode (status_extension = 0).
24471995e4dSLey Foon Tan  */
start_thread(struct pt_regs * regs,unsigned long pc,unsigned long sp)24571995e4dSLey Foon Tan void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp)
24671995e4dSLey Foon Tan {
24771995e4dSLey Foon Tan 	memset((void *) regs, 0, sizeof(struct pt_regs));
24871995e4dSLey Foon Tan 	regs->estatus = ESTATUS_EPIE | ESTATUS_EU;
24971995e4dSLey Foon Tan 	regs->ea = pc;
25071995e4dSLey Foon Tan 	regs->sp = sp;
25171995e4dSLey Foon Tan }
25271995e4dSLey Foon Tan 
nios2_clone(unsigned long clone_flags,unsigned long newsp,int __user * parent_tidptr,int __user * child_tidptr,unsigned long tls)25304bd52fbSChristian Brauner asmlinkage int nios2_clone(unsigned long clone_flags, unsigned long newsp,
25404bd52fbSChristian Brauner 			   int __user *parent_tidptr, int __user *child_tidptr,
25504bd52fbSChristian Brauner 			   unsigned long tls)
25604bd52fbSChristian Brauner {
25704bd52fbSChristian Brauner 	struct kernel_clone_args args = {
25804bd52fbSChristian Brauner 		.flags		= (lower_32_bits(clone_flags) & ~CSIGNAL),
25904bd52fbSChristian Brauner 		.pidfd		= parent_tidptr,
26004bd52fbSChristian Brauner 		.child_tid	= child_tidptr,
26104bd52fbSChristian Brauner 		.parent_tid	= parent_tidptr,
26204bd52fbSChristian Brauner 		.exit_signal	= (lower_32_bits(clone_flags) & CSIGNAL),
26304bd52fbSChristian Brauner 		.stack		= newsp,
26404bd52fbSChristian Brauner 		.tls		= tls,
26504bd52fbSChristian Brauner 	};
26604bd52fbSChristian Brauner 
267e7a2ec95SChristian Brauner 	return kernel_clone(&args);
26804bd52fbSChristian Brauner }
269