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