aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel
diff options
context:
space:
mode:
authorRussell King <rmk+kernel@arm.linux.org.uk>2015-04-01 12:02:45 -0400
committerRussell King <rmk+kernel@arm.linux.org.uk>2015-04-02 04:50:45 -0400
commit045ab94e10ee17038066d71abc8fdce719ab56f9 (patch)
tree4792e1db4af20c88bf88a4f8adb280de1b766fdf /arch/arm/kernel
parent767bf7e7a1e82a81c59778348d156993d0a6175d (diff)
ARM: move reboot code to arch/arm/kernel/reboot.c
Move shutdown and reboot related code to a separate file, out of process.c. This helps to avoid polluting process.c with non-process related code. Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
Diffstat (limited to 'arch/arm/kernel')
-rw-r--r--arch/arm/kernel/Makefile2
-rw-r--r--arch/arm/kernel/hibernate.c1
-rw-r--r--arch/arm/kernel/process.c149
-rw-r--r--arch/arm/kernel/reboot.c155
-rw-r--r--arch/arm/kernel/reboot.h1
5 files changed, 158 insertions, 150 deletions
diff --git a/arch/arm/kernel/Makefile b/arch/arm/kernel/Makefile
index 1c1cdfa566ac..b6544abe2f5e 100644
--- a/arch/arm/kernel/Makefile
+++ b/arch/arm/kernel/Makefile
@@ -16,7 +16,7 @@ CFLAGS_REMOVE_return_address.o = -pg
16# Object file lists. 16# Object file lists.
17 17
18obj-y := elf.o entry-common.o irq.o opcodes.o \ 18obj-y := elf.o entry-common.o irq.o opcodes.o \
19 process.o ptrace.o return_address.o \ 19 process.o ptrace.o reboot.o return_address.o \
20 setup.o signal.o sigreturn_codes.o \ 20 setup.o signal.o sigreturn_codes.o \
21 stacktrace.o sys_arm.o time.o traps.o 21 stacktrace.o sys_arm.o time.o traps.o
22 22
diff --git a/arch/arm/kernel/hibernate.c b/arch/arm/kernel/hibernate.c
index cfb354ff2a60..a71501ff6f18 100644
--- a/arch/arm/kernel/hibernate.c
+++ b/arch/arm/kernel/hibernate.c
@@ -100,7 +100,6 @@ static u64 resume_stack[PAGE_SIZE/2/sizeof(u64)] __nosavedata;
100 */ 100 */
101int swsusp_arch_resume(void) 101int swsusp_arch_resume(void)
102{ 102{
103 extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
104 call_with_stack(arch_restore_image, 0, 103 call_with_stack(arch_restore_image, 0,
105 resume_stack + ARRAY_SIZE(resume_stack)); 104 resume_stack + ARRAY_SIZE(resume_stack));
106 return 0; 105 return 0;
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 2bf1a162defb..f810a6cc3790 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -17,12 +17,9 @@
17#include <linux/stddef.h> 17#include <linux/stddef.h>
18#include <linux/unistd.h> 18#include <linux/unistd.h>
19#include <linux/user.h> 19#include <linux/user.h>
20#include <linux/delay.h>
21#include <linux/reboot.h>
22#include <linux/interrupt.h> 20#include <linux/interrupt.h>
23#include <linux/kallsyms.h> 21#include <linux/kallsyms.h>
24#include <linux/init.h> 22#include <linux/init.h>
25#include <linux/cpu.h>
26#include <linux/elfcore.h> 23#include <linux/elfcore.h>
27#include <linux/pm.h> 24#include <linux/pm.h>
28#include <linux/tick.h> 25#include <linux/tick.h>
@@ -31,17 +28,14 @@
31#include <linux/random.h> 28#include <linux/random.h>
32#include <linux/hw_breakpoint.h> 29#include <linux/hw_breakpoint.h>
33#include <linux/leds.h> 30#include <linux/leds.h>
34#include <linux/reboot.h>
35 31
36#include <asm/cacheflush.h>
37#include <asm/idmap.h>
38#include <asm/processor.h> 32#include <asm/processor.h>
39#include <asm/thread_notify.h> 33#include <asm/thread_notify.h>
40#include <asm/stacktrace.h> 34#include <asm/stacktrace.h>
41#include <asm/system_misc.h> 35#include <asm/system_misc.h>
42#include <asm/mach/time.h> 36#include <asm/mach/time.h>
43#include <asm/tls.h> 37#include <asm/tls.h>
44#include "reboot.h" 38#include <asm/vdso.h>
45 39
46#ifdef CONFIG_CC_STACKPROTECTOR 40#ifdef CONFIG_CC_STACKPROTECTOR
47#include <linux/stackprotector.h> 41#include <linux/stackprotector.h>
@@ -60,74 +54,6 @@ static const char *isa_modes[] __maybe_unused = {
60 "ARM" , "Thumb" , "Jazelle", "ThumbEE" 54 "ARM" , "Thumb" , "Jazelle", "ThumbEE"
61}; 55};
62 56
63extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
64typedef void (*phys_reset_t)(unsigned long);
65
66/*
67 * A temporary stack to use for CPU reset. This is static so that we
68 * don't clobber it with the identity mapping. When running with this
69 * stack, any references to the current task *will not work* so you
70 * should really do as little as possible before jumping to your reset
71 * code.
72 */
73static u64 soft_restart_stack[16];
74
75static void __soft_restart(void *addr)
76{
77 phys_reset_t phys_reset;
78
79 /* Take out a flat memory mapping. */
80 setup_mm_for_reboot();
81
82 /* Clean and invalidate caches */
83 flush_cache_all();
84
85 /* Turn off caching */
86 cpu_proc_fin();
87
88 /* Push out any further dirty data, and ensure cache is empty */
89 flush_cache_all();
90
91 /* Switch to the identity mapping. */
92 phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
93 phys_reset((unsigned long)addr);
94
95 /* Should never get here. */
96 BUG();
97}
98
99void _soft_restart(unsigned long addr, bool disable_l2)
100{
101 u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
102
103 /* Disable interrupts first */
104 raw_local_irq_disable();
105 local_fiq_disable();
106
107 /* Disable the L2 if we're the last man standing. */
108 if (disable_l2)
109 outer_disable();
110
111 /* Change to the new stack and continue with the reset. */
112 call_with_stack(__soft_restart, (void *)addr, (void *)stack);
113
114 /* Should never get here. */
115 BUG();
116}
117
118void soft_restart(unsigned long addr)
119{
120 _soft_restart(addr, num_online_cpus() == 1);
121}
122
123/*
124 * Function pointers to optional machine specific functions
125 */
126void (*pm_power_off)(void);
127EXPORT_SYMBOL(pm_power_off);
128
129void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
130
131/* 57/*
132 * This is our default idle handler. 58 * This is our default idle handler.
133 */ 59 */
@@ -172,79 +98,6 @@ void arch_cpu_idle_dead(void)
172} 98}
173#endif 99#endif
174 100
175/*
176 * Called by kexec, immediately prior to machine_kexec().
177 *
178 * This must completely disable all secondary CPUs; simply causing those CPUs
179 * to execute e.g. a RAM-based pin loop is not sufficient. This allows the
180 * kexec'd kernel to use any and all RAM as it sees fit, without having to
181 * avoid any code or data used by any SW CPU pin loop. The CPU hotplug
182 * functionality embodied in disable_nonboot_cpus() to achieve this.
183 */
184void machine_shutdown(void)
185{
186 disable_nonboot_cpus();
187}
188
189/*
190 * Halting simply requires that the secondary CPUs stop performing any
191 * activity (executing tasks, handling interrupts). smp_send_stop()
192 * achieves this.
193 */
194void machine_halt(void)
195{
196 local_irq_disable();
197 smp_send_stop();
198
199 local_irq_disable();
200 while (1);
201}
202
203/*
204 * Power-off simply requires that the secondary CPUs stop performing any
205 * activity (executing tasks, handling interrupts). smp_send_stop()
206 * achieves this. When the system power is turned off, it will take all CPUs
207 * with it.
208 */
209void machine_power_off(void)
210{
211 local_irq_disable();
212 smp_send_stop();
213
214 if (pm_power_off)
215 pm_power_off();
216}
217
218/*
219 * Restart requires that the secondary CPUs stop performing any activity
220 * while the primary CPU resets the system. Systems with a single CPU can
221 * use soft_restart() as their machine descriptor's .restart hook, since that
222 * will cause the only available CPU to reset. Systems with multiple CPUs must
223 * provide a HW restart implementation, to ensure that all CPUs reset at once.
224 * This is required so that any code running after reset on the primary CPU
225 * doesn't have to co-ordinate with other CPUs to ensure they aren't still
226 * executing pre-reset code, and using RAM that the primary CPU's code wishes
227 * to use. Implementing such co-ordination would be essentially impossible.
228 */
229void machine_restart(char *cmd)
230{
231 local_irq_disable();
232 smp_send_stop();
233
234 if (arm_pm_restart)
235 arm_pm_restart(reboot_mode, cmd);
236 else
237 do_kernel_restart(cmd);
238
239 /* Give a grace period for failure to restart of 1s */
240 mdelay(1000);
241
242 /* Whoops - the platform was unable to reboot. Tell the user! */
243 printk("Reboot failed -- System halted\n");
244 local_irq_disable();
245 while (1);
246}
247
248void __show_regs(struct pt_regs *regs) 101void __show_regs(struct pt_regs *regs)
249{ 102{
250 unsigned long flags; 103 unsigned long flags;
diff --git a/arch/arm/kernel/reboot.c b/arch/arm/kernel/reboot.c
new file mode 100644
index 000000000000..1a4d232796be
--- /dev/null
+++ b/arch/arm/kernel/reboot.c
@@ -0,0 +1,155 @@
1/*
2 * Copyright (C) 1996-2000 Russell King - Converted to ARM.
3 * Original Copyright (C) 1995 Linus Torvalds
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License version 2 as
7 * published by the Free Software Foundation.
8 */
9#include <linux/cpu.h>
10#include <linux/delay.h>
11#include <linux/reboot.h>
12
13#include <asm/cacheflush.h>
14#include <asm/idmap.h>
15
16#include "reboot.h"
17
18typedef void (*phys_reset_t)(unsigned long);
19
20/*
21 * Function pointers to optional machine specific functions
22 */
23void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd);
24void (*pm_power_off)(void);
25EXPORT_SYMBOL(pm_power_off);
26
27/*
28 * A temporary stack to use for CPU reset. This is static so that we
29 * don't clobber it with the identity mapping. When running with this
30 * stack, any references to the current task *will not work* so you
31 * should really do as little as possible before jumping to your reset
32 * code.
33 */
34static u64 soft_restart_stack[16];
35
36static void __soft_restart(void *addr)
37{
38 phys_reset_t phys_reset;
39
40 /* Take out a flat memory mapping. */
41 setup_mm_for_reboot();
42
43 /* Clean and invalidate caches */
44 flush_cache_all();
45
46 /* Turn off caching */
47 cpu_proc_fin();
48
49 /* Push out any further dirty data, and ensure cache is empty */
50 flush_cache_all();
51
52 /* Switch to the identity mapping. */
53 phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset);
54 phys_reset((unsigned long)addr);
55
56 /* Should never get here. */
57 BUG();
58}
59
60void _soft_restart(unsigned long addr, bool disable_l2)
61{
62 u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack);
63
64 /* Disable interrupts first */
65 raw_local_irq_disable();
66 local_fiq_disable();
67
68 /* Disable the L2 if we're the last man standing. */
69 if (disable_l2)
70 outer_disable();
71
72 /* Change to the new stack and continue with the reset. */
73 call_with_stack(__soft_restart, (void *)addr, (void *)stack);
74
75 /* Should never get here. */
76 BUG();
77}
78
79void soft_restart(unsigned long addr)
80{
81 _soft_restart(addr, num_online_cpus() == 1);
82}
83
84/*
85 * Called by kexec, immediately prior to machine_kexec().
86 *
87 * This must completely disable all secondary CPUs; simply causing those CPUs
88 * to execute e.g. a RAM-based pin loop is not sufficient. This allows the
89 * kexec'd kernel to use any and all RAM as it sees fit, without having to
90 * avoid any code or data used by any SW CPU pin loop. The CPU hotplug
91 * functionality embodied in disable_nonboot_cpus() to achieve this.
92 */
93void machine_shutdown(void)
94{
95 disable_nonboot_cpus();
96}
97
98/*
99 * Halting simply requires that the secondary CPUs stop performing any
100 * activity (executing tasks, handling interrupts). smp_send_stop()
101 * achieves this.
102 */
103void machine_halt(void)
104{
105 local_irq_disable();
106 smp_send_stop();
107
108 local_irq_disable();
109 while (1);
110}
111
112/*
113 * Power-off simply requires that the secondary CPUs stop performing any
114 * activity (executing tasks, handling interrupts). smp_send_stop()
115 * achieves this. When the system power is turned off, it will take all CPUs
116 * with it.
117 */
118void machine_power_off(void)
119{
120 local_irq_disable();
121 smp_send_stop();
122
123 if (pm_power_off)
124 pm_power_off();
125}
126
127/*
128 * Restart requires that the secondary CPUs stop performing any activity
129 * while the primary CPU resets the system. Systems with a single CPU can
130 * use soft_restart() as their machine descriptor's .restart hook, since that
131 * will cause the only available CPU to reset. Systems with multiple CPUs must
132 * provide a HW restart implementation, to ensure that all CPUs reset at once.
133 * This is required so that any code running after reset on the primary CPU
134 * doesn't have to co-ordinate with other CPUs to ensure they aren't still
135 * executing pre-reset code, and using RAM that the primary CPU's code wishes
136 * to use. Implementing such co-ordination would be essentially impossible.
137 */
138void machine_restart(char *cmd)
139{
140 local_irq_disable();
141 smp_send_stop();
142
143 if (arm_pm_restart)
144 arm_pm_restart(reboot_mode, cmd);
145 else
146 do_kernel_restart(cmd);
147
148 /* Give a grace period for failure to restart of 1s */
149 mdelay(1000);
150
151 /* Whoops - the platform was unable to reboot. Tell the user! */
152 printk("Reboot failed -- System halted\n");
153 local_irq_disable();
154 while (1);
155}
diff --git a/arch/arm/kernel/reboot.h b/arch/arm/kernel/reboot.h
index c87f05816d6b..bf7a0b1f076e 100644
--- a/arch/arm/kernel/reboot.h
+++ b/arch/arm/kernel/reboot.h
@@ -1,6 +1,7 @@
1#ifndef REBOOT_H 1#ifndef REBOOT_H
2#define REBOOT_H 2#define REBOOT_H
3 3
4extern void call_with_stack(void (*fn)(void *), void *arg, void *sp);
4extern void _soft_restart(unsigned long addr, bool disable_l2); 5extern void _soft_restart(unsigned long addr, bool disable_l2);
5 6
6#endif 7#endif