114cf11afSPaul Mackerras /* 214cf11afSPaul Mackerras * Derived from "arch/i386/kernel/process.c" 314cf11afSPaul Mackerras * Copyright (C) 1995 Linus Torvalds 414cf11afSPaul Mackerras * 514cf11afSPaul Mackerras * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and 614cf11afSPaul Mackerras * Paul Mackerras (paulus@cs.anu.edu.au) 714cf11afSPaul Mackerras * 814cf11afSPaul Mackerras * PowerPC version 914cf11afSPaul Mackerras * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 1014cf11afSPaul Mackerras * 1114cf11afSPaul Mackerras * This program is free software; you can redistribute it and/or 1214cf11afSPaul Mackerras * modify it under the terms of the GNU General Public License 1314cf11afSPaul Mackerras * as published by the Free Software Foundation; either version 1414cf11afSPaul Mackerras * 2 of the License, or (at your option) any later version. 1514cf11afSPaul Mackerras */ 1614cf11afSPaul Mackerras 1714cf11afSPaul Mackerras #include <linux/config.h> 1814cf11afSPaul Mackerras #include <linux/errno.h> 1914cf11afSPaul Mackerras #include <linux/sched.h> 2014cf11afSPaul Mackerras #include <linux/kernel.h> 2114cf11afSPaul Mackerras #include <linux/mm.h> 2214cf11afSPaul Mackerras #include <linux/smp.h> 2314cf11afSPaul Mackerras #include <linux/smp_lock.h> 2414cf11afSPaul Mackerras #include <linux/stddef.h> 2514cf11afSPaul Mackerras #include <linux/unistd.h> 2614cf11afSPaul Mackerras #include <linux/ptrace.h> 2714cf11afSPaul Mackerras #include <linux/slab.h> 2814cf11afSPaul Mackerras #include <linux/user.h> 2914cf11afSPaul Mackerras #include <linux/elf.h> 3014cf11afSPaul Mackerras #include <linux/init.h> 3114cf11afSPaul Mackerras #include <linux/prctl.h> 3214cf11afSPaul Mackerras #include <linux/init_task.h> 3314cf11afSPaul Mackerras #include <linux/module.h> 3414cf11afSPaul Mackerras #include <linux/kallsyms.h> 3514cf11afSPaul Mackerras #include <linux/mqueue.h> 3614cf11afSPaul Mackerras #include <linux/hardirq.h> 3706d67d54SPaul Mackerras #include <linux/utsname.h> 3806d67d54SPaul Mackerras #include <linux/kprobes.h> 3914cf11afSPaul Mackerras 4014cf11afSPaul Mackerras #include <asm/pgtable.h> 4114cf11afSPaul Mackerras #include <asm/uaccess.h> 4214cf11afSPaul Mackerras #include <asm/system.h> 4314cf11afSPaul Mackerras #include <asm/io.h> 4414cf11afSPaul Mackerras #include <asm/processor.h> 4514cf11afSPaul Mackerras #include <asm/mmu.h> 4614cf11afSPaul Mackerras #include <asm/prom.h> 4776032de8SMichael Ellerman #include <asm/machdep.h> 48*c6622f63SPaul Mackerras #include <asm/time.h> 4906d67d54SPaul Mackerras #ifdef CONFIG_PPC64 5006d67d54SPaul Mackerras #include <asm/firmware.h> 5106d67d54SPaul Mackerras #endif 5214cf11afSPaul Mackerras 5314cf11afSPaul Mackerras extern unsigned long _get_SP(void); 5414cf11afSPaul Mackerras 5514cf11afSPaul Mackerras #ifndef CONFIG_SMP 5614cf11afSPaul Mackerras struct task_struct *last_task_used_math = NULL; 5714cf11afSPaul Mackerras struct task_struct *last_task_used_altivec = NULL; 5814cf11afSPaul Mackerras struct task_struct *last_task_used_spe = NULL; 5914cf11afSPaul Mackerras #endif 6014cf11afSPaul Mackerras 6114cf11afSPaul Mackerras /* 6214cf11afSPaul Mackerras * Make sure the floating-point register state in the 6314cf11afSPaul Mackerras * the thread_struct is up to date for task tsk. 6414cf11afSPaul Mackerras */ 6514cf11afSPaul Mackerras void flush_fp_to_thread(struct task_struct *tsk) 6614cf11afSPaul Mackerras { 6714cf11afSPaul Mackerras if (tsk->thread.regs) { 6814cf11afSPaul Mackerras /* 6914cf11afSPaul Mackerras * We need to disable preemption here because if we didn't, 7014cf11afSPaul Mackerras * another process could get scheduled after the regs->msr 7114cf11afSPaul Mackerras * test but before we have finished saving the FP registers 7214cf11afSPaul Mackerras * to the thread_struct. That process could take over the 7314cf11afSPaul Mackerras * FPU, and then when we get scheduled again we would store 7414cf11afSPaul Mackerras * bogus values for the remaining FP registers. 7514cf11afSPaul Mackerras */ 7614cf11afSPaul Mackerras preempt_disable(); 7714cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_FP) { 7814cf11afSPaul Mackerras #ifdef CONFIG_SMP 7914cf11afSPaul Mackerras /* 8014cf11afSPaul Mackerras * This should only ever be called for current or 8114cf11afSPaul Mackerras * for a stopped child process. Since we save away 8214cf11afSPaul Mackerras * the FP register state on context switch on SMP, 8314cf11afSPaul Mackerras * there is something wrong if a stopped child appears 8414cf11afSPaul Mackerras * to still have its FP state in the CPU registers. 8514cf11afSPaul Mackerras */ 8614cf11afSPaul Mackerras BUG_ON(tsk != current); 8714cf11afSPaul Mackerras #endif 8814cf11afSPaul Mackerras giveup_fpu(current); 8914cf11afSPaul Mackerras } 9014cf11afSPaul Mackerras preempt_enable(); 9114cf11afSPaul Mackerras } 9214cf11afSPaul Mackerras } 9314cf11afSPaul Mackerras 9414cf11afSPaul Mackerras void enable_kernel_fp(void) 9514cf11afSPaul Mackerras { 9614cf11afSPaul Mackerras WARN_ON(preemptible()); 9714cf11afSPaul Mackerras 9814cf11afSPaul Mackerras #ifdef CONFIG_SMP 9914cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) 10014cf11afSPaul Mackerras giveup_fpu(current); 10114cf11afSPaul Mackerras else 10214cf11afSPaul Mackerras giveup_fpu(NULL); /* just enables FP for kernel */ 10314cf11afSPaul Mackerras #else 10414cf11afSPaul Mackerras giveup_fpu(last_task_used_math); 10514cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 10614cf11afSPaul Mackerras } 10714cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_fp); 10814cf11afSPaul Mackerras 10914cf11afSPaul Mackerras int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) 11014cf11afSPaul Mackerras { 11114cf11afSPaul Mackerras if (!tsk->thread.regs) 11214cf11afSPaul Mackerras return 0; 11314cf11afSPaul Mackerras flush_fp_to_thread(current); 11414cf11afSPaul Mackerras 11514cf11afSPaul Mackerras memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); 11614cf11afSPaul Mackerras 11714cf11afSPaul Mackerras return 1; 11814cf11afSPaul Mackerras } 11914cf11afSPaul Mackerras 12014cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 12114cf11afSPaul Mackerras void enable_kernel_altivec(void) 12214cf11afSPaul Mackerras { 12314cf11afSPaul Mackerras WARN_ON(preemptible()); 12414cf11afSPaul Mackerras 12514cf11afSPaul Mackerras #ifdef CONFIG_SMP 12614cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) 12714cf11afSPaul Mackerras giveup_altivec(current); 12814cf11afSPaul Mackerras else 12914cf11afSPaul Mackerras giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ 13014cf11afSPaul Mackerras #else 13114cf11afSPaul Mackerras giveup_altivec(last_task_used_altivec); 13214cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 13314cf11afSPaul Mackerras } 13414cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_altivec); 13514cf11afSPaul Mackerras 13614cf11afSPaul Mackerras /* 13714cf11afSPaul Mackerras * Make sure the VMX/Altivec register state in the 13814cf11afSPaul Mackerras * the thread_struct is up to date for task tsk. 13914cf11afSPaul Mackerras */ 14014cf11afSPaul Mackerras void flush_altivec_to_thread(struct task_struct *tsk) 14114cf11afSPaul Mackerras { 14214cf11afSPaul Mackerras if (tsk->thread.regs) { 14314cf11afSPaul Mackerras preempt_disable(); 14414cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_VEC) { 14514cf11afSPaul Mackerras #ifdef CONFIG_SMP 14614cf11afSPaul Mackerras BUG_ON(tsk != current); 14714cf11afSPaul Mackerras #endif 14814cf11afSPaul Mackerras giveup_altivec(current); 14914cf11afSPaul Mackerras } 15014cf11afSPaul Mackerras preempt_enable(); 15114cf11afSPaul Mackerras } 15214cf11afSPaul Mackerras } 15314cf11afSPaul Mackerras 15414cf11afSPaul Mackerras int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) 15514cf11afSPaul Mackerras { 15614cf11afSPaul Mackerras flush_altivec_to_thread(current); 15714cf11afSPaul Mackerras memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); 15814cf11afSPaul Mackerras return 1; 15914cf11afSPaul Mackerras } 16014cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 16114cf11afSPaul Mackerras 16214cf11afSPaul Mackerras #ifdef CONFIG_SPE 16314cf11afSPaul Mackerras 16414cf11afSPaul Mackerras void enable_kernel_spe(void) 16514cf11afSPaul Mackerras { 16614cf11afSPaul Mackerras WARN_ON(preemptible()); 16714cf11afSPaul Mackerras 16814cf11afSPaul Mackerras #ifdef CONFIG_SMP 16914cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) 17014cf11afSPaul Mackerras giveup_spe(current); 17114cf11afSPaul Mackerras else 17214cf11afSPaul Mackerras giveup_spe(NULL); /* just enable SPE for kernel - force */ 17314cf11afSPaul Mackerras #else 17414cf11afSPaul Mackerras giveup_spe(last_task_used_spe); 17514cf11afSPaul Mackerras #endif /* __SMP __ */ 17614cf11afSPaul Mackerras } 17714cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_spe); 17814cf11afSPaul Mackerras 17914cf11afSPaul Mackerras void flush_spe_to_thread(struct task_struct *tsk) 18014cf11afSPaul Mackerras { 18114cf11afSPaul Mackerras if (tsk->thread.regs) { 18214cf11afSPaul Mackerras preempt_disable(); 18314cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_SPE) { 18414cf11afSPaul Mackerras #ifdef CONFIG_SMP 18514cf11afSPaul Mackerras BUG_ON(tsk != current); 18614cf11afSPaul Mackerras #endif 18714cf11afSPaul Mackerras giveup_spe(current); 18814cf11afSPaul Mackerras } 18914cf11afSPaul Mackerras preempt_enable(); 19014cf11afSPaul Mackerras } 19114cf11afSPaul Mackerras } 19214cf11afSPaul Mackerras 19314cf11afSPaul Mackerras int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) 19414cf11afSPaul Mackerras { 19514cf11afSPaul Mackerras flush_spe_to_thread(current); 19614cf11afSPaul Mackerras /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ 19714cf11afSPaul Mackerras memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); 19814cf11afSPaul Mackerras return 1; 19914cf11afSPaul Mackerras } 20014cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 20114cf11afSPaul Mackerras 2025388fb10SPaul Mackerras #ifndef CONFIG_SMP 20348abec07SPaul Mackerras /* 20448abec07SPaul Mackerras * If we are doing lazy switching of CPU state (FP, altivec or SPE), 20548abec07SPaul Mackerras * and the current task has some state, discard it. 20648abec07SPaul Mackerras */ 2075388fb10SPaul Mackerras void discard_lazy_cpu_state(void) 20848abec07SPaul Mackerras { 20948abec07SPaul Mackerras preempt_disable(); 21048abec07SPaul Mackerras if (last_task_used_math == current) 21148abec07SPaul Mackerras last_task_used_math = NULL; 21248abec07SPaul Mackerras #ifdef CONFIG_ALTIVEC 21348abec07SPaul Mackerras if (last_task_used_altivec == current) 21448abec07SPaul Mackerras last_task_used_altivec = NULL; 21548abec07SPaul Mackerras #endif /* CONFIG_ALTIVEC */ 21648abec07SPaul Mackerras #ifdef CONFIG_SPE 21748abec07SPaul Mackerras if (last_task_used_spe == current) 21848abec07SPaul Mackerras last_task_used_spe = NULL; 21948abec07SPaul Mackerras #endif 22048abec07SPaul Mackerras preempt_enable(); 22148abec07SPaul Mackerras } 2225388fb10SPaul Mackerras #endif /* CONFIG_SMP */ 22348abec07SPaul Mackerras 224624cee31SPaul Mackerras #ifdef CONFIG_PPC_MERGE /* XXX for now */ 22514cf11afSPaul Mackerras int set_dabr(unsigned long dabr) 22614cf11afSPaul Mackerras { 227cab0af98SMichael Ellerman if (ppc_md.set_dabr) 228cab0af98SMichael Ellerman return ppc_md.set_dabr(dabr); 22914cf11afSPaul Mackerras 230cab0af98SMichael Ellerman mtspr(SPRN_DABR, dabr); 231cab0af98SMichael Ellerman return 0; 23214cf11afSPaul Mackerras } 233624cee31SPaul Mackerras #endif 23414cf11afSPaul Mackerras 23506d67d54SPaul Mackerras #ifdef CONFIG_PPC64 23606d67d54SPaul Mackerras DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); 23714cf11afSPaul Mackerras static DEFINE_PER_CPU(unsigned long, current_dabr); 23806d67d54SPaul Mackerras #endif 23914cf11afSPaul Mackerras 24014cf11afSPaul Mackerras struct task_struct *__switch_to(struct task_struct *prev, 24114cf11afSPaul Mackerras struct task_struct *new) 24214cf11afSPaul Mackerras { 24314cf11afSPaul Mackerras struct thread_struct *new_thread, *old_thread; 24414cf11afSPaul Mackerras unsigned long flags; 24514cf11afSPaul Mackerras struct task_struct *last; 24614cf11afSPaul Mackerras 24714cf11afSPaul Mackerras #ifdef CONFIG_SMP 24814cf11afSPaul Mackerras /* avoid complexity of lazy save/restore of fpu 24914cf11afSPaul Mackerras * by just saving it every time we switch out if 25014cf11afSPaul Mackerras * this task used the fpu during the last quantum. 25114cf11afSPaul Mackerras * 25214cf11afSPaul Mackerras * If it tries to use the fpu again, it'll trap and 25314cf11afSPaul Mackerras * reload its fp regs. So we don't have to do a restore 25414cf11afSPaul Mackerras * every switch, just a save. 25514cf11afSPaul Mackerras * -- Cort 25614cf11afSPaul Mackerras */ 25714cf11afSPaul Mackerras if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) 25814cf11afSPaul Mackerras giveup_fpu(prev); 25914cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 26014cf11afSPaul Mackerras /* 26114cf11afSPaul Mackerras * If the previous thread used altivec in the last quantum 26214cf11afSPaul Mackerras * (thus changing altivec regs) then save them. 26314cf11afSPaul Mackerras * We used to check the VRSAVE register but not all apps 26414cf11afSPaul Mackerras * set it, so we don't rely on it now (and in fact we need 26514cf11afSPaul Mackerras * to save & restore VSCR even if VRSAVE == 0). -- paulus 26614cf11afSPaul Mackerras * 26714cf11afSPaul Mackerras * On SMP we always save/restore altivec regs just to avoid the 26814cf11afSPaul Mackerras * complexity of changing processors. 26914cf11afSPaul Mackerras * -- Cort 27014cf11afSPaul Mackerras */ 27114cf11afSPaul Mackerras if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) 27214cf11afSPaul Mackerras giveup_altivec(prev); 27314cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 27414cf11afSPaul Mackerras #ifdef CONFIG_SPE 27514cf11afSPaul Mackerras /* 27614cf11afSPaul Mackerras * If the previous thread used spe in the last quantum 27714cf11afSPaul Mackerras * (thus changing spe regs) then save them. 27814cf11afSPaul Mackerras * 27914cf11afSPaul Mackerras * On SMP we always save/restore spe regs just to avoid the 28014cf11afSPaul Mackerras * complexity of changing processors. 28114cf11afSPaul Mackerras */ 28214cf11afSPaul Mackerras if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) 28314cf11afSPaul Mackerras giveup_spe(prev); 284c0c0d996SPaul Mackerras #endif /* CONFIG_SPE */ 285c0c0d996SPaul Mackerras 286c0c0d996SPaul Mackerras #else /* CONFIG_SMP */ 287c0c0d996SPaul Mackerras #ifdef CONFIG_ALTIVEC 288c0c0d996SPaul Mackerras /* Avoid the trap. On smp this this never happens since 289c0c0d996SPaul Mackerras * we don't set last_task_used_altivec -- Cort 290c0c0d996SPaul Mackerras */ 291c0c0d996SPaul Mackerras if (new->thread.regs && last_task_used_altivec == new) 292c0c0d996SPaul Mackerras new->thread.regs->msr |= MSR_VEC; 293c0c0d996SPaul Mackerras #endif /* CONFIG_ALTIVEC */ 294c0c0d996SPaul Mackerras #ifdef CONFIG_SPE 29514cf11afSPaul Mackerras /* Avoid the trap. On smp this this never happens since 29614cf11afSPaul Mackerras * we don't set last_task_used_spe 29714cf11afSPaul Mackerras */ 29814cf11afSPaul Mackerras if (new->thread.regs && last_task_used_spe == new) 29914cf11afSPaul Mackerras new->thread.regs->msr |= MSR_SPE; 30014cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 301c0c0d996SPaul Mackerras 30214cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 30314cf11afSPaul Mackerras 30414cf11afSPaul Mackerras #ifdef CONFIG_PPC64 /* for now */ 30514cf11afSPaul Mackerras if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { 30614cf11afSPaul Mackerras set_dabr(new->thread.dabr); 30714cf11afSPaul Mackerras __get_cpu_var(current_dabr) = new->thread.dabr; 30814cf11afSPaul Mackerras } 30906d67d54SPaul Mackerras 31006d67d54SPaul Mackerras flush_tlb_pending(); 31114cf11afSPaul Mackerras #endif 31214cf11afSPaul Mackerras 31314cf11afSPaul Mackerras new_thread = &new->thread; 31414cf11afSPaul Mackerras old_thread = ¤t->thread; 31506d67d54SPaul Mackerras 31606d67d54SPaul Mackerras #ifdef CONFIG_PPC64 31706d67d54SPaul Mackerras /* 31806d67d54SPaul Mackerras * Collect processor utilization data per process 31906d67d54SPaul Mackerras */ 32006d67d54SPaul Mackerras if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 32106d67d54SPaul Mackerras struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 32206d67d54SPaul Mackerras long unsigned start_tb, current_tb; 32306d67d54SPaul Mackerras start_tb = old_thread->start_tb; 32406d67d54SPaul Mackerras cu->current_tb = current_tb = mfspr(SPRN_PURR); 32506d67d54SPaul Mackerras old_thread->accum_tb += (current_tb - start_tb); 32606d67d54SPaul Mackerras new_thread->start_tb = current_tb; 32706d67d54SPaul Mackerras } 32806d67d54SPaul Mackerras #endif 32906d67d54SPaul Mackerras 33014cf11afSPaul Mackerras local_irq_save(flags); 331*c6622f63SPaul Mackerras 332*c6622f63SPaul Mackerras account_system_vtime(current); 333*c6622f63SPaul Mackerras account_process_vtime(current); 334*c6622f63SPaul Mackerras calculate_steal_time(); 335*c6622f63SPaul Mackerras 33614cf11afSPaul Mackerras last = _switch(old_thread, new_thread); 33714cf11afSPaul Mackerras 33814cf11afSPaul Mackerras local_irq_restore(flags); 33914cf11afSPaul Mackerras 34014cf11afSPaul Mackerras return last; 34114cf11afSPaul Mackerras } 34214cf11afSPaul Mackerras 34306d67d54SPaul Mackerras static int instructions_to_print = 16; 34406d67d54SPaul Mackerras 34506d67d54SPaul Mackerras #ifdef CONFIG_PPC64 34606d67d54SPaul Mackerras #define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \ 34706d67d54SPaul Mackerras (REGION_ID(pc) != VMALLOC_REGION_ID)) 34806d67d54SPaul Mackerras #else 34906d67d54SPaul Mackerras #define BAD_PC(pc) ((pc) < KERNELBASE) 35006d67d54SPaul Mackerras #endif 35106d67d54SPaul Mackerras 35206d67d54SPaul Mackerras static void show_instructions(struct pt_regs *regs) 35306d67d54SPaul Mackerras { 35406d67d54SPaul Mackerras int i; 35506d67d54SPaul Mackerras unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 * 35606d67d54SPaul Mackerras sizeof(int)); 35706d67d54SPaul Mackerras 35806d67d54SPaul Mackerras printk("Instruction dump:"); 35906d67d54SPaul Mackerras 36006d67d54SPaul Mackerras for (i = 0; i < instructions_to_print; i++) { 36106d67d54SPaul Mackerras int instr; 36206d67d54SPaul Mackerras 36306d67d54SPaul Mackerras if (!(i % 8)) 36406d67d54SPaul Mackerras printk("\n"); 36506d67d54SPaul Mackerras 36606d67d54SPaul Mackerras if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) { 36706d67d54SPaul Mackerras printk("XXXXXXXX "); 36806d67d54SPaul Mackerras } else { 36906d67d54SPaul Mackerras if (regs->nip == pc) 37006d67d54SPaul Mackerras printk("<%08x> ", instr); 37106d67d54SPaul Mackerras else 37206d67d54SPaul Mackerras printk("%08x ", instr); 37306d67d54SPaul Mackerras } 37406d67d54SPaul Mackerras 37506d67d54SPaul Mackerras pc += sizeof(int); 37606d67d54SPaul Mackerras } 37706d67d54SPaul Mackerras 37806d67d54SPaul Mackerras printk("\n"); 37906d67d54SPaul Mackerras } 38006d67d54SPaul Mackerras 38106d67d54SPaul Mackerras static struct regbit { 38206d67d54SPaul Mackerras unsigned long bit; 38306d67d54SPaul Mackerras const char *name; 38406d67d54SPaul Mackerras } msr_bits[] = { 38506d67d54SPaul Mackerras {MSR_EE, "EE"}, 38606d67d54SPaul Mackerras {MSR_PR, "PR"}, 38706d67d54SPaul Mackerras {MSR_FP, "FP"}, 38806d67d54SPaul Mackerras {MSR_ME, "ME"}, 38906d67d54SPaul Mackerras {MSR_IR, "IR"}, 39006d67d54SPaul Mackerras {MSR_DR, "DR"}, 39106d67d54SPaul Mackerras {0, NULL} 39206d67d54SPaul Mackerras }; 39306d67d54SPaul Mackerras 39406d67d54SPaul Mackerras static void printbits(unsigned long val, struct regbit *bits) 39506d67d54SPaul Mackerras { 39606d67d54SPaul Mackerras const char *sep = ""; 39706d67d54SPaul Mackerras 39806d67d54SPaul Mackerras printk("<"); 39906d67d54SPaul Mackerras for (; bits->bit; ++bits) 40006d67d54SPaul Mackerras if (val & bits->bit) { 40106d67d54SPaul Mackerras printk("%s%s", sep, bits->name); 40206d67d54SPaul Mackerras sep = ","; 40306d67d54SPaul Mackerras } 40406d67d54SPaul Mackerras printk(">"); 40506d67d54SPaul Mackerras } 40606d67d54SPaul Mackerras 40706d67d54SPaul Mackerras #ifdef CONFIG_PPC64 40806d67d54SPaul Mackerras #define REG "%016lX" 40906d67d54SPaul Mackerras #define REGS_PER_LINE 4 41006d67d54SPaul Mackerras #define LAST_VOLATILE 13 41106d67d54SPaul Mackerras #else 41206d67d54SPaul Mackerras #define REG "%08lX" 41306d67d54SPaul Mackerras #define REGS_PER_LINE 8 41406d67d54SPaul Mackerras #define LAST_VOLATILE 12 41506d67d54SPaul Mackerras #endif 41606d67d54SPaul Mackerras 41714cf11afSPaul Mackerras void show_regs(struct pt_regs * regs) 41814cf11afSPaul Mackerras { 41914cf11afSPaul Mackerras int i, trap; 42014cf11afSPaul Mackerras 42106d67d54SPaul Mackerras printk("NIP: "REG" LR: "REG" CTR: "REG"\n", 42206d67d54SPaul Mackerras regs->nip, regs->link, regs->ctr); 42306d67d54SPaul Mackerras printk("REGS: %p TRAP: %04lx %s (%s)\n", 42406d67d54SPaul Mackerras regs, regs->trap, print_tainted(), system_utsname.release); 42506d67d54SPaul Mackerras printk("MSR: "REG" ", regs->msr); 42606d67d54SPaul Mackerras printbits(regs->msr, msr_bits); 42706d67d54SPaul Mackerras printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer); 42814cf11afSPaul Mackerras trap = TRAP(regs); 42914cf11afSPaul Mackerras if (trap == 0x300 || trap == 0x600) 43006d67d54SPaul Mackerras printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); 43106d67d54SPaul Mackerras printk("TASK = %p[%d] '%s' THREAD: %p", 432b5e2fc1cSAl Viro current, current->pid, current->comm, task_thread_info(current)); 43314cf11afSPaul Mackerras 43414cf11afSPaul Mackerras #ifdef CONFIG_SMP 43514cf11afSPaul Mackerras printk(" CPU: %d", smp_processor_id()); 43614cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 43714cf11afSPaul Mackerras 43814cf11afSPaul Mackerras for (i = 0; i < 32; i++) { 43906d67d54SPaul Mackerras if ((i % REGS_PER_LINE) == 0) 44014cf11afSPaul Mackerras printk("\n" KERN_INFO "GPR%02d: ", i); 44106d67d54SPaul Mackerras printk(REG " ", regs->gpr[i]); 44206d67d54SPaul Mackerras if (i == LAST_VOLATILE && !FULL_REGS(regs)) 44314cf11afSPaul Mackerras break; 44414cf11afSPaul Mackerras } 44514cf11afSPaul Mackerras printk("\n"); 44614cf11afSPaul Mackerras #ifdef CONFIG_KALLSYMS 44714cf11afSPaul Mackerras /* 44814cf11afSPaul Mackerras * Lookup NIP late so we have the best change of getting the 44914cf11afSPaul Mackerras * above info out without failing 45014cf11afSPaul Mackerras */ 45106d67d54SPaul Mackerras printk("NIP ["REG"] ", regs->nip); 45214cf11afSPaul Mackerras print_symbol("%s\n", regs->nip); 45306d67d54SPaul Mackerras printk("LR ["REG"] ", regs->link); 45414cf11afSPaul Mackerras print_symbol("%s\n", regs->link); 45514cf11afSPaul Mackerras #endif 45614cf11afSPaul Mackerras show_stack(current, (unsigned long *) regs->gpr[1]); 45706d67d54SPaul Mackerras if (!user_mode(regs)) 45806d67d54SPaul Mackerras show_instructions(regs); 45914cf11afSPaul Mackerras } 46014cf11afSPaul Mackerras 46114cf11afSPaul Mackerras void exit_thread(void) 46214cf11afSPaul Mackerras { 46306d67d54SPaul Mackerras kprobe_flush_task(current); 46448abec07SPaul Mackerras discard_lazy_cpu_state(); 46514cf11afSPaul Mackerras } 46614cf11afSPaul Mackerras 46714cf11afSPaul Mackerras void flush_thread(void) 46814cf11afSPaul Mackerras { 46906d67d54SPaul Mackerras #ifdef CONFIG_PPC64 47006d67d54SPaul Mackerras struct thread_info *t = current_thread_info(); 47106d67d54SPaul Mackerras 47206d67d54SPaul Mackerras if (t->flags & _TIF_ABI_PENDING) 47306d67d54SPaul Mackerras t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); 47406d67d54SPaul Mackerras #endif 47506d67d54SPaul Mackerras 47648abec07SPaul Mackerras discard_lazy_cpu_state(); 47714cf11afSPaul Mackerras 47814cf11afSPaul Mackerras #ifdef CONFIG_PPC64 /* for now */ 47914cf11afSPaul Mackerras if (current->thread.dabr) { 48014cf11afSPaul Mackerras current->thread.dabr = 0; 48114cf11afSPaul Mackerras set_dabr(0); 48214cf11afSPaul Mackerras } 48314cf11afSPaul Mackerras #endif 48414cf11afSPaul Mackerras } 48514cf11afSPaul Mackerras 48614cf11afSPaul Mackerras void 48714cf11afSPaul Mackerras release_thread(struct task_struct *t) 48814cf11afSPaul Mackerras { 48914cf11afSPaul Mackerras } 49014cf11afSPaul Mackerras 49114cf11afSPaul Mackerras /* 49214cf11afSPaul Mackerras * This gets called before we allocate a new thread and copy 49314cf11afSPaul Mackerras * the current task into it. 49414cf11afSPaul Mackerras */ 49514cf11afSPaul Mackerras void prepare_to_copy(struct task_struct *tsk) 49614cf11afSPaul Mackerras { 49714cf11afSPaul Mackerras flush_fp_to_thread(current); 49814cf11afSPaul Mackerras flush_altivec_to_thread(current); 49914cf11afSPaul Mackerras flush_spe_to_thread(current); 50014cf11afSPaul Mackerras } 50114cf11afSPaul Mackerras 50214cf11afSPaul Mackerras /* 50314cf11afSPaul Mackerras * Copy a thread.. 50414cf11afSPaul Mackerras */ 50506d67d54SPaul Mackerras int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, 50606d67d54SPaul Mackerras unsigned long unused, struct task_struct *p, 50706d67d54SPaul Mackerras struct pt_regs *regs) 50814cf11afSPaul Mackerras { 50914cf11afSPaul Mackerras struct pt_regs *childregs, *kregs; 51014cf11afSPaul Mackerras extern void ret_from_fork(void); 5110cec6fd1SAl Viro unsigned long sp = (unsigned long)task_stack_page(p) + THREAD_SIZE; 51214cf11afSPaul Mackerras 51314cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 51414cf11afSPaul Mackerras /* Copy registers */ 51514cf11afSPaul Mackerras sp -= sizeof(struct pt_regs); 51614cf11afSPaul Mackerras childregs = (struct pt_regs *) sp; 51714cf11afSPaul Mackerras *childregs = *regs; 51814cf11afSPaul Mackerras if ((childregs->msr & MSR_PR) == 0) { 51914cf11afSPaul Mackerras /* for kernel thread, set `current' and stackptr in new task */ 52014cf11afSPaul Mackerras childregs->gpr[1] = sp + sizeof(struct pt_regs); 52106d67d54SPaul Mackerras #ifdef CONFIG_PPC32 52214cf11afSPaul Mackerras childregs->gpr[2] = (unsigned long) p; 52306d67d54SPaul Mackerras #else 524b5e2fc1cSAl Viro clear_tsk_thread_flag(p, TIF_32BIT); 52506d67d54SPaul Mackerras #endif 52614cf11afSPaul Mackerras p->thread.regs = NULL; /* no user register state */ 52714cf11afSPaul Mackerras } else { 52814cf11afSPaul Mackerras childregs->gpr[1] = usp; 52914cf11afSPaul Mackerras p->thread.regs = childregs; 53006d67d54SPaul Mackerras if (clone_flags & CLONE_SETTLS) { 53106d67d54SPaul Mackerras #ifdef CONFIG_PPC64 53206d67d54SPaul Mackerras if (!test_thread_flag(TIF_32BIT)) 53306d67d54SPaul Mackerras childregs->gpr[13] = childregs->gpr[6]; 53406d67d54SPaul Mackerras else 53506d67d54SPaul Mackerras #endif 53614cf11afSPaul Mackerras childregs->gpr[2] = childregs->gpr[6]; 53714cf11afSPaul Mackerras } 53806d67d54SPaul Mackerras } 53914cf11afSPaul Mackerras childregs->gpr[3] = 0; /* Result from fork() */ 54014cf11afSPaul Mackerras sp -= STACK_FRAME_OVERHEAD; 54114cf11afSPaul Mackerras 54214cf11afSPaul Mackerras /* 54314cf11afSPaul Mackerras * The way this works is that at some point in the future 54414cf11afSPaul Mackerras * some task will call _switch to switch to the new task. 54514cf11afSPaul Mackerras * That will pop off the stack frame created below and start 54614cf11afSPaul Mackerras * the new task running at ret_from_fork. The new task will 54714cf11afSPaul Mackerras * do some house keeping and then return from the fork or clone 54814cf11afSPaul Mackerras * system call, using the stack frame created above. 54914cf11afSPaul Mackerras */ 55014cf11afSPaul Mackerras sp -= sizeof(struct pt_regs); 55114cf11afSPaul Mackerras kregs = (struct pt_regs *) sp; 55214cf11afSPaul Mackerras sp -= STACK_FRAME_OVERHEAD; 55314cf11afSPaul Mackerras p->thread.ksp = sp; 55414cf11afSPaul Mackerras 55506d67d54SPaul Mackerras #ifdef CONFIG_PPC64 55606d67d54SPaul Mackerras if (cpu_has_feature(CPU_FTR_SLB)) { 55706d67d54SPaul Mackerras unsigned long sp_vsid = get_kernel_vsid(sp); 5583c726f8dSBenjamin Herrenschmidt unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp; 55906d67d54SPaul Mackerras 56006d67d54SPaul Mackerras sp_vsid <<= SLB_VSID_SHIFT; 5613c726f8dSBenjamin Herrenschmidt sp_vsid |= SLB_VSID_KERNEL | llp; 56206d67d54SPaul Mackerras p->thread.ksp_vsid = sp_vsid; 56306d67d54SPaul Mackerras } 56406d67d54SPaul Mackerras 56506d67d54SPaul Mackerras /* 56606d67d54SPaul Mackerras * The PPC64 ABI makes use of a TOC to contain function 56706d67d54SPaul Mackerras * pointers. The function (ret_from_except) is actually a pointer 56806d67d54SPaul Mackerras * to the TOC entry. The first entry is a pointer to the actual 56906d67d54SPaul Mackerras * function. 57006d67d54SPaul Mackerras */ 57106d67d54SPaul Mackerras kregs->nip = *((unsigned long *)ret_from_fork); 57206d67d54SPaul Mackerras #else 57306d67d54SPaul Mackerras kregs->nip = (unsigned long)ret_from_fork; 57414cf11afSPaul Mackerras p->thread.last_syscall = -1; 57506d67d54SPaul Mackerras #endif 57614cf11afSPaul Mackerras 57714cf11afSPaul Mackerras return 0; 57814cf11afSPaul Mackerras } 57914cf11afSPaul Mackerras 58014cf11afSPaul Mackerras /* 58114cf11afSPaul Mackerras * Set up a thread for executing a new program 58214cf11afSPaul Mackerras */ 58306d67d54SPaul Mackerras void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) 58414cf11afSPaul Mackerras { 58590eac727SMichael Ellerman #ifdef CONFIG_PPC64 58690eac727SMichael Ellerman unsigned long load_addr = regs->gpr[2]; /* saved by ELF_PLAT_INIT */ 58790eac727SMichael Ellerman #endif 58890eac727SMichael Ellerman 58914cf11afSPaul Mackerras set_fs(USER_DS); 59006d67d54SPaul Mackerras 59106d67d54SPaul Mackerras /* 59206d67d54SPaul Mackerras * If we exec out of a kernel thread then thread.regs will not be 59306d67d54SPaul Mackerras * set. Do it now. 59406d67d54SPaul Mackerras */ 59506d67d54SPaul Mackerras if (!current->thread.regs) { 5960cec6fd1SAl Viro struct pt_regs *regs = task_stack_page(current) + THREAD_SIZE; 5970cec6fd1SAl Viro current->thread.regs = regs - 1; 59806d67d54SPaul Mackerras } 59906d67d54SPaul Mackerras 60014cf11afSPaul Mackerras memset(regs->gpr, 0, sizeof(regs->gpr)); 60114cf11afSPaul Mackerras regs->ctr = 0; 60214cf11afSPaul Mackerras regs->link = 0; 60314cf11afSPaul Mackerras regs->xer = 0; 60414cf11afSPaul Mackerras regs->ccr = 0; 60514cf11afSPaul Mackerras regs->gpr[1] = sp; 60606d67d54SPaul Mackerras 60706d67d54SPaul Mackerras #ifdef CONFIG_PPC32 60806d67d54SPaul Mackerras regs->mq = 0; 60906d67d54SPaul Mackerras regs->nip = start; 61014cf11afSPaul Mackerras regs->msr = MSR_USER; 61106d67d54SPaul Mackerras #else 612d4bf9a78SStephen Rothwell if (!test_thread_flag(TIF_32BIT)) { 61390eac727SMichael Ellerman unsigned long entry, toc; 61406d67d54SPaul Mackerras 61506d67d54SPaul Mackerras /* start is a relocated pointer to the function descriptor for 61606d67d54SPaul Mackerras * the elf _start routine. The first entry in the function 61706d67d54SPaul Mackerras * descriptor is the entry address of _start and the second 61806d67d54SPaul Mackerras * entry is the TOC value we need to use. 61906d67d54SPaul Mackerras */ 62006d67d54SPaul Mackerras __get_user(entry, (unsigned long __user *)start); 62106d67d54SPaul Mackerras __get_user(toc, (unsigned long __user *)start+1); 62206d67d54SPaul Mackerras 62306d67d54SPaul Mackerras /* Check whether the e_entry function descriptor entries 62406d67d54SPaul Mackerras * need to be relocated before we can use them. 62506d67d54SPaul Mackerras */ 62606d67d54SPaul Mackerras if (load_addr != 0) { 62706d67d54SPaul Mackerras entry += load_addr; 62806d67d54SPaul Mackerras toc += load_addr; 62906d67d54SPaul Mackerras } 63006d67d54SPaul Mackerras regs->nip = entry; 63106d67d54SPaul Mackerras regs->gpr[2] = toc; 63206d67d54SPaul Mackerras regs->msr = MSR_USER64; 633d4bf9a78SStephen Rothwell } else { 634d4bf9a78SStephen Rothwell regs->nip = start; 635d4bf9a78SStephen Rothwell regs->gpr[2] = 0; 636d4bf9a78SStephen Rothwell regs->msr = MSR_USER32; 63706d67d54SPaul Mackerras } 63806d67d54SPaul Mackerras #endif 63906d67d54SPaul Mackerras 64048abec07SPaul Mackerras discard_lazy_cpu_state(); 64114cf11afSPaul Mackerras memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); 64225c8a78bSDavid Gibson current->thread.fpscr.val = 0; 64314cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 64414cf11afSPaul Mackerras memset(current->thread.vr, 0, sizeof(current->thread.vr)); 64514cf11afSPaul Mackerras memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); 64606d67d54SPaul Mackerras current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ 64714cf11afSPaul Mackerras current->thread.vrsave = 0; 64814cf11afSPaul Mackerras current->thread.used_vr = 0; 64914cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 65014cf11afSPaul Mackerras #ifdef CONFIG_SPE 65114cf11afSPaul Mackerras memset(current->thread.evr, 0, sizeof(current->thread.evr)); 65214cf11afSPaul Mackerras current->thread.acc = 0; 65314cf11afSPaul Mackerras current->thread.spefscr = 0; 65414cf11afSPaul Mackerras current->thread.used_spe = 0; 65514cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 65614cf11afSPaul Mackerras } 65714cf11afSPaul Mackerras 65814cf11afSPaul Mackerras #define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ 65914cf11afSPaul Mackerras | PR_FP_EXC_RES | PR_FP_EXC_INV) 66014cf11afSPaul Mackerras 66114cf11afSPaul Mackerras int set_fpexc_mode(struct task_struct *tsk, unsigned int val) 66214cf11afSPaul Mackerras { 66314cf11afSPaul Mackerras struct pt_regs *regs = tsk->thread.regs; 66414cf11afSPaul Mackerras 66514cf11afSPaul Mackerras /* This is a bit hairy. If we are an SPE enabled processor 66614cf11afSPaul Mackerras * (have embedded fp) we store the IEEE exception enable flags in 66714cf11afSPaul Mackerras * fpexc_mode. fpexc_mode is also used for setting FP exception 66814cf11afSPaul Mackerras * mode (asyn, precise, disabled) for 'Classic' FP. */ 66914cf11afSPaul Mackerras if (val & PR_FP_EXC_SW_ENABLE) { 67014cf11afSPaul Mackerras #ifdef CONFIG_SPE 67114cf11afSPaul Mackerras tsk->thread.fpexc_mode = val & 67214cf11afSPaul Mackerras (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); 67306d67d54SPaul Mackerras return 0; 67414cf11afSPaul Mackerras #else 67514cf11afSPaul Mackerras return -EINVAL; 67614cf11afSPaul Mackerras #endif 67706d67d54SPaul Mackerras } 67806d67d54SPaul Mackerras 67914cf11afSPaul Mackerras /* on a CONFIG_SPE this does not hurt us. The bits that 68014cf11afSPaul Mackerras * __pack_fe01 use do not overlap with bits used for 68114cf11afSPaul Mackerras * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits 68214cf11afSPaul Mackerras * on CONFIG_SPE implementations are reserved so writing to 68314cf11afSPaul Mackerras * them does not change anything */ 68414cf11afSPaul Mackerras if (val > PR_FP_EXC_PRECISE) 68514cf11afSPaul Mackerras return -EINVAL; 68614cf11afSPaul Mackerras tsk->thread.fpexc_mode = __pack_fe01(val); 68714cf11afSPaul Mackerras if (regs != NULL && (regs->msr & MSR_FP) != 0) 68814cf11afSPaul Mackerras regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) 68914cf11afSPaul Mackerras | tsk->thread.fpexc_mode; 69014cf11afSPaul Mackerras return 0; 69114cf11afSPaul Mackerras } 69214cf11afSPaul Mackerras 69314cf11afSPaul Mackerras int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) 69414cf11afSPaul Mackerras { 69514cf11afSPaul Mackerras unsigned int val; 69614cf11afSPaul Mackerras 69714cf11afSPaul Mackerras if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) 69814cf11afSPaul Mackerras #ifdef CONFIG_SPE 69914cf11afSPaul Mackerras val = tsk->thread.fpexc_mode; 70014cf11afSPaul Mackerras #else 70114cf11afSPaul Mackerras return -EINVAL; 70214cf11afSPaul Mackerras #endif 70314cf11afSPaul Mackerras else 70414cf11afSPaul Mackerras val = __unpack_fe01(tsk->thread.fpexc_mode); 70514cf11afSPaul Mackerras return put_user(val, (unsigned int __user *) adr); 70614cf11afSPaul Mackerras } 70714cf11afSPaul Mackerras 70806d67d54SPaul Mackerras #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) 70906d67d54SPaul Mackerras 71014cf11afSPaul Mackerras int sys_clone(unsigned long clone_flags, unsigned long usp, 71114cf11afSPaul Mackerras int __user *parent_tidp, void __user *child_threadptr, 71214cf11afSPaul Mackerras int __user *child_tidp, int p6, 71314cf11afSPaul Mackerras struct pt_regs *regs) 71414cf11afSPaul Mackerras { 71514cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 71614cf11afSPaul Mackerras if (usp == 0) 71714cf11afSPaul Mackerras usp = regs->gpr[1]; /* stack pointer for child */ 71806d67d54SPaul Mackerras #ifdef CONFIG_PPC64 71906d67d54SPaul Mackerras if (test_thread_flag(TIF_32BIT)) { 72006d67d54SPaul Mackerras parent_tidp = TRUNC_PTR(parent_tidp); 72106d67d54SPaul Mackerras child_tidp = TRUNC_PTR(child_tidp); 72206d67d54SPaul Mackerras } 72306d67d54SPaul Mackerras #endif 72414cf11afSPaul Mackerras return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); 72514cf11afSPaul Mackerras } 72614cf11afSPaul Mackerras 72714cf11afSPaul Mackerras int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, 72814cf11afSPaul Mackerras unsigned long p4, unsigned long p5, unsigned long p6, 72914cf11afSPaul Mackerras struct pt_regs *regs) 73014cf11afSPaul Mackerras { 73114cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 73214cf11afSPaul Mackerras return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); 73314cf11afSPaul Mackerras } 73414cf11afSPaul Mackerras 73514cf11afSPaul Mackerras int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, 73614cf11afSPaul Mackerras unsigned long p4, unsigned long p5, unsigned long p6, 73714cf11afSPaul Mackerras struct pt_regs *regs) 73814cf11afSPaul Mackerras { 73914cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 74014cf11afSPaul Mackerras return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], 74114cf11afSPaul Mackerras regs, 0, NULL, NULL); 74214cf11afSPaul Mackerras } 74314cf11afSPaul Mackerras 74414cf11afSPaul Mackerras int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, 74514cf11afSPaul Mackerras unsigned long a3, unsigned long a4, unsigned long a5, 74614cf11afSPaul Mackerras struct pt_regs *regs) 74714cf11afSPaul Mackerras { 74814cf11afSPaul Mackerras int error; 74914cf11afSPaul Mackerras char *filename; 75014cf11afSPaul Mackerras 75114cf11afSPaul Mackerras filename = getname((char __user *) a0); 75214cf11afSPaul Mackerras error = PTR_ERR(filename); 75314cf11afSPaul Mackerras if (IS_ERR(filename)) 75414cf11afSPaul Mackerras goto out; 75514cf11afSPaul Mackerras flush_fp_to_thread(current); 75614cf11afSPaul Mackerras flush_altivec_to_thread(current); 75714cf11afSPaul Mackerras flush_spe_to_thread(current); 75820c8c210SPaul Mackerras error = do_execve(filename, (char __user * __user *) a1, 75920c8c210SPaul Mackerras (char __user * __user *) a2, regs); 76014cf11afSPaul Mackerras if (error == 0) { 76114cf11afSPaul Mackerras task_lock(current); 76214cf11afSPaul Mackerras current->ptrace &= ~PT_DTRACE; 76314cf11afSPaul Mackerras task_unlock(current); 76414cf11afSPaul Mackerras } 76514cf11afSPaul Mackerras putname(filename); 76614cf11afSPaul Mackerras out: 76714cf11afSPaul Mackerras return error; 76814cf11afSPaul Mackerras } 76914cf11afSPaul Mackerras 77014cf11afSPaul Mackerras static int validate_sp(unsigned long sp, struct task_struct *p, 77114cf11afSPaul Mackerras unsigned long nbytes) 77214cf11afSPaul Mackerras { 7730cec6fd1SAl Viro unsigned long stack_page = (unsigned long)task_stack_page(p); 77414cf11afSPaul Mackerras 77514cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 77614cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 77714cf11afSPaul Mackerras return 1; 77814cf11afSPaul Mackerras 77914cf11afSPaul Mackerras #ifdef CONFIG_IRQSTACKS 78014cf11afSPaul Mackerras stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; 78114cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 78214cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 78314cf11afSPaul Mackerras return 1; 78414cf11afSPaul Mackerras 78514cf11afSPaul Mackerras stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; 78614cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 78714cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 78814cf11afSPaul Mackerras return 1; 78914cf11afSPaul Mackerras #endif 79014cf11afSPaul Mackerras 79114cf11afSPaul Mackerras return 0; 79214cf11afSPaul Mackerras } 79314cf11afSPaul Mackerras 79406d67d54SPaul Mackerras #ifdef CONFIG_PPC64 79506d67d54SPaul Mackerras #define MIN_STACK_FRAME 112 /* same as STACK_FRAME_OVERHEAD, in fact */ 79606d67d54SPaul Mackerras #define FRAME_LR_SAVE 2 79706d67d54SPaul Mackerras #define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288) 79806d67d54SPaul Mackerras #define REGS_MARKER 0x7265677368657265ul 79906d67d54SPaul Mackerras #define FRAME_MARKER 12 80006d67d54SPaul Mackerras #else 80106d67d54SPaul Mackerras #define MIN_STACK_FRAME 16 80206d67d54SPaul Mackerras #define FRAME_LR_SAVE 1 80306d67d54SPaul Mackerras #define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD) 80406d67d54SPaul Mackerras #define REGS_MARKER 0x72656773ul 80506d67d54SPaul Mackerras #define FRAME_MARKER 2 80606d67d54SPaul Mackerras #endif 80714cf11afSPaul Mackerras 80806d67d54SPaul Mackerras unsigned long get_wchan(struct task_struct *p) 80906d67d54SPaul Mackerras { 81006d67d54SPaul Mackerras unsigned long ip, sp; 81106d67d54SPaul Mackerras int count = 0; 81206d67d54SPaul Mackerras 81306d67d54SPaul Mackerras if (!p || p == current || p->state == TASK_RUNNING) 81406d67d54SPaul Mackerras return 0; 81506d67d54SPaul Mackerras 81606d67d54SPaul Mackerras sp = p->thread.ksp; 81706d67d54SPaul Mackerras if (!validate_sp(sp, p, MIN_STACK_FRAME)) 81806d67d54SPaul Mackerras return 0; 81906d67d54SPaul Mackerras 82006d67d54SPaul Mackerras do { 82106d67d54SPaul Mackerras sp = *(unsigned long *)sp; 82206d67d54SPaul Mackerras if (!validate_sp(sp, p, MIN_STACK_FRAME)) 82306d67d54SPaul Mackerras return 0; 82406d67d54SPaul Mackerras if (count > 0) { 82506d67d54SPaul Mackerras ip = ((unsigned long *)sp)[FRAME_LR_SAVE]; 82606d67d54SPaul Mackerras if (!in_sched_functions(ip)) 82706d67d54SPaul Mackerras return ip; 82806d67d54SPaul Mackerras } 82906d67d54SPaul Mackerras } while (count++ < 16); 83006d67d54SPaul Mackerras return 0; 83106d67d54SPaul Mackerras } 83206d67d54SPaul Mackerras EXPORT_SYMBOL(get_wchan); 83306d67d54SPaul Mackerras 83406d67d54SPaul Mackerras static int kstack_depth_to_print = 64; 83514cf11afSPaul Mackerras 83614cf11afSPaul Mackerras void show_stack(struct task_struct *tsk, unsigned long *stack) 83714cf11afSPaul Mackerras { 83806d67d54SPaul Mackerras unsigned long sp, ip, lr, newsp; 83914cf11afSPaul Mackerras int count = 0; 84006d67d54SPaul Mackerras int firstframe = 1; 84114cf11afSPaul Mackerras 84214cf11afSPaul Mackerras sp = (unsigned long) stack; 84314cf11afSPaul Mackerras if (tsk == NULL) 84414cf11afSPaul Mackerras tsk = current; 84514cf11afSPaul Mackerras if (sp == 0) { 84614cf11afSPaul Mackerras if (tsk == current) 84714cf11afSPaul Mackerras asm("mr %0,1" : "=r" (sp)); 84814cf11afSPaul Mackerras else 84914cf11afSPaul Mackerras sp = tsk->thread.ksp; 85014cf11afSPaul Mackerras } 85114cf11afSPaul Mackerras 85206d67d54SPaul Mackerras lr = 0; 85306d67d54SPaul Mackerras printk("Call Trace:\n"); 85414cf11afSPaul Mackerras do { 85506d67d54SPaul Mackerras if (!validate_sp(sp, tsk, MIN_STACK_FRAME)) 85606d67d54SPaul Mackerras return; 85706d67d54SPaul Mackerras 85806d67d54SPaul Mackerras stack = (unsigned long *) sp; 85906d67d54SPaul Mackerras newsp = stack[0]; 86006d67d54SPaul Mackerras ip = stack[FRAME_LR_SAVE]; 86106d67d54SPaul Mackerras if (!firstframe || ip != lr) { 86206d67d54SPaul Mackerras printk("["REG"] ["REG"] ", sp, ip); 86306d67d54SPaul Mackerras print_symbol("%s", ip); 86406d67d54SPaul Mackerras if (firstframe) 86506d67d54SPaul Mackerras printk(" (unreliable)"); 86606d67d54SPaul Mackerras printk("\n"); 86714cf11afSPaul Mackerras } 86806d67d54SPaul Mackerras firstframe = 0; 86906d67d54SPaul Mackerras 87006d67d54SPaul Mackerras /* 87106d67d54SPaul Mackerras * See if this is an exception frame. 87206d67d54SPaul Mackerras * We look for the "regshere" marker in the current frame. 87306d67d54SPaul Mackerras */ 87406d67d54SPaul Mackerras if (validate_sp(sp, tsk, INT_FRAME_SIZE) 87506d67d54SPaul Mackerras && stack[FRAME_MARKER] == REGS_MARKER) { 87606d67d54SPaul Mackerras struct pt_regs *regs = (struct pt_regs *) 87706d67d54SPaul Mackerras (sp + STACK_FRAME_OVERHEAD); 87806d67d54SPaul Mackerras printk("--- Exception: %lx", regs->trap); 87906d67d54SPaul Mackerras print_symbol(" at %s\n", regs->nip); 88006d67d54SPaul Mackerras lr = regs->link; 88106d67d54SPaul Mackerras print_symbol(" LR = %s\n", lr); 88206d67d54SPaul Mackerras firstframe = 1; 88314cf11afSPaul Mackerras } 88406d67d54SPaul Mackerras 88506d67d54SPaul Mackerras sp = newsp; 88606d67d54SPaul Mackerras } while (count++ < kstack_depth_to_print); 88706d67d54SPaul Mackerras } 88806d67d54SPaul Mackerras 88906d67d54SPaul Mackerras void dump_stack(void) 89006d67d54SPaul Mackerras { 89106d67d54SPaul Mackerras show_stack(current, NULL); 89206d67d54SPaul Mackerras } 89306d67d54SPaul Mackerras EXPORT_SYMBOL(dump_stack); 894cb2c9b27SAnton Blanchard 895cb2c9b27SAnton Blanchard #ifdef CONFIG_PPC64 896cb2c9b27SAnton Blanchard void ppc64_runlatch_on(void) 897cb2c9b27SAnton Blanchard { 898cb2c9b27SAnton Blanchard unsigned long ctrl; 899cb2c9b27SAnton Blanchard 900cb2c9b27SAnton Blanchard if (cpu_has_feature(CPU_FTR_CTRL) && !test_thread_flag(TIF_RUNLATCH)) { 901cb2c9b27SAnton Blanchard HMT_medium(); 902cb2c9b27SAnton Blanchard 903cb2c9b27SAnton Blanchard ctrl = mfspr(SPRN_CTRLF); 904cb2c9b27SAnton Blanchard ctrl |= CTRL_RUNLATCH; 905cb2c9b27SAnton Blanchard mtspr(SPRN_CTRLT, ctrl); 906cb2c9b27SAnton Blanchard 907cb2c9b27SAnton Blanchard set_thread_flag(TIF_RUNLATCH); 908cb2c9b27SAnton Blanchard } 909cb2c9b27SAnton Blanchard } 910cb2c9b27SAnton Blanchard 911cb2c9b27SAnton Blanchard void ppc64_runlatch_off(void) 912cb2c9b27SAnton Blanchard { 913cb2c9b27SAnton Blanchard unsigned long ctrl; 914cb2c9b27SAnton Blanchard 915cb2c9b27SAnton Blanchard if (cpu_has_feature(CPU_FTR_CTRL) && test_thread_flag(TIF_RUNLATCH)) { 916cb2c9b27SAnton Blanchard HMT_medium(); 917cb2c9b27SAnton Blanchard 918cb2c9b27SAnton Blanchard clear_thread_flag(TIF_RUNLATCH); 919cb2c9b27SAnton Blanchard 920cb2c9b27SAnton Blanchard ctrl = mfspr(SPRN_CTRLF); 921cb2c9b27SAnton Blanchard ctrl &= ~CTRL_RUNLATCH; 922cb2c9b27SAnton Blanchard mtspr(SPRN_CTRLT, ctrl); 923cb2c9b27SAnton Blanchard } 924cb2c9b27SAnton Blanchard } 925cb2c9b27SAnton Blanchard #endif 926