1b3901d54SCatalin Marinas /* 2b3901d54SCatalin Marinas * Based on arch/arm/kernel/process.c 3b3901d54SCatalin Marinas * 4b3901d54SCatalin Marinas * Original Copyright (C) 1995 Linus Torvalds 5b3901d54SCatalin Marinas * Copyright (C) 1996-2000 Russell King - Converted to ARM. 6b3901d54SCatalin Marinas * Copyright (C) 2012 ARM Ltd. 7b3901d54SCatalin Marinas * 8b3901d54SCatalin Marinas * This program is free software; you can redistribute it and/or modify 9b3901d54SCatalin Marinas * it under the terms of the GNU General Public License version 2 as 10b3901d54SCatalin Marinas * published by the Free Software Foundation. 11b3901d54SCatalin Marinas * 12b3901d54SCatalin Marinas * This program is distributed in the hope that it will be useful, 13b3901d54SCatalin Marinas * but WITHOUT ANY WARRANTY; without even the implied warranty of 14b3901d54SCatalin Marinas * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15b3901d54SCatalin Marinas * GNU General Public License for more details. 16b3901d54SCatalin Marinas * 17b3901d54SCatalin Marinas * You should have received a copy of the GNU General Public License 18b3901d54SCatalin Marinas * along with this program. If not, see <http://www.gnu.org/licenses/>. 19b3901d54SCatalin Marinas */ 20b3901d54SCatalin Marinas 21b3901d54SCatalin Marinas #include <stdarg.h> 22b3901d54SCatalin Marinas 23b3901d54SCatalin Marinas #include <linux/export.h> 24b3901d54SCatalin Marinas #include <linux/sched.h> 25b3901d54SCatalin Marinas #include <linux/kernel.h> 26b3901d54SCatalin Marinas #include <linux/mm.h> 27b3901d54SCatalin Marinas #include <linux/stddef.h> 28b3901d54SCatalin Marinas #include <linux/unistd.h> 29b3901d54SCatalin Marinas #include <linux/user.h> 30b3901d54SCatalin Marinas #include <linux/delay.h> 31b3901d54SCatalin Marinas #include <linux/reboot.h> 32b3901d54SCatalin Marinas #include <linux/interrupt.h> 33b3901d54SCatalin Marinas #include <linux/kallsyms.h> 34b3901d54SCatalin Marinas #include <linux/init.h> 35b3901d54SCatalin Marinas #include <linux/cpu.h> 36b3901d54SCatalin Marinas #include <linux/elfcore.h> 37b3901d54SCatalin Marinas #include <linux/pm.h> 38b3901d54SCatalin Marinas #include <linux/tick.h> 39b3901d54SCatalin Marinas #include <linux/utsname.h> 40b3901d54SCatalin Marinas #include <linux/uaccess.h> 41b3901d54SCatalin Marinas #include <linux/random.h> 42b3901d54SCatalin Marinas #include <linux/hw_breakpoint.h> 43b3901d54SCatalin Marinas #include <linux/personality.h> 44b3901d54SCatalin Marinas #include <linux/notifier.h> 45b3901d54SCatalin Marinas 46b3901d54SCatalin Marinas #include <asm/compat.h> 47b3901d54SCatalin Marinas #include <asm/cacheflush.h> 48ec45d1cfSWill Deacon #include <asm/fpsimd.h> 49ec45d1cfSWill Deacon #include <asm/mmu_context.h> 50b3901d54SCatalin Marinas #include <asm/processor.h> 51b3901d54SCatalin Marinas #include <asm/stacktrace.h> 52b3901d54SCatalin Marinas 53b3901d54SCatalin Marinas static void setup_restart(void) 54b3901d54SCatalin Marinas { 55b3901d54SCatalin Marinas /* 56b3901d54SCatalin Marinas * Tell the mm system that we are going to reboot - 57b3901d54SCatalin Marinas * we may need it to insert some 1:1 mappings so that 58b3901d54SCatalin Marinas * soft boot works. 59b3901d54SCatalin Marinas */ 60b3901d54SCatalin Marinas setup_mm_for_reboot(); 61b3901d54SCatalin Marinas 62b3901d54SCatalin Marinas /* Clean and invalidate caches */ 63b3901d54SCatalin Marinas flush_cache_all(); 64b3901d54SCatalin Marinas 65b3901d54SCatalin Marinas /* Turn D-cache off */ 66b3901d54SCatalin Marinas cpu_cache_off(); 67b3901d54SCatalin Marinas 68b3901d54SCatalin Marinas /* Push out any further dirty data, and ensure cache is empty */ 69b3901d54SCatalin Marinas flush_cache_all(); 70b3901d54SCatalin Marinas } 71b3901d54SCatalin Marinas 72b3901d54SCatalin Marinas void soft_restart(unsigned long addr) 73b3901d54SCatalin Marinas { 74b3901d54SCatalin Marinas setup_restart(); 75b3901d54SCatalin Marinas cpu_reset(addr); 76b3901d54SCatalin Marinas } 77b3901d54SCatalin Marinas 78b3901d54SCatalin Marinas /* 79b3901d54SCatalin Marinas * Function pointers to optional machine specific functions 80b3901d54SCatalin Marinas */ 81b3901d54SCatalin Marinas void (*pm_power_off)(void); 82b3901d54SCatalin Marinas EXPORT_SYMBOL_GPL(pm_power_off); 83b3901d54SCatalin Marinas 84*b0946fc8SCatalin Marinas void (*arm_pm_restart)(enum reboot_mode reboot_mode, const char *cmd); 85aa1e8ec1SCatalin Marinas EXPORT_SYMBOL_GPL(arm_pm_restart); 86b3901d54SCatalin Marinas 870087298fSThomas Gleixner void arch_cpu_idle_prepare(void) 880087298fSThomas Gleixner { 890087298fSThomas Gleixner local_fiq_enable(); 900087298fSThomas Gleixner } 91b3901d54SCatalin Marinas 92b3901d54SCatalin Marinas /* 93b3901d54SCatalin Marinas * This is our default idle handler. 94b3901d54SCatalin Marinas */ 950087298fSThomas Gleixner void arch_cpu_idle(void) 96b3901d54SCatalin Marinas { 97b3901d54SCatalin Marinas /* 98b3901d54SCatalin Marinas * This should do all the clock switching and wait for interrupt 99b3901d54SCatalin Marinas * tricks 100b3901d54SCatalin Marinas */ 101b3901d54SCatalin Marinas cpu_do_idle(); 102b3901d54SCatalin Marinas local_irq_enable(); 103b3901d54SCatalin Marinas } 104b3901d54SCatalin Marinas 105b3901d54SCatalin Marinas void machine_shutdown(void) 106b3901d54SCatalin Marinas { 107b3901d54SCatalin Marinas #ifdef CONFIG_SMP 108b3901d54SCatalin Marinas smp_send_stop(); 109b3901d54SCatalin Marinas #endif 110b3901d54SCatalin Marinas } 111b3901d54SCatalin Marinas 112b3901d54SCatalin Marinas void machine_halt(void) 113b3901d54SCatalin Marinas { 114b3901d54SCatalin Marinas machine_shutdown(); 115b3901d54SCatalin Marinas while (1); 116b3901d54SCatalin Marinas } 117b3901d54SCatalin Marinas 118b3901d54SCatalin Marinas void machine_power_off(void) 119b3901d54SCatalin Marinas { 120b3901d54SCatalin Marinas machine_shutdown(); 121b3901d54SCatalin Marinas if (pm_power_off) 122b3901d54SCatalin Marinas pm_power_off(); 123b3901d54SCatalin Marinas } 124b3901d54SCatalin Marinas 125b3901d54SCatalin Marinas void machine_restart(char *cmd) 126b3901d54SCatalin Marinas { 127b3901d54SCatalin Marinas machine_shutdown(); 128b3901d54SCatalin Marinas 129b3901d54SCatalin Marinas /* Disable interrupts first */ 130b3901d54SCatalin Marinas local_irq_disable(); 131b3901d54SCatalin Marinas local_fiq_disable(); 132b3901d54SCatalin Marinas 133b3901d54SCatalin Marinas /* Now call the architecture specific reboot code. */ 134aa1e8ec1SCatalin Marinas if (arm_pm_restart) 135ff701306SMarc Zyngier arm_pm_restart(reboot_mode, cmd); 136b3901d54SCatalin Marinas 137b3901d54SCatalin Marinas /* 138b3901d54SCatalin Marinas * Whoops - the architecture was unable to reboot. 139b3901d54SCatalin Marinas */ 140b3901d54SCatalin Marinas printk("Reboot failed -- System halted\n"); 141b3901d54SCatalin Marinas while (1); 142b3901d54SCatalin Marinas } 143b3901d54SCatalin Marinas 144b3901d54SCatalin Marinas void __show_regs(struct pt_regs *regs) 145b3901d54SCatalin Marinas { 146b3901d54SCatalin Marinas int i; 147b3901d54SCatalin Marinas 148a43cb95dSTejun Heo show_regs_print_info(KERN_DEFAULT); 149b3901d54SCatalin Marinas print_symbol("PC is at %s\n", instruction_pointer(regs)); 150b3901d54SCatalin Marinas print_symbol("LR is at %s\n", regs->regs[30]); 151b3901d54SCatalin Marinas printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", 152b3901d54SCatalin Marinas regs->pc, regs->regs[30], regs->pstate); 153b3901d54SCatalin Marinas printk("sp : %016llx\n", regs->sp); 154b3901d54SCatalin Marinas for (i = 29; i >= 0; i--) { 155b3901d54SCatalin Marinas printk("x%-2d: %016llx ", i, regs->regs[i]); 156b3901d54SCatalin Marinas if (i % 2 == 0) 157b3901d54SCatalin Marinas printk("\n"); 158b3901d54SCatalin Marinas } 159b3901d54SCatalin Marinas printk("\n"); 160b3901d54SCatalin Marinas } 161b3901d54SCatalin Marinas 162b3901d54SCatalin Marinas void show_regs(struct pt_regs * regs) 163b3901d54SCatalin Marinas { 164b3901d54SCatalin Marinas printk("\n"); 165b3901d54SCatalin Marinas __show_regs(regs); 166b3901d54SCatalin Marinas } 167b3901d54SCatalin Marinas 168b3901d54SCatalin Marinas /* 169b3901d54SCatalin Marinas * Free current thread data structures etc.. 170b3901d54SCatalin Marinas */ 171b3901d54SCatalin Marinas void exit_thread(void) 172b3901d54SCatalin Marinas { 173b3901d54SCatalin Marinas } 174b3901d54SCatalin Marinas 175b3901d54SCatalin Marinas void flush_thread(void) 176b3901d54SCatalin Marinas { 177b3901d54SCatalin Marinas fpsimd_flush_thread(); 178b3901d54SCatalin Marinas flush_ptrace_hw_breakpoint(current); 179b3901d54SCatalin Marinas } 180b3901d54SCatalin Marinas 181b3901d54SCatalin Marinas void release_thread(struct task_struct *dead_task) 182b3901d54SCatalin Marinas { 183b3901d54SCatalin Marinas } 184b3901d54SCatalin Marinas 185b3901d54SCatalin Marinas int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 186b3901d54SCatalin Marinas { 187b3901d54SCatalin Marinas fpsimd_save_state(¤t->thread.fpsimd_state); 188b3901d54SCatalin Marinas *dst = *src; 189b3901d54SCatalin Marinas return 0; 190b3901d54SCatalin Marinas } 191b3901d54SCatalin Marinas 192b3901d54SCatalin Marinas asmlinkage void ret_from_fork(void) asm("ret_from_fork"); 193b3901d54SCatalin Marinas 194b3901d54SCatalin Marinas int copy_thread(unsigned long clone_flags, unsigned long stack_start, 195afa86fc4SAl Viro unsigned long stk_sz, struct task_struct *p) 196b3901d54SCatalin Marinas { 197b3901d54SCatalin Marinas struct pt_regs *childregs = task_pt_regs(p); 198b3901d54SCatalin Marinas unsigned long tls = p->thread.tp_value; 199b3901d54SCatalin Marinas 200c34501d2SCatalin Marinas memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); 201c34501d2SCatalin Marinas 2029ac08002SAl Viro if (likely(!(p->flags & PF_KTHREAD))) { 2039ac08002SAl Viro *childregs = *current_pt_regs(); 204b3901d54SCatalin Marinas childregs->regs[0] = 0; 205c34501d2SCatalin Marinas if (is_compat_thread(task_thread_info(p))) { 206e0fd18ceSAl Viro if (stack_start) 207b3901d54SCatalin Marinas childregs->compat_sp = stack_start; 208c34501d2SCatalin Marinas } else { 209b3901d54SCatalin Marinas /* 210b3901d54SCatalin Marinas * Read the current TLS pointer from tpidr_el0 as it may be 211b3901d54SCatalin Marinas * out-of-sync with the saved value. 212b3901d54SCatalin Marinas */ 213b3901d54SCatalin Marinas asm("mrs %0, tpidr_el0" : "=r" (tls)); 214e0fd18ceSAl Viro if (stack_start) { 215e0fd18ceSAl Viro /* 16-byte aligned stack mandatory on AArch64 */ 216e0fd18ceSAl Viro if (stack_start & 15) 217e0fd18ceSAl Viro return -EINVAL; 218b3901d54SCatalin Marinas childregs->sp = stack_start; 219b3901d54SCatalin Marinas } 220e0fd18ceSAl Viro } 221c34501d2SCatalin Marinas /* 222c34501d2SCatalin Marinas * If a TLS pointer was passed to clone (4th argument), use it 223c34501d2SCatalin Marinas * for the new thread. 224c34501d2SCatalin Marinas */ 225b3901d54SCatalin Marinas if (clone_flags & CLONE_SETTLS) 2269ac08002SAl Viro tls = childregs->regs[3]; 227c34501d2SCatalin Marinas } else { 228c34501d2SCatalin Marinas memset(childregs, 0, sizeof(struct pt_regs)); 229c34501d2SCatalin Marinas childregs->pstate = PSR_MODE_EL1h; 230c34501d2SCatalin Marinas p->thread.cpu_context.x19 = stack_start; 231c34501d2SCatalin Marinas p->thread.cpu_context.x20 = stk_sz; 232c34501d2SCatalin Marinas } 233c34501d2SCatalin Marinas p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 234c34501d2SCatalin Marinas p->thread.cpu_context.sp = (unsigned long)childregs; 235b3901d54SCatalin Marinas p->thread.tp_value = tls; 236b3901d54SCatalin Marinas 237b3901d54SCatalin Marinas ptrace_hw_copy_thread(p); 238b3901d54SCatalin Marinas 239b3901d54SCatalin Marinas return 0; 240b3901d54SCatalin Marinas } 241b3901d54SCatalin Marinas 242b3901d54SCatalin Marinas static void tls_thread_switch(struct task_struct *next) 243b3901d54SCatalin Marinas { 244b3901d54SCatalin Marinas unsigned long tpidr, tpidrro; 245b3901d54SCatalin Marinas 246b3901d54SCatalin Marinas if (!is_compat_task()) { 247b3901d54SCatalin Marinas asm("mrs %0, tpidr_el0" : "=r" (tpidr)); 248b3901d54SCatalin Marinas current->thread.tp_value = tpidr; 249b3901d54SCatalin Marinas } 250b3901d54SCatalin Marinas 251b3901d54SCatalin Marinas if (is_compat_thread(task_thread_info(next))) { 252b3901d54SCatalin Marinas tpidr = 0; 253b3901d54SCatalin Marinas tpidrro = next->thread.tp_value; 254b3901d54SCatalin Marinas } else { 255b3901d54SCatalin Marinas tpidr = next->thread.tp_value; 256b3901d54SCatalin Marinas tpidrro = 0; 257b3901d54SCatalin Marinas } 258b3901d54SCatalin Marinas 259b3901d54SCatalin Marinas asm( 260b3901d54SCatalin Marinas " msr tpidr_el0, %0\n" 261b3901d54SCatalin Marinas " msr tpidrro_el0, %1" 262b3901d54SCatalin Marinas : : "r" (tpidr), "r" (tpidrro)); 263b3901d54SCatalin Marinas } 264b3901d54SCatalin Marinas 265b3901d54SCatalin Marinas /* 266b3901d54SCatalin Marinas * Thread switching. 267b3901d54SCatalin Marinas */ 268b3901d54SCatalin Marinas struct task_struct *__switch_to(struct task_struct *prev, 269b3901d54SCatalin Marinas struct task_struct *next) 270b3901d54SCatalin Marinas { 271b3901d54SCatalin Marinas struct task_struct *last; 272b3901d54SCatalin Marinas 273b3901d54SCatalin Marinas fpsimd_thread_switch(next); 274b3901d54SCatalin Marinas tls_thread_switch(next); 275b3901d54SCatalin Marinas hw_breakpoint_thread_switch(next); 2763325732fSChristopher Covington contextidr_thread_switch(next); 277b3901d54SCatalin Marinas 2785108c67cSCatalin Marinas /* 2795108c67cSCatalin Marinas * Complete any pending TLB or cache maintenance on this CPU in case 2805108c67cSCatalin Marinas * the thread migrates to a different CPU. 2815108c67cSCatalin Marinas */ 2825108c67cSCatalin Marinas dsb(); 283b3901d54SCatalin Marinas 284b3901d54SCatalin Marinas /* the actual thread switch */ 285b3901d54SCatalin Marinas last = cpu_switch_to(prev, next); 286b3901d54SCatalin Marinas 287b3901d54SCatalin Marinas return last; 288b3901d54SCatalin Marinas } 289b3901d54SCatalin Marinas 290b3901d54SCatalin Marinas unsigned long get_wchan(struct task_struct *p) 291b3901d54SCatalin Marinas { 292b3901d54SCatalin Marinas struct stackframe frame; 293b3901d54SCatalin Marinas int count = 0; 294b3901d54SCatalin Marinas if (!p || p == current || p->state == TASK_RUNNING) 295b3901d54SCatalin Marinas return 0; 296b3901d54SCatalin Marinas 297b3901d54SCatalin Marinas frame.fp = thread_saved_fp(p); 298b3901d54SCatalin Marinas frame.sp = thread_saved_sp(p); 299b3901d54SCatalin Marinas frame.pc = thread_saved_pc(p); 300b3901d54SCatalin Marinas do { 301b3901d54SCatalin Marinas int ret = unwind_frame(&frame); 302b3901d54SCatalin Marinas if (ret < 0) 303b3901d54SCatalin Marinas return 0; 304b3901d54SCatalin Marinas if (!in_sched_functions(frame.pc)) 305b3901d54SCatalin Marinas return frame.pc; 306b3901d54SCatalin Marinas } while (count ++ < 16); 307b3901d54SCatalin Marinas return 0; 308b3901d54SCatalin Marinas } 309b3901d54SCatalin Marinas 310b3901d54SCatalin Marinas unsigned long arch_align_stack(unsigned long sp) 311b3901d54SCatalin Marinas { 312b3901d54SCatalin Marinas if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 313b3901d54SCatalin Marinas sp -= get_random_int() & ~PAGE_MASK; 314b3901d54SCatalin Marinas return sp & ~0xf; 315b3901d54SCatalin Marinas } 316b3901d54SCatalin Marinas 317b3901d54SCatalin Marinas static unsigned long randomize_base(unsigned long base) 318b3901d54SCatalin Marinas { 319b3901d54SCatalin Marinas unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1; 320b3901d54SCatalin Marinas return randomize_range(base, range_end, 0) ? : base; 321b3901d54SCatalin Marinas } 322b3901d54SCatalin Marinas 323b3901d54SCatalin Marinas unsigned long arch_randomize_brk(struct mm_struct *mm) 324b3901d54SCatalin Marinas { 325b3901d54SCatalin Marinas return randomize_base(mm->brk); 326b3901d54SCatalin Marinas } 327b3901d54SCatalin Marinas 328b3901d54SCatalin Marinas unsigned long randomize_et_dyn(unsigned long base) 329b3901d54SCatalin Marinas { 330b3901d54SCatalin Marinas return randomize_base(base); 331b3901d54SCatalin Marinas } 332