diff options
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r-- | arch/arm/kernel/process.c | 77 |
1 files changed, 54 insertions, 23 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c index 3d0c6fb74ae4..b29776aa6586 100644 --- a/arch/arm/kernel/process.c +++ b/arch/arm/kernel/process.c | |||
@@ -57,7 +57,7 @@ static const char *isa_modes[] = { | |||
57 | "ARM" , "Thumb" , "Jazelle", "ThumbEE" | 57 | "ARM" , "Thumb" , "Jazelle", "ThumbEE" |
58 | }; | 58 | }; |
59 | 59 | ||
60 | extern void setup_mm_for_reboot(char mode); | 60 | extern void setup_mm_for_reboot(void); |
61 | 61 | ||
62 | static volatile int hlt_counter; | 62 | static volatile int hlt_counter; |
63 | 63 | ||
@@ -92,18 +92,24 @@ static int __init hlt_setup(char *__unused) | |||
92 | __setup("nohlt", nohlt_setup); | 92 | __setup("nohlt", nohlt_setup); |
93 | __setup("hlt", hlt_setup); | 93 | __setup("hlt", hlt_setup); |
94 | 94 | ||
95 | void arm_machine_restart(char mode, const char *cmd) | 95 | extern void call_with_stack(void (*fn)(void *), void *arg, void *sp); |
96 | typedef void (*phys_reset_t)(unsigned long); | ||
97 | |||
98 | /* | ||
99 | * A temporary stack to use for CPU reset. This is static so that we | ||
100 | * don't clobber it with the identity mapping. When running with this | ||
101 | * stack, any references to the current task *will not work* so you | ||
102 | * should really do as little as possible before jumping to your reset | ||
103 | * code. | ||
104 | */ | ||
105 | static u64 soft_restart_stack[16]; | ||
106 | |||
107 | static void __soft_restart(void *addr) | ||
96 | { | 108 | { |
97 | /* Disable interrupts first */ | 109 | phys_reset_t phys_reset; |
98 | local_irq_disable(); | ||
99 | local_fiq_disable(); | ||
100 | 110 | ||
101 | /* | 111 | /* Take out a flat memory mapping. */ |
102 | * Tell the mm system that we are going to reboot - | 112 | setup_mm_for_reboot(); |
103 | * we may need it to insert some 1:1 mappings so that | ||
104 | * soft boot works. | ||
105 | */ | ||
106 | setup_mm_for_reboot(mode); | ||
107 | 113 | ||
108 | /* Clean and invalidate caches */ | 114 | /* Clean and invalidate caches */ |
109 | flush_cache_all(); | 115 | flush_cache_all(); |
@@ -114,18 +120,35 @@ void arm_machine_restart(char mode, const char *cmd) | |||
114 | /* Push out any further dirty data, and ensure cache is empty */ | 120 | /* Push out any further dirty data, and ensure cache is empty */ |
115 | flush_cache_all(); | 121 | flush_cache_all(); |
116 | 122 | ||
117 | /* | 123 | /* Switch to the identity mapping. */ |
118 | * Now call the architecture specific reboot code. | 124 | phys_reset = (phys_reset_t)(unsigned long)virt_to_phys(cpu_reset); |
119 | */ | 125 | phys_reset((unsigned long)addr); |
120 | arch_reset(mode, cmd); | ||
121 | 126 | ||
122 | /* | 127 | /* Should never get here. */ |
123 | * Whoops - the architecture was unable to reboot. | 128 | BUG(); |
124 | * Tell the user! | 129 | } |
125 | */ | 130 | |
126 | mdelay(1000); | 131 | void soft_restart(unsigned long addr) |
127 | printk("Reboot failed -- System halted\n"); | 132 | { |
128 | while (1); | 133 | u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); |
134 | |||
135 | /* Disable interrupts first */ | ||
136 | local_irq_disable(); | ||
137 | local_fiq_disable(); | ||
138 | |||
139 | /* Disable the L2 if we're the last man standing. */ | ||
140 | if (num_online_cpus() == 1) | ||
141 | outer_disable(); | ||
142 | |||
143 | /* Change to the new stack and continue with the reset. */ | ||
144 | call_with_stack(__soft_restart, (void *)addr, (void *)stack); | ||
145 | |||
146 | /* Should never get here. */ | ||
147 | BUG(); | ||
148 | } | ||
149 | |||
150 | static void null_restart(char mode, const char *cmd) | ||
151 | { | ||
129 | } | 152 | } |
130 | 153 | ||
131 | /* | 154 | /* |
@@ -134,7 +157,7 @@ void arm_machine_restart(char mode, const char *cmd) | |||
134 | void (*pm_power_off)(void); | 157 | void (*pm_power_off)(void); |
135 | EXPORT_SYMBOL(pm_power_off); | 158 | EXPORT_SYMBOL(pm_power_off); |
136 | 159 | ||
137 | void (*arm_pm_restart)(char str, const char *cmd) = arm_machine_restart; | 160 | void (*arm_pm_restart)(char str, const char *cmd) = null_restart; |
138 | EXPORT_SYMBOL_GPL(arm_pm_restart); | 161 | EXPORT_SYMBOL_GPL(arm_pm_restart); |
139 | 162 | ||
140 | static void do_nothing(void *unused) | 163 | static void do_nothing(void *unused) |
@@ -253,7 +276,15 @@ void machine_power_off(void) | |||
253 | void machine_restart(char *cmd) | 276 | void machine_restart(char *cmd) |
254 | { | 277 | { |
255 | machine_shutdown(); | 278 | machine_shutdown(); |
279 | |||
256 | arm_pm_restart(reboot_mode, cmd); | 280 | arm_pm_restart(reboot_mode, cmd); |
281 | |||
282 | /* Give a grace period for failure to restart of 1s */ | ||
283 | mdelay(1000); | ||
284 | |||
285 | /* Whoops - the platform was unable to reboot. Tell the user! */ | ||
286 | printk("Reboot failed -- System halted\n"); | ||
287 | while (1); | ||
257 | } | 288 | } |
258 | 289 | ||
259 | void __show_regs(struct pt_regs *regs) | 290 | void __show_regs(struct pt_regs *regs) |