xref: /openbmc/linux/arch/arm/kernel/reboot.c (revision 4f2c0a4acffbec01079c28f839422e64ddeff004)
1d2912cb1SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-only
2045ab94eSRussell King /*
3045ab94eSRussell King  *  Copyright (C) 1996-2000 Russell King - Converted to ARM.
4045ab94eSRussell King  *  Original Copyright (C) 1995  Linus Torvalds
5045ab94eSRussell King  */
6045ab94eSRussell King #include <linux/cpu.h>
7045ab94eSRussell King #include <linux/delay.h>
8045ab94eSRussell King #include <linux/reboot.h>
9045ab94eSRussell King 
10045ab94eSRussell King #include <asm/cacheflush.h>
11045ab94eSRussell King #include <asm/idmap.h>
129da5ac23SRussell King #include <asm/virt.h>
13*fe520635SBen Dooks #include <asm/system_misc.h>
14045ab94eSRussell King 
15045ab94eSRussell King #include "reboot.h"
16045ab94eSRussell King 
179da5ac23SRussell King typedef void (*phys_reset_t)(unsigned long, bool);
18045ab94eSRussell King 
19045ab94eSRussell King /*
20045ab94eSRussell King  * Function pointers to optional machine specific functions
21045ab94eSRussell King  */
22045ab94eSRussell King void (*pm_power_off)(void);
23045ab94eSRussell King EXPORT_SYMBOL(pm_power_off);
24045ab94eSRussell King 
25045ab94eSRussell King /*
26045ab94eSRussell King  * A temporary stack to use for CPU reset. This is static so that we
27045ab94eSRussell King  * don't clobber it with the identity mapping. When running with this
28045ab94eSRussell King  * stack, any references to the current task *will not work* so you
29045ab94eSRussell King  * should really do as little as possible before jumping to your reset
30045ab94eSRussell King  * code.
31045ab94eSRussell King  */
32045ab94eSRussell King static u64 soft_restart_stack[16];
33045ab94eSRussell King 
__soft_restart(void * addr)34045ab94eSRussell King static void __soft_restart(void *addr)
35045ab94eSRussell King {
36045ab94eSRussell King 	phys_reset_t phys_reset;
37045ab94eSRussell King 
38045ab94eSRussell King 	/* Take out a flat memory mapping. */
39045ab94eSRussell King 	setup_mm_for_reboot();
40045ab94eSRussell King 
41045ab94eSRussell King 	/* Clean and invalidate caches */
42045ab94eSRussell King 	flush_cache_all();
43045ab94eSRussell King 
44045ab94eSRussell King 	/* Turn off caching */
45045ab94eSRussell King 	cpu_proc_fin();
46045ab94eSRussell King 
47045ab94eSRussell King 	/* Push out any further dirty data, and ensure cache is empty */
48045ab94eSRussell King 	flush_cache_all();
49045ab94eSRussell King 
50045ab94eSRussell King 	/* Switch to the identity mapping. */
5128410293SRussell King 	phys_reset = (phys_reset_t)virt_to_idmap(cpu_reset);
529da5ac23SRussell King 
539da5ac23SRussell King 	/* original stub should be restored by kvm */
549da5ac23SRussell King 	phys_reset((unsigned long)addr, is_hyp_mode_available());
55045ab94eSRussell King 
56045ab94eSRussell King 	/* Should never get here. */
57045ab94eSRussell King 	BUG();
58045ab94eSRussell King }
59045ab94eSRussell King 
_soft_restart(unsigned long addr,bool disable_l2)60045ab94eSRussell King void _soft_restart(unsigned long addr, bool disable_l2)
61045ab94eSRussell King {
62045ab94eSRussell King 	u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
63045ab94eSRussell King 
64045ab94eSRussell King 	/* Disable interrupts first */
65045ab94eSRussell King 	raw_local_irq_disable();
66045ab94eSRussell King 	local_fiq_disable();
67045ab94eSRussell King 
68045ab94eSRussell King 	/* Disable the L2 if we're the last man standing. */
69045ab94eSRussell King 	if (disable_l2)
70045ab94eSRussell King 		outer_disable();
71045ab94eSRussell King 
72045ab94eSRussell King 	/* Change to the new stack and continue with the reset. */
73045ab94eSRussell King 	call_with_stack(__soft_restart, (void *)addr, (void *)stack);
74045ab94eSRussell King 
75045ab94eSRussell King 	/* Should never get here. */
76045ab94eSRussell King 	BUG();
77045ab94eSRussell King }
78045ab94eSRussell King 
soft_restart(unsigned long addr)79045ab94eSRussell King void soft_restart(unsigned long addr)
80045ab94eSRussell King {
81045ab94eSRussell King 	_soft_restart(addr, num_online_cpus() == 1);
82045ab94eSRussell King }
83045ab94eSRussell King 
84045ab94eSRussell King /*
85045ab94eSRussell King  * Called by kexec, immediately prior to machine_kexec().
86045ab94eSRussell King  *
87045ab94eSRussell King  * This must completely disable all secondary CPUs; simply causing those CPUs
88045ab94eSRussell King  * to execute e.g. a RAM-based pin loop is not sufficient. This allows the
89045ab94eSRussell King  * kexec'd kernel to use any and all RAM as it sees fit, without having to
90045ab94eSRussell King  * avoid any code or data used by any SW CPU pin loop. The CPU hotplug
91dddf3578SQais Yousef  * functionality embodied in smp_shutdown_nonboot_cpus() to achieve this.
92045ab94eSRussell King  */
machine_shutdown(void)93045ab94eSRussell King void machine_shutdown(void)
94045ab94eSRussell King {
9511ee270eSQais Yousef 	smp_shutdown_nonboot_cpus(reboot_cpu);
96045ab94eSRussell King }
97045ab94eSRussell King 
98045ab94eSRussell King /*
99045ab94eSRussell King  * Halting simply requires that the secondary CPUs stop performing any
100045ab94eSRussell King  * activity (executing tasks, handling interrupts). smp_send_stop()
101045ab94eSRussell King  * achieves this.
102045ab94eSRussell King  */
machine_halt(void)103045ab94eSRussell King void machine_halt(void)
104045ab94eSRussell King {
105045ab94eSRussell King 	local_irq_disable();
106045ab94eSRussell King 	smp_send_stop();
107045ab94eSRussell King 	while (1);
108045ab94eSRussell King }
109045ab94eSRussell King 
110045ab94eSRussell King /*
111045ab94eSRussell King  * Power-off simply requires that the secondary CPUs stop performing any
112045ab94eSRussell King  * activity (executing tasks, handling interrupts). smp_send_stop()
113045ab94eSRussell King  * achieves this. When the system power is turned off, it will take all CPUs
114045ab94eSRussell King  * with it.
115045ab94eSRussell King  */
machine_power_off(void)116045ab94eSRussell King void machine_power_off(void)
117045ab94eSRussell King {
118045ab94eSRussell King 	local_irq_disable();
119045ab94eSRussell King 	smp_send_stop();
120856c288bSDmitry Osipenko 	do_kernel_power_off();
121045ab94eSRussell King }
122045ab94eSRussell King 
123045ab94eSRussell King /*
124045ab94eSRussell King  * Restart requires that the secondary CPUs stop performing any activity
125045ab94eSRussell King  * while the primary CPU resets the system. Systems with a single CPU can
126045ab94eSRussell King  * use soft_restart() as their machine descriptor's .restart hook, since that
127045ab94eSRussell King  * will cause the only available CPU to reset. Systems with multiple CPUs must
128045ab94eSRussell King  * provide a HW restart implementation, to ensure that all CPUs reset at once.
129045ab94eSRussell King  * This is required so that any code running after reset on the primary CPU
130045ab94eSRussell King  * doesn't have to co-ordinate with other CPUs to ensure they aren't still
131045ab94eSRussell King  * executing pre-reset code, and using RAM that the primary CPU's code wishes
132045ab94eSRussell King  * to use. Implementing such co-ordination would be essentially impossible.
133045ab94eSRussell King  */
machine_restart(char * cmd)134045ab94eSRussell King void machine_restart(char *cmd)
135045ab94eSRussell King {
136045ab94eSRussell King 	local_irq_disable();
137045ab94eSRussell King 	smp_send_stop();
138045ab94eSRussell King 
139045ab94eSRussell King 	do_kernel_restart(cmd);
140045ab94eSRussell King 
141045ab94eSRussell King 	/* Give a grace period for failure to restart of 1s */
142045ab94eSRussell King 	mdelay(1000);
143045ab94eSRussell King 
144045ab94eSRussell King 	/* Whoops - the platform was unable to reboot. Tell the user! */
145045ab94eSRussell King 	printk("Reboot failed -- System halted\n");
146045ab94eSRussell King 	while (1);
147045ab94eSRussell King }
148