aboutsummaryrefslogtreecommitdiffstats
path: root/arch/arm/kernel/process.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/arm/kernel/process.c')
-rw-r--r--arch/arm/kernel/process.c133
1 files changed, 126 insertions, 7 deletions
diff --git a/arch/arm/kernel/process.c b/arch/arm/kernel/process.c
index 5e1e5419722..3a2da7788cc 100644
--- a/arch/arm/kernel/process.c
+++ b/arch/arm/kernel/process.c
@@ -30,9 +30,10 @@
30#include <linux/uaccess.h> 30#include <linux/uaccess.h>
31#include <linux/random.h> 31#include <linux/random.h>
32#include <linux/hw_breakpoint.h> 32#include <linux/hw_breakpoint.h>
33#include <linux/cpuidle.h>
34#include <linux/console.h>
33 35
34#include <asm/cacheflush.h> 36#include <asm/cacheflush.h>
35#include <asm/leds.h>
36#include <asm/processor.h> 37#include <asm/processor.h>
37#include <asm/system.h> 38#include <asm/system.h>
38#include <asm/thread_notify.h> 39#include <asm/thread_notify.h>
@@ -62,6 +63,18 @@ static volatile int hlt_counter;
62 63
63#include <mach/system.h> 64#include <mach/system.h>
64 65
66#ifdef CONFIG_SMP
67void arch_trigger_all_cpu_backtrace(void)
68{
69 smp_send_all_cpu_backtrace();
70}
71#else
72void arch_trigger_all_cpu_backtrace(void)
73{
74 dump_stack();
75}
76#endif
77
65void disable_hlt(void) 78void disable_hlt(void)
66{ 79{
67 hlt_counter++; 80 hlt_counter++;
@@ -91,12 +104,33 @@ static int __init hlt_setup(char *__unused)
91__setup("nohlt", nohlt_setup); 104__setup("nohlt", nohlt_setup);
92__setup("hlt", hlt_setup); 105__setup("hlt", hlt_setup);
93 106
94void arm_machine_restart(char mode, const char *cmd) 107#ifdef CONFIG_ARM_FLUSH_CONSOLE_ON_RESTART
108void arm_machine_flush_console(void)
95{ 109{
96 /* Disable interrupts first */ 110 printk("\n");
111 pr_emerg("Restarting %s\n", linux_banner);
112 if (console_trylock()) {
113 console_unlock();
114 return;
115 }
116
117 mdelay(50);
118
97 local_irq_disable(); 119 local_irq_disable();
98 local_fiq_disable(); 120 if (!console_trylock())
121 pr_emerg("arm_restart: Console was locked! Busting\n");
122 else
123 pr_emerg("arm_restart: Console was locked!\n");
124 console_unlock();
125}
126#else
127void arm_machine_flush_console(void)
128{
129}
130#endif
99 131
132void arm_machine_restart(char mode, const char *cmd)
133{
100 /* 134 /*
101 * Tell the mm system that we are going to reboot - 135 * Tell the mm system that we are going to reboot -
102 * we may need it to insert some 1:1 mappings so that 136 * we may need it to insert some 1:1 mappings so that
@@ -182,8 +216,8 @@ void cpu_idle(void)
182 216
183 /* endless idle loop with no priority at all */ 217 /* endless idle loop with no priority at all */
184 while (1) { 218 while (1) {
219 idle_notifier_call_chain(IDLE_START);
185 tick_nohz_stop_sched_tick(1); 220 tick_nohz_stop_sched_tick(1);
186 leds_event(led_idle_start);
187 while (!need_resched()) { 221 while (!need_resched()) {
188#ifdef CONFIG_HOTPLUG_CPU 222#ifdef CONFIG_HOTPLUG_CPU
189 if (cpu_is_offline(smp_processor_id())) 223 if (cpu_is_offline(smp_processor_id()))
@@ -191,12 +225,16 @@ void cpu_idle(void)
191#endif 225#endif
192 226
193 local_irq_disable(); 227 local_irq_disable();
228#ifdef CONFIG_PL310_ERRATA_769419
229 wmb();
230#endif
194 if (hlt_counter) { 231 if (hlt_counter) {
195 local_irq_enable(); 232 local_irq_enable();
196 cpu_relax(); 233 cpu_relax();
197 } else { 234 } else {
198 stop_critical_timings(); 235 stop_critical_timings();
199 pm_idle(); 236 if (cpuidle_idle_call())
237 pm_idle();
200 start_critical_timings(); 238 start_critical_timings();
201 /* 239 /*
202 * This will eventually be removed - pm_idle 240 * This will eventually be removed - pm_idle
@@ -207,8 +245,8 @@ void cpu_idle(void)
207 local_irq_enable(); 245 local_irq_enable();
208 } 246 }
209 } 247 }
210 leds_event(led_idle_end);
211 tick_nohz_restart_sched_tick(); 248 tick_nohz_restart_sched_tick();
249 idle_notifier_call_chain(IDLE_END);
212 preempt_enable_no_resched(); 250 preempt_enable_no_resched();
213 schedule(); 251 schedule();
214 preempt_disable(); 252 preempt_disable();
@@ -247,10 +285,89 @@ void machine_power_off(void)
247 285
248void machine_restart(char *cmd) 286void machine_restart(char *cmd)
249{ 287{
288 /* Flush the console to make sure all the relevant messages make it
289 * out to the console drivers */
290 arm_machine_flush_console();
291
292 /* Disable interrupts first */
293 local_irq_disable();
294 local_fiq_disable();
295
250 machine_shutdown(); 296 machine_shutdown();
251 arm_pm_restart(reboot_mode, cmd); 297 arm_pm_restart(reboot_mode, cmd);
252} 298}
253 299
300/*
301 * dump a block of kernel memory from around the given address
302 */
303static void show_data(unsigned long addr, int nbytes, const char *name)
304{
305 int i, j;
306 int nlines;
307 u32 *p;
308
309 /*
310 * don't attempt to dump non-kernel addresses or
311 * values that are probably just small negative numbers
312 */
313 if (addr < PAGE_OFFSET || addr > -256UL)
314 return;
315
316 printk("\n%s: %#lx:\n", name, addr);
317
318 /*
319 * round address down to a 32 bit boundary
320 * and always dump a multiple of 32 bytes
321 */
322 p = (u32 *)(addr & ~(sizeof(u32) - 1));
323 nbytes += (addr & (sizeof(u32) - 1));
324 nlines = (nbytes + 31) / 32;
325
326
327 for (i = 0; i < nlines; i++) {
328 /*
329 * just display low 16 bits of address to keep
330 * each line of the dump < 80 characters
331 */
332 printk("%04lx ", (unsigned long)p & 0xffff);
333 for (j = 0; j < 8; j++) {
334 u32 data;
335 if (probe_kernel_address(p, data)) {
336 printk(" ********");
337 } else {
338 printk(" %08x", data);
339 }
340 ++p;
341 }
342 printk("\n");
343 }
344}
345
346static void show_extra_register_data(struct pt_regs *regs, int nbytes)
347{
348 mm_segment_t fs;
349
350 fs = get_fs();
351 set_fs(KERNEL_DS);
352 show_data(regs->ARM_pc - nbytes, nbytes * 2, "PC");
353 show_data(regs->ARM_lr - nbytes, nbytes * 2, "LR");
354 show_data(regs->ARM_sp - nbytes, nbytes * 2, "SP");
355 show_data(regs->ARM_ip - nbytes, nbytes * 2, "IP");
356 show_data(regs->ARM_fp - nbytes, nbytes * 2, "FP");
357 show_data(regs->ARM_r0 - nbytes, nbytes * 2, "R0");
358 show_data(regs->ARM_r1 - nbytes, nbytes * 2, "R1");
359 show_data(regs->ARM_r2 - nbytes, nbytes * 2, "R2");
360 show_data(regs->ARM_r3 - nbytes, nbytes * 2, "R3");
361 show_data(regs->ARM_r4 - nbytes, nbytes * 2, "R4");
362 show_data(regs->ARM_r5 - nbytes, nbytes * 2, "R5");
363 show_data(regs->ARM_r6 - nbytes, nbytes * 2, "R6");
364 show_data(regs->ARM_r7 - nbytes, nbytes * 2, "R7");
365 show_data(regs->ARM_r8 - nbytes, nbytes * 2, "R8");
366 show_data(regs->ARM_r9 - nbytes, nbytes * 2, "R9");
367 show_data(regs->ARM_r10 - nbytes, nbytes * 2, "R10");
368 set_fs(fs);
369}
370
254void __show_regs(struct pt_regs *regs) 371void __show_regs(struct pt_regs *regs)
255{ 372{
256 unsigned long flags; 373 unsigned long flags;
@@ -310,6 +427,8 @@ void __show_regs(struct pt_regs *regs)
310 printk("Control: %08x%s\n", ctrl, buf); 427 printk("Control: %08x%s\n", ctrl, buf);
311 } 428 }
312#endif 429#endif
430
431 show_extra_register_data(regs, 128);
313} 432}
314 433
315void show_regs(struct pt_regs * regs) 434void show_regs(struct pt_regs * regs)