12874c5fdSThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later 288ef7f3fSJonas Bonn /* 388ef7f3fSJonas Bonn * OpenRISC process.c 488ef7f3fSJonas Bonn * 588ef7f3fSJonas Bonn * Linux architectural port borrowing liberally from similar works of 688ef7f3fSJonas Bonn * others. All original copyrights apply as per the original source 788ef7f3fSJonas Bonn * declaration. 888ef7f3fSJonas Bonn * 988ef7f3fSJonas Bonn * Modifications for the OpenRISC architecture: 1088ef7f3fSJonas Bonn * Copyright (C) 2003 Matjaz Breskvar <phoenix@bsemi.com> 1188ef7f3fSJonas Bonn * Copyright (C) 2010-2011 Jonas Bonn <jonas@southpole.se> 1288ef7f3fSJonas Bonn * 1388ef7f3fSJonas Bonn * This file handles the architecture-dependent parts of process handling... 1488ef7f3fSJonas Bonn */ 1588ef7f3fSJonas Bonn 1688ef7f3fSJonas Bonn #define __KERNEL_SYSCALLS__ 1788ef7f3fSJonas Bonn #include <linux/errno.h> 1888ef7f3fSJonas Bonn #include <linux/sched.h> 19b17b0153SIngo Molnar #include <linux/sched/debug.h> 2029930025SIngo Molnar #include <linux/sched/task.h> 2168db0cf1SIngo Molnar #include <linux/sched/task_stack.h> 2288ef7f3fSJonas Bonn #include <linux/kernel.h> 231938852dSStafford Horne #include <linux/export.h> 2488ef7f3fSJonas Bonn #include <linux/mm.h> 2588ef7f3fSJonas Bonn #include <linux/stddef.h> 2688ef7f3fSJonas Bonn #include <linux/unistd.h> 2788ef7f3fSJonas Bonn #include <linux/ptrace.h> 2888ef7f3fSJonas Bonn #include <linux/slab.h> 2988ef7f3fSJonas Bonn #include <linux/elfcore.h> 3088ef7f3fSJonas Bonn #include <linux/interrupt.h> 3188ef7f3fSJonas Bonn #include <linux/delay.h> 3288ef7f3fSJonas Bonn #include <linux/init_task.h> 3388ef7f3fSJonas Bonn #include <linux/mqueue.h> 3488ef7f3fSJonas Bonn #include <linux/fs.h> 35131172a4SJoel Stanley #include <linux/reboot.h> 3688ef7f3fSJonas Bonn 377c0f6ba6SLinus Torvalds #include <linux/uaccess.h> 3888ef7f3fSJonas Bonn #include <asm/io.h> 3988ef7f3fSJonas Bonn #include <asm/processor.h> 4088ef7f3fSJonas Bonn #include <asm/spr_defs.h> 4188ef7f3fSJonas Bonn 4288ef7f3fSJonas Bonn #include <linux/smp.h> 4388ef7f3fSJonas Bonn 4488ef7f3fSJonas Bonn /* 4588ef7f3fSJonas Bonn * Pointer to Current thread info structure. 4688ef7f3fSJonas Bonn * 4788ef7f3fSJonas Bonn * Used at user space -> kernel transitions. 4888ef7f3fSJonas Bonn */ 4988ef7f3fSJonas Bonn struct thread_info *current_thread_info_set[NR_CPUS] = { &init_thread_info, }; 5088ef7f3fSJonas Bonn 51131172a4SJoel Stanley void machine_restart(char *cmd) 5288ef7f3fSJonas Bonn { 53131172a4SJoel Stanley do_kernel_restart(cmd); 54131172a4SJoel Stanley 55635267b7SJason A. Donenfeld __asm__("l.nop 13"); 56635267b7SJason A. Donenfeld 57131172a4SJoel Stanley /* Give a grace period for failure to restart of 1s */ 58131172a4SJoel Stanley mdelay(1000); 59131172a4SJoel Stanley 60131172a4SJoel Stanley /* Whoops - the platform was unable to reboot. Tell the user! */ 61131172a4SJoel Stanley pr_emerg("Reboot failed -- System halted\n"); 62131172a4SJoel Stanley while (1); 6388ef7f3fSJonas Bonn } 6488ef7f3fSJonas Bonn 6588ef7f3fSJonas Bonn /* 6683da38d8SStafford Horne * This is used if pm_power_off has not been set by a power management 6783da38d8SStafford Horne * driver, in this case we can assume we are on a simulator. On 6883da38d8SStafford Horne * OpenRISC simulators l.nop 1 will trigger the simulator exit. 6983da38d8SStafford Horne */ 7083da38d8SStafford Horne static void default_power_off(void) 7183da38d8SStafford Horne { 7283da38d8SStafford Horne __asm__("l.nop 1"); 7383da38d8SStafford Horne } 7483da38d8SStafford Horne 7583da38d8SStafford Horne /* 7688ef7f3fSJonas Bonn * Similar to machine_power_off, but don't shut off power. Add code 7788ef7f3fSJonas Bonn * here to freeze the system for e.g. post-mortem debug purpose when 7888ef7f3fSJonas Bonn * possible. This halt has nothing to do with the idle halt. 7988ef7f3fSJonas Bonn */ 8088ef7f3fSJonas Bonn void machine_halt(void) 8188ef7f3fSJonas Bonn { 8288ef7f3fSJonas Bonn printk(KERN_INFO "*** MACHINE HALT ***\n"); 8388ef7f3fSJonas Bonn __asm__("l.nop 1"); 8488ef7f3fSJonas Bonn } 8588ef7f3fSJonas Bonn 8688ef7f3fSJonas Bonn /* If or when software power-off is implemented, add code here. */ 8788ef7f3fSJonas Bonn void machine_power_off(void) 8888ef7f3fSJonas Bonn { 8988ef7f3fSJonas Bonn printk(KERN_INFO "*** MACHINE POWER OFF ***\n"); 9083da38d8SStafford Horne if (pm_power_off != NULL) 9183da38d8SStafford Horne pm_power_off(); 9283da38d8SStafford Horne else 9383da38d8SStafford Horne default_power_off(); 9488ef7f3fSJonas Bonn } 9588ef7f3fSJonas Bonn 96e29d11c6SSebastian Macke /* 97e29d11c6SSebastian Macke * Send the doze signal to the cpu if available. 98e29d11c6SSebastian Macke * Make sure, that all interrupts are enabled 99e29d11c6SSebastian Macke */ 100e29d11c6SSebastian Macke void arch_cpu_idle(void) 101e29d11c6SSebastian Macke { 10258c644baSPeter Zijlstra raw_local_irq_enable(); 103e29d11c6SSebastian Macke if (mfspr(SPR_UPR) & SPR_UPR_PMP) 104e29d11c6SSebastian Macke mtspr(SPR_PMR, mfspr(SPR_PMR) | SPR_PMR_DME); 105*89b30987SPeter Zijlstra raw_local_irq_disable(); 106e29d11c6SSebastian Macke } 107e29d11c6SSebastian Macke 10883da38d8SStafford Horne void (*pm_power_off)(void) = NULL; 109363dad58SStafford Horne EXPORT_SYMBOL(pm_power_off); 11088ef7f3fSJonas Bonn 11188ef7f3fSJonas Bonn /* 11288ef7f3fSJonas Bonn * When a process does an "exec", machine state like FPU and debug 11388ef7f3fSJonas Bonn * registers need to be reset. This is a hook function for that. 11488ef7f3fSJonas Bonn * Currently we don't have any such state to reset, so this is empty. 11588ef7f3fSJonas Bonn */ 11688ef7f3fSJonas Bonn void flush_thread(void) 11788ef7f3fSJonas Bonn { 11888ef7f3fSJonas Bonn } 11988ef7f3fSJonas Bonn 12088ef7f3fSJonas Bonn void show_regs(struct pt_regs *regs) 12188ef7f3fSJonas Bonn { 12288ef7f3fSJonas Bonn extern void show_registers(struct pt_regs *regs); 12388ef7f3fSJonas Bonn 124a43cb95dSTejun Heo show_regs_print_info(KERN_DEFAULT); 12588ef7f3fSJonas Bonn /* __PHX__ cleanup this mess */ 12688ef7f3fSJonas Bonn show_registers(regs); 12788ef7f3fSJonas Bonn } 12888ef7f3fSJonas Bonn 12988ef7f3fSJonas Bonn /* 13088ef7f3fSJonas Bonn * Copy the thread-specific (arch specific) info from the current 13188ef7f3fSJonas Bonn * process to the new one p 13288ef7f3fSJonas Bonn */ 13388ef7f3fSJonas Bonn extern asmlinkage void ret_from_fork(void); 13488ef7f3fSJonas Bonn 135cbf23cf1SJonas Bonn /* 136714acdbdSChristian Brauner * copy_thread 137cbf23cf1SJonas Bonn * @clone_flags: flags 138cbf23cf1SJonas Bonn * @usp: user stack pointer or fn for kernel thread 139cbf23cf1SJonas Bonn * @arg: arg to fn for kernel thread; always NULL for userspace thread 140cbf23cf1SJonas Bonn * @p: the newly created task 1410d4e1bb1SStafford Horne * @tls: the Thread Local Storage pointer for the new process 142cbf23cf1SJonas Bonn * 143cbf23cf1SJonas Bonn * At the top of a newly initialized kernel stack are two stacked pt_reg 144cbf23cf1SJonas Bonn * structures. The first (topmost) is the userspace context of the thread. 145cbf23cf1SJonas Bonn * The second is the kernelspace context of the thread. 146cbf23cf1SJonas Bonn * 147cbf23cf1SJonas Bonn * A kernel thread will not be returning to userspace, so the topmost pt_regs 148cbf23cf1SJonas Bonn * struct can be uninitialized; it _does_ need to exist, though, because 149cbf23cf1SJonas Bonn * a kernel thread can become a userspace thread by doing a kernel_execve, in 150cbf23cf1SJonas Bonn * which case the topmost context will be initialized and used for 'returning' 151cbf23cf1SJonas Bonn * to userspace. 152cbf23cf1SJonas Bonn * 153cbf23cf1SJonas Bonn * The second pt_reg struct needs to be initialized to 'return' to 154cbf23cf1SJonas Bonn * ret_from_fork. A kernel thread will need to set r20 to the address of 155cbf23cf1SJonas Bonn * a function to call into (with arg in r22); userspace threads need to set 156cbf23cf1SJonas Bonn * r20 to NULL in which case ret_from_fork will just continue a return to 157cbf23cf1SJonas Bonn * userspace. 158cbf23cf1SJonas Bonn * 159cbf23cf1SJonas Bonn * A kernel thread 'fn' may return; this is effectively what happens when 160cbf23cf1SJonas Bonn * kernel_execve is called. In that case, the userspace pt_regs must have 161cbf23cf1SJonas Bonn * been initialized (which kernel_execve takes care of, see start_thread 162cbf23cf1SJonas Bonn * below); ret_from_fork will then continue its execution causing the 163cbf23cf1SJonas Bonn * 'kernel thread' to return to userspace as a userspace thread. 164cbf23cf1SJonas Bonn */ 165cbf23cf1SJonas Bonn 16688ef7f3fSJonas Bonn int 167c5febea0SEric W. Biederman copy_thread(struct task_struct *p, const struct kernel_clone_args *args) 16888ef7f3fSJonas Bonn { 169c5febea0SEric W. Biederman unsigned long clone_flags = args->flags; 170c5febea0SEric W. Biederman unsigned long usp = args->stack; 171c5febea0SEric W. Biederman unsigned long tls = args->tls; 172cbf23cf1SJonas Bonn struct pt_regs *userregs; 17388ef7f3fSJonas Bonn struct pt_regs *kregs; 17488ef7f3fSJonas Bonn unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 17588ef7f3fSJonas Bonn unsigned long top_of_kernel_stack; 17688ef7f3fSJonas Bonn 17788ef7f3fSJonas Bonn top_of_kernel_stack = sp; 17888ef7f3fSJonas Bonn 179cbf23cf1SJonas Bonn /* Locate userspace context on stack... */ 180cbf23cf1SJonas Bonn sp -= STACK_FRAME_OVERHEAD; /* redzone */ 18188ef7f3fSJonas Bonn sp -= sizeof(struct pt_regs); 182cbf23cf1SJonas Bonn userregs = (struct pt_regs *) sp; 18388ef7f3fSJonas Bonn 184cbf23cf1SJonas Bonn /* ...and kernel context */ 185cbf23cf1SJonas Bonn sp -= STACK_FRAME_OVERHEAD; /* redzone */ 18688ef7f3fSJonas Bonn sp -= sizeof(struct pt_regs); 18788ef7f3fSJonas Bonn kregs = (struct pt_regs *)sp; 18888ef7f3fSJonas Bonn 1895bd2e97cSEric W. Biederman if (unlikely(args->fn)) { 190cbf23cf1SJonas Bonn memset(kregs, 0, sizeof(struct pt_regs)); 1915bd2e97cSEric W. Biederman kregs->gpr[20] = (unsigned long)args->fn; 1925bd2e97cSEric W. Biederman kregs->gpr[22] = (unsigned long)args->fn_arg; 193cbf23cf1SJonas Bonn } else { 19439d91a9eSAl Viro *userregs = *current_pt_regs(); 19588ef7f3fSJonas Bonn 19639d91a9eSAl Viro if (usp) 197cbf23cf1SJonas Bonn userregs->sp = usp; 198e60aa2fbSChristian Svensson 199e60aa2fbSChristian Svensson /* 2000d4e1bb1SStafford Horne * For CLONE_SETTLS set "tp" (r10) to the TLS pointer. 201e60aa2fbSChristian Svensson */ 202e60aa2fbSChristian Svensson if (clone_flags & CLONE_SETTLS) 2030d4e1bb1SStafford Horne userregs->gpr[10] = tls; 204e60aa2fbSChristian Svensson 205cbf23cf1SJonas Bonn userregs->gpr[11] = 0; /* Result from fork() */ 206cbf23cf1SJonas Bonn 207cbf23cf1SJonas Bonn kregs->gpr[20] = 0; /* Userspace thread */ 208cbf23cf1SJonas Bonn } 209cbf23cf1SJonas Bonn 210cbf23cf1SJonas Bonn /* 211cbf23cf1SJonas Bonn * _switch wants the kernel stack page in pt_regs->sp so that it 212cbf23cf1SJonas Bonn * can restore it to thread_info->ksp... see _switch for details. 21388ef7f3fSJonas Bonn */ 21488ef7f3fSJonas Bonn kregs->sp = top_of_kernel_stack; 21588ef7f3fSJonas Bonn kregs->gpr[9] = (unsigned long)ret_from_fork; 21688ef7f3fSJonas Bonn 217cbf23cf1SJonas Bonn task_thread_info(p)->ksp = (unsigned long)kregs; 218cbf23cf1SJonas Bonn 21988ef7f3fSJonas Bonn return 0; 22088ef7f3fSJonas Bonn } 22188ef7f3fSJonas Bonn 22288ef7f3fSJonas Bonn /* 22388ef7f3fSJonas Bonn * Set up a thread for executing a new program 22488ef7f3fSJonas Bonn */ 22588ef7f3fSJonas Bonn void start_thread(struct pt_regs *regs, unsigned long pc, unsigned long sp) 22688ef7f3fSJonas Bonn { 227cbf23cf1SJonas Bonn unsigned long sr = mfspr(SPR_SR) & ~SPR_SR_SM; 22888ef7f3fSJonas Bonn 229cbf23cf1SJonas Bonn memset(regs, 0, sizeof(struct pt_regs)); 23088ef7f3fSJonas Bonn 23188ef7f3fSJonas Bonn regs->pc = pc; 23288ef7f3fSJonas Bonn regs->sr = sr; 23388ef7f3fSJonas Bonn regs->sp = sp; 23488ef7f3fSJonas Bonn } 23588ef7f3fSJonas Bonn 23688ef7f3fSJonas Bonn extern struct thread_info *_switch(struct thread_info *old_ti, 23788ef7f3fSJonas Bonn struct thread_info *new_ti); 23863104c06SStefan Kristiansson extern int lwa_flag; 23988ef7f3fSJonas Bonn 24088ef7f3fSJonas Bonn struct task_struct *__switch_to(struct task_struct *old, 24188ef7f3fSJonas Bonn struct task_struct *new) 24288ef7f3fSJonas Bonn { 24388ef7f3fSJonas Bonn struct task_struct *last; 24488ef7f3fSJonas Bonn struct thread_info *new_ti, *old_ti; 24588ef7f3fSJonas Bonn unsigned long flags; 24688ef7f3fSJonas Bonn 24788ef7f3fSJonas Bonn local_irq_save(flags); 24888ef7f3fSJonas Bonn 24988ef7f3fSJonas Bonn /* current_set is an array of saved current pointers 25088ef7f3fSJonas Bonn * (one for each cpu). we need them at user->kernel transition, 25188ef7f3fSJonas Bonn * while we save them at kernel->user transition 25288ef7f3fSJonas Bonn */ 25388ef7f3fSJonas Bonn new_ti = new->stack; 25488ef7f3fSJonas Bonn old_ti = old->stack; 25588ef7f3fSJonas Bonn 25663104c06SStefan Kristiansson lwa_flag = 0; 25763104c06SStefan Kristiansson 25888ef7f3fSJonas Bonn current_thread_info_set[smp_processor_id()] = new_ti; 25988ef7f3fSJonas Bonn last = (_switch(old_ti, new_ti))->task; 26088ef7f3fSJonas Bonn 26188ef7f3fSJonas Bonn local_irq_restore(flags); 26288ef7f3fSJonas Bonn 26388ef7f3fSJonas Bonn return last; 26488ef7f3fSJonas Bonn } 26588ef7f3fSJonas Bonn 26688ef7f3fSJonas Bonn /* 26788ef7f3fSJonas Bonn * Write out registers in core dump format, as defined by the 26888ef7f3fSJonas Bonn * struct user_regs_struct 26988ef7f3fSJonas Bonn */ 27088ef7f3fSJonas Bonn void dump_elf_thread(elf_greg_t *dest, struct pt_regs* regs) 27188ef7f3fSJonas Bonn { 27288ef7f3fSJonas Bonn dest[0] = 0; /* r0 */ 27388ef7f3fSJonas Bonn memcpy(dest+1, regs->gpr+1, 31*sizeof(unsigned long)); 27488ef7f3fSJonas Bonn dest[32] = regs->pc; 27588ef7f3fSJonas Bonn dest[33] = regs->sr; 27688ef7f3fSJonas Bonn dest[34] = 0; 27788ef7f3fSJonas Bonn dest[35] = 0; 27888ef7f3fSJonas Bonn } 27988ef7f3fSJonas Bonn 28042a20f86SKees Cook unsigned long __get_wchan(struct task_struct *p) 28188ef7f3fSJonas Bonn { 28288ef7f3fSJonas Bonn /* TODO */ 28388ef7f3fSJonas Bonn 28488ef7f3fSJonas Bonn return 0; 28588ef7f3fSJonas Bonn } 286