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 #include <asm/virt.h> 16 17 #include "reboot.h" 18 19 typedef void (*phys_reset_t)(unsigned long, bool); 20 21 /* 22 * Function pointers to optional machine specific functions 23 */ 24 void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); 25 void (*pm_power_off)(void); 26 EXPORT_SYMBOL(pm_power_off); 27 28 /* 29 * A temporary stack to use for CPU reset. This is static so that we 30 * don't clobber it with the identity mapping. When running with this 31 * stack, any references to the current task *will not work* so you 32 * should really do as little as possible before jumping to your reset 33 * code. 34 */ 35 static u64 soft_restart_stack[16]; 36 37 static void __soft_restart(void *addr) 38 { 39 phys_reset_t phys_reset; 40 41 /* Take out a flat memory mapping. */ 42 setup_mm_for_reboot(); 43 44 /* Clean and invalidate caches */ 45 flush_cache_all(); 46 47 /* Turn off caching */ 48 cpu_proc_fin(); 49 50 /* Push out any further dirty data, and ensure cache is empty */ 51 flush_cache_all(); 52 53 /* Switch to the identity mapping. */ 54 phys_reset = (phys_reset_t)virt_to_idmap(cpu_reset); 55 56 /* original stub should be restored by kvm */ 57 phys_reset((unsigned long)addr, is_hyp_mode_available()); 58 59 /* Should never get here. */ 60 BUG(); 61 } 62 63 void _soft_restart(unsigned long addr, bool disable_l2) 64 { 65 u64 *stack = soft_restart_stack + ARRAY_SIZE(soft_restart_stack); 66 67 /* Disable interrupts first */ 68 raw_local_irq_disable(); 69 local_fiq_disable(); 70 71 /* Disable the L2 if we're the last man standing. */ 72 if (disable_l2) 73 outer_disable(); 74 75 /* Change to the new stack and continue with the reset. */ 76 call_with_stack(__soft_restart, (void *)addr, (void *)stack); 77 78 /* Should never get here. */ 79 BUG(); 80 } 81 82 void soft_restart(unsigned long addr) 83 { 84 _soft_restart(addr, num_online_cpus() == 1); 85 } 86 87 /* 88 * Called by kexec, immediately prior to machine_kexec(). 89 * 90 * This must completely disable all secondary CPUs; simply causing those CPUs 91 * to execute e.g. a RAM-based pin loop is not sufficient. This allows the 92 * kexec'd kernel to use any and all RAM as it sees fit, without having to 93 * avoid any code or data used by any SW CPU pin loop. The CPU hotplug 94 * functionality embodied in disable_nonboot_cpus() to achieve this. 95 */ 96 void machine_shutdown(void) 97 { 98 disable_nonboot_cpus(); 99 } 100 101 /* 102 * Halting simply requires that the secondary CPUs stop performing any 103 * activity (executing tasks, handling interrupts). smp_send_stop() 104 * achieves this. 105 */ 106 void machine_halt(void) 107 { 108 local_irq_disable(); 109 smp_send_stop(); 110 while (1); 111 } 112 113 /* 114 * Power-off simply requires that the secondary CPUs stop performing any 115 * activity (executing tasks, handling interrupts). smp_send_stop() 116 * achieves this. When the system power is turned off, it will take all CPUs 117 * with it. 118 */ 119 void machine_power_off(void) 120 { 121 local_irq_disable(); 122 smp_send_stop(); 123 124 if (pm_power_off) 125 pm_power_off(); 126 } 127 128 /* 129 * Restart requires that the secondary CPUs stop performing any activity 130 * while the primary CPU resets the system. Systems with a single CPU can 131 * use soft_restart() as their machine descriptor's .restart hook, since that 132 * will cause the only available CPU to reset. Systems with multiple CPUs must 133 * provide a HW restart implementation, to ensure that all CPUs reset at once. 134 * This is required so that any code running after reset on the primary CPU 135 * doesn't have to co-ordinate with other CPUs to ensure they aren't still 136 * executing pre-reset code, and using RAM that the primary CPU's code wishes 137 * to use. Implementing such co-ordination would be essentially impossible. 138 */ 139 void machine_restart(char *cmd) 140 { 141 local_irq_disable(); 142 smp_send_stop(); 143 144 if (arm_pm_restart) 145 arm_pm_restart(reboot_mode, cmd); 146 else 147 do_kernel_restart(cmd); 148 149 /* Give a grace period for failure to restart of 1s */ 150 mdelay(1000); 151 152 /* Whoops - the platform was unable to reboot. Tell the user! */ 153 printk("Reboot failed -- System halted\n"); 154 while (1); 155 } 156