11a59d1b8SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
21da177e4SLinus Torvalds /*
31da177e4SLinus Torvalds * PARISC Architecture-dependent parts of process handling
41da177e4SLinus Torvalds * based on the work for i386
51da177e4SLinus Torvalds *
61da177e4SLinus Torvalds * Copyright (C) 1999-2003 Matthew Wilcox <willy at parisc-linux.org>
71da177e4SLinus Torvalds * Copyright (C) 2000 Martin K Petersen <mkp at mkp.net>
81da177e4SLinus Torvalds * Copyright (C) 2000 John Marvin <jsm at parisc-linux.org>
91da177e4SLinus Torvalds * Copyright (C) 2000 David Huggins-Daines <dhd with pobox.org>
101da177e4SLinus Torvalds * Copyright (C) 2000-2003 Paul Bame <bame at parisc-linux.org>
111da177e4SLinus Torvalds * Copyright (C) 2000 Philipp Rumpf <prumpf with tux.org>
121da177e4SLinus Torvalds * Copyright (C) 2000 David Kennedy <dkennedy with linuxcare.com>
13b2450cc1SCarlos O'Donell * Copyright (C) 2000 Richard Hirst <rhirst with parisc-linux.org>
141da177e4SLinus Torvalds * Copyright (C) 2000 Grant Grundler <grundler with parisc-linux.org>
151da177e4SLinus Torvalds * Copyright (C) 2001 Alan Modra <amodra at parisc-linux.org>
161da177e4SLinus Torvalds * Copyright (C) 2001-2002 Ryan Bradetich <rbrad at parisc-linux.org>
179dabf60dSHelge Deller * Copyright (C) 2001-2014 Helge Deller <deller@gmx.de>
181da177e4SLinus Torvalds * Copyright (C) 2002 Randolph Chung <tausq with parisc-linux.org>
191da177e4SLinus Torvalds */
201da177e4SLinus Torvalds #include <linux/elf.h>
211da177e4SLinus Torvalds #include <linux/errno.h>
221da177e4SLinus Torvalds #include <linux/kernel.h>
231da177e4SLinus Torvalds #include <linux/mm.h>
244e950f6fSAlexey Dobriyan #include <linux/fs.h>
25310d8278SHelge Deller #include <linux/cpu.h>
261da177e4SLinus Torvalds #include <linux/module.h>
271da177e4SLinus Torvalds #include <linux/personality.h>
281da177e4SLinus Torvalds #include <linux/ptrace.h>
29f4622fe4SDmitry Osipenko #include <linux/reboot.h>
301da177e4SLinus Torvalds #include <linux/sched.h>
31b17b0153SIngo Molnar #include <linux/sched/debug.h>
3229930025SIngo Molnar #include <linux/sched/task.h>
3368db0cf1SIngo Molnar #include <linux/sched/task_stack.h>
345a0e3ad6STejun Heo #include <linux/slab.h>
351da177e4SLinus Torvalds #include <linux/stddef.h>
361da177e4SLinus Torvalds #include <linux/unistd.h>
371da177e4SLinus Torvalds #include <linux/kallsyms.h>
38b609308eSKyle McMartin #include <linux/uaccess.h>
39fbe75218SFrederic Weisbecker #include <linux/rcupdate.h>
409dabf60dSHelge Deller #include <linux/random.h>
4156188832SHelge Deller #include <linux/nmi.h>
4298903688SHelge Deller #include <linux/sched/hotplug.h>
431da177e4SLinus Torvalds
441da177e4SLinus Torvalds #include <asm/io.h>
450013a854SSam Ravnborg #include <asm/asm-offsets.h>
46ff0ab8afSAl Viro #include <asm/assembly.h>
471da177e4SLinus Torvalds #include <asm/pdc.h>
481da177e4SLinus Torvalds #include <asm/pdc_chassis.h>
491da177e4SLinus Torvalds #include <asm/unwind.h>
50b609308eSKyle McMartin #include <asm/sections.h>
5198903688SHelge Deller #include <asm/cacheflush.h>
521da177e4SLinus Torvalds
5310992092SKyle McMartin #define COMMAND_GLOBAL F_EXTEND(0xfffe0030)
541da177e4SLinus Torvalds #define CMD_RESET 5 /* reset any module */
551da177e4SLinus Torvalds
561da177e4SLinus Torvalds /*
571da177e4SLinus Torvalds ** The Wright Brothers and Gecko systems have a H/W problem
581da177e4SLinus Torvalds ** (Lasi...'nuf said) may cause a broadcast reset to lockup
591da177e4SLinus Torvalds ** the system. An HVERSION dependent PDC call was developed
601da177e4SLinus Torvalds ** to perform a "safe", platform specific broadcast reset instead
611da177e4SLinus Torvalds ** of kludging up all the code.
621da177e4SLinus Torvalds **
631da177e4SLinus Torvalds ** Older machines which do not implement PDC_BROADCAST_RESET will
641da177e4SLinus Torvalds ** return (with an error) and the regular broadcast reset can be
651da177e4SLinus Torvalds ** issued. Obviously, if the PDC does implement PDC_BROADCAST_RESET
661da177e4SLinus Torvalds ** the PDC call will not return (the system will be reset).
671da177e4SLinus Torvalds */
machine_restart(char * cmd)681da177e4SLinus Torvalds void machine_restart(char *cmd)
691da177e4SLinus Torvalds {
701da177e4SLinus Torvalds #ifdef FASTBOOT_SELFTEST_SUPPORT
711da177e4SLinus Torvalds /*
721da177e4SLinus Torvalds ** If user has modified the Firmware Selftest Bitmap,
731da177e4SLinus Torvalds ** run the tests specified in the bitmap after the
741da177e4SLinus Torvalds ** system is rebooted w/PDC_DO_RESET.
751da177e4SLinus Torvalds **
761da177e4SLinus Torvalds ** ftc_bitmap = 0x1AUL "Skip destructive memory tests"
771da177e4SLinus Torvalds **
781da177e4SLinus Torvalds ** Using "directed resets" at each processor with the MEM_TOC
791da177e4SLinus Torvalds ** vector cleared will also avoid running destructive
801da177e4SLinus Torvalds ** memory self tests. (Not implemented yet)
811da177e4SLinus Torvalds */
821da177e4SLinus Torvalds if (ftc_bitmap) {
831da177e4SLinus Torvalds pdc_do_firm_test_reset(ftc_bitmap);
841da177e4SLinus Torvalds }
851da177e4SLinus Torvalds #endif
861da177e4SLinus Torvalds /* set up a new led state on systems shipped with a LED State panel */
871da177e4SLinus Torvalds pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
881da177e4SLinus Torvalds
891da177e4SLinus Torvalds /* "Normal" system reset */
901da177e4SLinus Torvalds pdc_do_reset();
911da177e4SLinus Torvalds
921da177e4SLinus Torvalds /* Nope...box should reset with just CMD_RESET now */
931da177e4SLinus Torvalds gsc_writel(CMD_RESET, COMMAND_GLOBAL);
941da177e4SLinus Torvalds
951da177e4SLinus Torvalds /* Wait for RESET to lay us to rest. */
961da177e4SLinus Torvalds while (1) ;
971da177e4SLinus Torvalds
981da177e4SLinus Torvalds }
991da177e4SLinus Torvalds
10085509c00SKyle McMartin /*
1011da177e4SLinus Torvalds * This routine is called from sys_reboot to actually turn off the
1021da177e4SLinus Torvalds * machine
1031da177e4SLinus Torvalds */
machine_power_off(void)1041da177e4SLinus Torvalds void machine_power_off(void)
1051da177e4SLinus Torvalds {
1061da177e4SLinus Torvalds /* Put the soft power button back under hardware control.
1071da177e4SLinus Torvalds * If the user had already pressed the power button, the
1081da177e4SLinus Torvalds * following call will immediately power off. */
10985509c00SKyle McMartin pdc_soft_power_button(0);
11085509c00SKyle McMartin
1111da177e4SLinus Torvalds pdc_chassis_send_status(PDC_CHASSIS_DIRECT_SHUTDOWN);
1121da177e4SLinus Torvalds
1131da177e4SLinus Torvalds /* ipmi_poweroff may have been installed. */
1141da177e4SLinus Torvalds do_kernel_power_off();
1151da177e4SLinus Torvalds
1161da177e4SLinus Torvalds /* It seems we have no way to power the system off via
1171da177e4SLinus Torvalds * software. The user has to press the button himself. */
1181da177e4SLinus Torvalds
11924002d59SHelge Deller printk("Power off or press RETURN to reboot.\n");
120f4622fe4SDmitry Osipenko
12124002d59SHelge Deller /* prevent soft lockup/stalled CPU messages for endless loop. */
1221da177e4SLinus Torvalds rcu_sysrq_start();
1231da177e4SLinus Torvalds lockup_detector_soft_poweroff();
1241da177e4SLinus Torvalds while (1) {
1251da177e4SLinus Torvalds /* reboot if user presses RETURN key */
126ad361c98SJoe Perches if (pdc_iodc_getc() == 13) {
12773580dacSHelge Deller printk("Rebooting...\n");
128476e75a4SHelge Deller machine_restart(NULL);
129476e75a4SHelge Deller }
13047bb4bafSThomas Gleixner }
13173580dacSHelge Deller }
1321da177e4SLinus Torvalds
1331da177e4SLinus Torvalds void (*pm_power_off)(void);
13424002d59SHelge Deller EXPORT_SYMBOL(pm_power_off);
13585509c00SKyle McMartin
machine_halt(void)1361da177e4SLinus Torvalds void machine_halt(void)
13767698287SHelge Deller {
13867698287SHelge Deller machine_power_off();
13967698287SHelge Deller }
14067698287SHelge Deller
flush_thread(void)14167698287SHelge Deller void flush_thread(void)
1421da177e4SLinus Torvalds {
1431da177e4SLinus Torvalds /* Only needs to handle fpu stuff or perf monitors.
1441da177e4SLinus Torvalds ** REVISIT: several arches implement a "lazy fpu state".
1451da177e4SLinus Torvalds */
1461da177e4SLinus Torvalds }
1471da177e4SLinus Torvalds
1481da177e4SLinus Torvalds /*
1491da177e4SLinus Torvalds * Idle thread support
150310d8278SHelge Deller *
151310d8278SHelge Deller * Detect when running on QEMU with SeaBIOS PDC Firmware and let
152310d8278SHelge Deller * QEMU idle the host too.
153310d8278SHelge Deller */
154310d8278SHelge Deller
155310d8278SHelge Deller int running_on_qemu __ro_after_init;
1567e4c65bfSHelge Deller EXPORT_SYMBOL(running_on_qemu);
1573e1120f4SHelge Deller
158310d8278SHelge Deller /*
15998903688SHelge Deller * Called from the idle thread for the CPU which has been shutdown.
16098903688SHelge Deller */
arch_cpu_idle_dead(void)16198903688SHelge Deller void __noreturn arch_cpu_idle_dead(void)
16298903688SHelge Deller {
163310d8278SHelge Deller #ifdef CONFIG_HOTPLUG_CPU
16498903688SHelge Deller idle_task_exit();
16598903688SHelge Deller
16698903688SHelge Deller local_irq_disable();
16798903688SHelge Deller
16898903688SHelge Deller /* Tell the core that this CPU is now safe to dispose of. */
16998903688SHelge Deller cpuhp_ap_report_dead();
17098903688SHelge Deller
17198903688SHelge Deller /* Ensure that the cache lines are written out. */
17298903688SHelge Deller flush_cache_all_local();
17398903688SHelge Deller flush_tlb_all_local(NULL);
17498903688SHelge Deller
17598903688SHelge Deller /* Let PDC firmware put CPU into firmware idle loop. */
17698903688SHelge Deller __pdc_cpu_rendezvous();
17798903688SHelge Deller
17898903688SHelge Deller pr_warn("PDC does not provide rendezvous function.\n");
17998903688SHelge Deller #endif
18098903688SHelge Deller while (1);
18198903688SHelge Deller }
182310d8278SHelge Deller
arch_cpu_idle(void)183310d8278SHelge Deller void __cpuidle arch_cpu_idle(void)
184310d8278SHelge Deller {
185310d8278SHelge Deller /* nop on real hardware, qemu will idle sleep. */
18658c644baSPeter Zijlstra asm volatile("or %%r10,%%r10,%%r10\n":::);
187310d8278SHelge Deller }
188310d8278SHelge Deller
parisc_idle_init(void)189310d8278SHelge Deller static int __init parisc_idle_init(void)
190310d8278SHelge Deller {
191310d8278SHelge Deller if (!running_on_qemu)
192310d8278SHelge Deller cpu_idle_poll_ctrl(1);
193310d8278SHelge Deller
194310d8278SHelge Deller return 0;
195310d8278SHelge Deller }
196310d8278SHelge Deller arch_initcall(parisc_idle_init);
197310d8278SHelge Deller
198310d8278SHelge Deller /*
199310d8278SHelge Deller * Copy architecture-specific thread state
200310d8278SHelge Deller */
201310d8278SHelge Deller int
copy_thread(struct task_struct * p,const struct kernel_clone_args * args)2025fec97d0SAlex Dowad copy_thread(struct task_struct *p, const struct kernel_clone_args *args)
2035fec97d0SAlex Dowad {
2041da177e4SLinus Torvalds unsigned long clone_flags = args->flags;
205c5febea0SEric W. Biederman unsigned long usp = args->stack;
2061da177e4SLinus Torvalds unsigned long tls = args->tls;
207c5febea0SEric W. Biederman struct pt_regs *cregs = &(p->thread.regs);
208c5febea0SEric W. Biederman void *stack = task_stack_page(p);
209c5febea0SEric W. Biederman
2101da177e4SLinus Torvalds /* We have to use void * instead of a function pointer, because
21140f1f0deSAl Viro * function pointers aren't a pointer to the function on 64-bit.
2121da177e4SLinus Torvalds * Make them const so the compiler knows they live in .text */
2131da177e4SLinus Torvalds extern void * const ret_from_kernel_thread;
2141da177e4SLinus Torvalds extern void * const child_return;
2151da177e4SLinus Torvalds
2161da177e4SLinus Torvalds if (unlikely(args->fn)) {
2171da177e4SLinus Torvalds /* kernel thread */
218c78c2b7eSHelge Deller memset(cregs, 0, sizeof(struct pt_regs));
2195bd2e97cSEric W. Biederman if (args->idle) /* idle thread */
2205fec97d0SAlex Dowad return 0;
221a44e060fSAl Viro /* Must exit via ret_from_kernel_thread in order
22236cb0e1cSEric W. Biederman * to call schedule_tail()
223ff0ab8afSAl Viro */
2241da177e4SLinus Torvalds cregs->ksp = (unsigned long) stack + FRAME_SIZE + PT_SZ_ALGN;
2251da177e4SLinus Torvalds cregs->kpc = (unsigned long) &ret_from_kernel_thread;
2261da177e4SLinus Torvalds /*
2272214c0e7SHelge Deller * Copy function and argument to be called from
2281da177e4SLinus Torvalds * ret_from_kernel_thread.
2291da177e4SLinus Torvalds */
2301da177e4SLinus Torvalds #ifdef CONFIG_64BIT
2311da177e4SLinus Torvalds cregs->gr[27] = ((unsigned long *)args->fn)[3];
2321da177e4SLinus Torvalds cregs->gr[26] = ((unsigned long *)args->fn)[2];
233a8f44e38SHelge Deller #else
2345bd2e97cSEric W. Biederman cregs->gr[26] = (unsigned long) args->fn;
2355bd2e97cSEric W. Biederman #endif
236a44e060fSAl Viro cregs->gr[25] = (unsigned long) args->fn_arg;
2375bd2e97cSEric W. Biederman } else {
2381da177e4SLinus Torvalds /* user thread */
2395bd2e97cSEric W. Biederman /* usp must be word aligned. This also prevents users from
2401da177e4SLinus Torvalds * passing in the value 1 (which is the signal for a special
2411da177e4SLinus Torvalds * return for a kernel thread) */
242415bfae9SAl Viro if (usp) {
243415bfae9SAl Viro usp = ALIGN(usp, 4);
244415bfae9SAl Viro if (likely(usp))
245415bfae9SAl Viro cregs->gr[30] = usp;
246415bfae9SAl Viro }
247415bfae9SAl Viro cregs->ksp = (unsigned long) stack + FRAME_SIZE;
2481da177e4SLinus Torvalds cregs->kpc = (unsigned long) &child_return;
249415bfae9SAl Viro
2502214c0e7SHelge Deller /* Setup thread TLS area */
2511da177e4SLinus Torvalds if (clone_flags & CLONE_SETTLS)
252c78c2b7eSHelge Deller cregs->cr27 = tls;
253d2f36c78SAmanieu d'Antras }
254b2450cc1SCarlos O'Donell
255d2f36c78SAmanieu d'Antras return 0;
2561da177e4SLinus Torvalds }
2571da177e4SLinus Torvalds
2581da177e4SLinus Torvalds unsigned long
__get_wchan(struct task_struct * p)2591da177e4SLinus Torvalds __get_wchan(struct task_struct *p)
2601da177e4SLinus Torvalds {
2611da177e4SLinus Torvalds struct unwind_frame_info info;
26242a20f86SKees Cook unsigned long ip;
2631da177e4SLinus Torvalds int count = 0;
2641da177e4SLinus Torvalds
2651da177e4SLinus Torvalds /*
2661da177e4SLinus Torvalds * These bracket the sleeping functions..
267cc650a7aSKyle McMartin */
2681da177e4SLinus Torvalds
2691da177e4SLinus Torvalds unwind_frame_init_from_blocked_task(&info, p);
2701da177e4SLinus Torvalds do {
2711da177e4SLinus Torvalds if (unwind_once(&info) < 0)
2721da177e4SLinus Torvalds return 0;
2731da177e4SLinus Torvalds if (task_is_running(p))
2741da177e4SLinus Torvalds return 0;
2751da177e4SLinus Torvalds ip = info.ip;
276b03fbd4fSPeter Zijlstra if (!in_sched_functions(ip))
277f2863032SHelge Deller return ip;
2781da177e4SLinus Torvalds } while (count++ < MAX_UNWIND_ENTRIES);
2791da177e4SLinus Torvalds return 0;
2801da177e4SLinus Torvalds }
281c8921d72SHelge Deller