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 84b3901d54SCatalin Marinas void (*pm_restart)(const char *cmd); 85b3901d54SCatalin Marinas EXPORT_SYMBOL_GPL(pm_restart); 86b3901d54SCatalin Marinas 87*0087298fSThomas Gleixner void arch_cpu_idle_prepare(void) 88*0087298fSThomas Gleixner { 89*0087298fSThomas Gleixner local_fiq_enable(); 90*0087298fSThomas Gleixner } 91b3901d54SCatalin Marinas 92b3901d54SCatalin Marinas /* 93b3901d54SCatalin Marinas * This is our default idle handler. 94b3901d54SCatalin Marinas */ 95*0087298fSThomas 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. */ 134b3901d54SCatalin Marinas if (pm_restart) 135b3901d54SCatalin Marinas pm_restart(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 148b3901d54SCatalin Marinas printk("CPU: %d %s (%s %.*s)\n", 149b3901d54SCatalin Marinas raw_smp_processor_id(), print_tainted(), 150b3901d54SCatalin Marinas init_utsname()->release, 151b3901d54SCatalin Marinas (int)strcspn(init_utsname()->version, " "), 152b3901d54SCatalin Marinas init_utsname()->version); 153b3901d54SCatalin Marinas print_symbol("PC is at %s\n", instruction_pointer(regs)); 154b3901d54SCatalin Marinas print_symbol("LR is at %s\n", regs->regs[30]); 155b3901d54SCatalin Marinas printk("pc : [<%016llx>] lr : [<%016llx>] pstate: %08llx\n", 156b3901d54SCatalin Marinas regs->pc, regs->regs[30], regs->pstate); 157b3901d54SCatalin Marinas printk("sp : %016llx\n", regs->sp); 158b3901d54SCatalin Marinas for (i = 29; i >= 0; i--) { 159b3901d54SCatalin Marinas printk("x%-2d: %016llx ", i, regs->regs[i]); 160b3901d54SCatalin Marinas if (i % 2 == 0) 161b3901d54SCatalin Marinas printk("\n"); 162b3901d54SCatalin Marinas } 163b3901d54SCatalin Marinas printk("\n"); 164b3901d54SCatalin Marinas } 165b3901d54SCatalin Marinas 166b3901d54SCatalin Marinas void show_regs(struct pt_regs * regs) 167b3901d54SCatalin Marinas { 168b3901d54SCatalin Marinas printk("\n"); 169b3901d54SCatalin Marinas printk("Pid: %d, comm: %20s\n", task_pid_nr(current), current->comm); 170b3901d54SCatalin Marinas __show_regs(regs); 171b3901d54SCatalin Marinas } 172b3901d54SCatalin Marinas 173b3901d54SCatalin Marinas /* 174b3901d54SCatalin Marinas * Free current thread data structures etc.. 175b3901d54SCatalin Marinas */ 176b3901d54SCatalin Marinas void exit_thread(void) 177b3901d54SCatalin Marinas { 178b3901d54SCatalin Marinas } 179b3901d54SCatalin Marinas 180b3901d54SCatalin Marinas void flush_thread(void) 181b3901d54SCatalin Marinas { 182b3901d54SCatalin Marinas fpsimd_flush_thread(); 183b3901d54SCatalin Marinas flush_ptrace_hw_breakpoint(current); 184b3901d54SCatalin Marinas } 185b3901d54SCatalin Marinas 186b3901d54SCatalin Marinas void release_thread(struct task_struct *dead_task) 187b3901d54SCatalin Marinas { 188b3901d54SCatalin Marinas } 189b3901d54SCatalin Marinas 190b3901d54SCatalin Marinas int arch_dup_task_struct(struct task_struct *dst, struct task_struct *src) 191b3901d54SCatalin Marinas { 192b3901d54SCatalin Marinas fpsimd_save_state(¤t->thread.fpsimd_state); 193b3901d54SCatalin Marinas *dst = *src; 194b3901d54SCatalin Marinas return 0; 195b3901d54SCatalin Marinas } 196b3901d54SCatalin Marinas 197b3901d54SCatalin Marinas asmlinkage void ret_from_fork(void) asm("ret_from_fork"); 198b3901d54SCatalin Marinas 199b3901d54SCatalin Marinas int copy_thread(unsigned long clone_flags, unsigned long stack_start, 200afa86fc4SAl Viro unsigned long stk_sz, struct task_struct *p) 201b3901d54SCatalin Marinas { 202b3901d54SCatalin Marinas struct pt_regs *childregs = task_pt_regs(p); 203b3901d54SCatalin Marinas unsigned long tls = p->thread.tp_value; 204b3901d54SCatalin Marinas 205c34501d2SCatalin Marinas memset(&p->thread.cpu_context, 0, sizeof(struct cpu_context)); 206c34501d2SCatalin Marinas 2079ac08002SAl Viro if (likely(!(p->flags & PF_KTHREAD))) { 2089ac08002SAl Viro *childregs = *current_pt_regs(); 209b3901d54SCatalin Marinas childregs->regs[0] = 0; 210c34501d2SCatalin Marinas if (is_compat_thread(task_thread_info(p))) { 211e0fd18ceSAl Viro if (stack_start) 212b3901d54SCatalin Marinas childregs->compat_sp = stack_start; 213c34501d2SCatalin Marinas } else { 214b3901d54SCatalin Marinas /* 215b3901d54SCatalin Marinas * Read the current TLS pointer from tpidr_el0 as it may be 216b3901d54SCatalin Marinas * out-of-sync with the saved value. 217b3901d54SCatalin Marinas */ 218b3901d54SCatalin Marinas asm("mrs %0, tpidr_el0" : "=r" (tls)); 219e0fd18ceSAl Viro if (stack_start) { 220e0fd18ceSAl Viro /* 16-byte aligned stack mandatory on AArch64 */ 221e0fd18ceSAl Viro if (stack_start & 15) 222e0fd18ceSAl Viro return -EINVAL; 223b3901d54SCatalin Marinas childregs->sp = stack_start; 224b3901d54SCatalin Marinas } 225e0fd18ceSAl Viro } 226c34501d2SCatalin Marinas /* 227c34501d2SCatalin Marinas * If a TLS pointer was passed to clone (4th argument), use it 228c34501d2SCatalin Marinas * for the new thread. 229c34501d2SCatalin Marinas */ 230b3901d54SCatalin Marinas if (clone_flags & CLONE_SETTLS) 2319ac08002SAl Viro tls = childregs->regs[3]; 232c34501d2SCatalin Marinas } else { 233c34501d2SCatalin Marinas memset(childregs, 0, sizeof(struct pt_regs)); 234c34501d2SCatalin Marinas childregs->pstate = PSR_MODE_EL1h; 235c34501d2SCatalin Marinas p->thread.cpu_context.x19 = stack_start; 236c34501d2SCatalin Marinas p->thread.cpu_context.x20 = stk_sz; 237c34501d2SCatalin Marinas } 238c34501d2SCatalin Marinas p->thread.cpu_context.pc = (unsigned long)ret_from_fork; 239c34501d2SCatalin Marinas p->thread.cpu_context.sp = (unsigned long)childregs; 240b3901d54SCatalin Marinas p->thread.tp_value = tls; 241b3901d54SCatalin Marinas 242b3901d54SCatalin Marinas ptrace_hw_copy_thread(p); 243b3901d54SCatalin Marinas 244b3901d54SCatalin Marinas return 0; 245b3901d54SCatalin Marinas } 246b3901d54SCatalin Marinas 247b3901d54SCatalin Marinas static void tls_thread_switch(struct task_struct *next) 248b3901d54SCatalin Marinas { 249b3901d54SCatalin Marinas unsigned long tpidr, tpidrro; 250b3901d54SCatalin Marinas 251b3901d54SCatalin Marinas if (!is_compat_task()) { 252b3901d54SCatalin Marinas asm("mrs %0, tpidr_el0" : "=r" (tpidr)); 253b3901d54SCatalin Marinas current->thread.tp_value = tpidr; 254b3901d54SCatalin Marinas } 255b3901d54SCatalin Marinas 256b3901d54SCatalin Marinas if (is_compat_thread(task_thread_info(next))) { 257b3901d54SCatalin Marinas tpidr = 0; 258b3901d54SCatalin Marinas tpidrro = next->thread.tp_value; 259b3901d54SCatalin Marinas } else { 260b3901d54SCatalin Marinas tpidr = next->thread.tp_value; 261b3901d54SCatalin Marinas tpidrro = 0; 262b3901d54SCatalin Marinas } 263b3901d54SCatalin Marinas 264b3901d54SCatalin Marinas asm( 265b3901d54SCatalin Marinas " msr tpidr_el0, %0\n" 266b3901d54SCatalin Marinas " msr tpidrro_el0, %1" 267b3901d54SCatalin Marinas : : "r" (tpidr), "r" (tpidrro)); 268b3901d54SCatalin Marinas } 269b3901d54SCatalin Marinas 270b3901d54SCatalin Marinas /* 271b3901d54SCatalin Marinas * Thread switching. 272b3901d54SCatalin Marinas */ 273b3901d54SCatalin Marinas struct task_struct *__switch_to(struct task_struct *prev, 274b3901d54SCatalin Marinas struct task_struct *next) 275b3901d54SCatalin Marinas { 276b3901d54SCatalin Marinas struct task_struct *last; 277b3901d54SCatalin Marinas 278b3901d54SCatalin Marinas fpsimd_thread_switch(next); 279b3901d54SCatalin Marinas tls_thread_switch(next); 280b3901d54SCatalin Marinas hw_breakpoint_thread_switch(next); 281b3901d54SCatalin Marinas 282b3901d54SCatalin Marinas /* the actual thread switch */ 283b3901d54SCatalin Marinas last = cpu_switch_to(prev, next); 284b3901d54SCatalin Marinas 285ec45d1cfSWill Deacon contextidr_thread_switch(next); 286b3901d54SCatalin Marinas return last; 287b3901d54SCatalin Marinas } 288b3901d54SCatalin Marinas 289b3901d54SCatalin Marinas unsigned long get_wchan(struct task_struct *p) 290b3901d54SCatalin Marinas { 291b3901d54SCatalin Marinas struct stackframe frame; 292b3901d54SCatalin Marinas int count = 0; 293b3901d54SCatalin Marinas if (!p || p == current || p->state == TASK_RUNNING) 294b3901d54SCatalin Marinas return 0; 295b3901d54SCatalin Marinas 296b3901d54SCatalin Marinas frame.fp = thread_saved_fp(p); 297b3901d54SCatalin Marinas frame.sp = thread_saved_sp(p); 298b3901d54SCatalin Marinas frame.pc = thread_saved_pc(p); 299b3901d54SCatalin Marinas do { 300b3901d54SCatalin Marinas int ret = unwind_frame(&frame); 301b3901d54SCatalin Marinas if (ret < 0) 302b3901d54SCatalin Marinas return 0; 303b3901d54SCatalin Marinas if (!in_sched_functions(frame.pc)) 304b3901d54SCatalin Marinas return frame.pc; 305b3901d54SCatalin Marinas } while (count ++ < 16); 306b3901d54SCatalin Marinas return 0; 307b3901d54SCatalin Marinas } 308b3901d54SCatalin Marinas 309b3901d54SCatalin Marinas unsigned long arch_align_stack(unsigned long sp) 310b3901d54SCatalin Marinas { 311b3901d54SCatalin Marinas if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space) 312b3901d54SCatalin Marinas sp -= get_random_int() & ~PAGE_MASK; 313b3901d54SCatalin Marinas return sp & ~0xf; 314b3901d54SCatalin Marinas } 315b3901d54SCatalin Marinas 316b3901d54SCatalin Marinas static unsigned long randomize_base(unsigned long base) 317b3901d54SCatalin Marinas { 318b3901d54SCatalin Marinas unsigned long range_end = base + (STACK_RND_MASK << PAGE_SHIFT) + 1; 319b3901d54SCatalin Marinas return randomize_range(base, range_end, 0) ? : base; 320b3901d54SCatalin Marinas } 321b3901d54SCatalin Marinas 322b3901d54SCatalin Marinas unsigned long arch_randomize_brk(struct mm_struct *mm) 323b3901d54SCatalin Marinas { 324b3901d54SCatalin Marinas return randomize_base(mm->brk); 325b3901d54SCatalin Marinas } 326b3901d54SCatalin Marinas 327b3901d54SCatalin Marinas unsigned long randomize_et_dyn(unsigned long base) 328b3901d54SCatalin Marinas { 329b3901d54SCatalin Marinas return randomize_base(base); 330b3901d54SCatalin Marinas } 331