114cf11afSPaul Mackerras /* 214cf11afSPaul Mackerras * arch/ppc/kernel/process.c 314cf11afSPaul Mackerras * 414cf11afSPaul Mackerras * Derived from "arch/i386/kernel/process.c" 514cf11afSPaul Mackerras * Copyright (C) 1995 Linus Torvalds 614cf11afSPaul Mackerras * 714cf11afSPaul Mackerras * Updated and modified by Cort Dougan (cort@cs.nmt.edu) and 814cf11afSPaul Mackerras * Paul Mackerras (paulus@cs.anu.edu.au) 914cf11afSPaul Mackerras * 1014cf11afSPaul Mackerras * PowerPC version 1114cf11afSPaul Mackerras * Copyright (C) 1995-1996 Gary Thomas (gdt@linuxppc.org) 1214cf11afSPaul Mackerras * 1314cf11afSPaul Mackerras * This program is free software; you can redistribute it and/or 1414cf11afSPaul Mackerras * modify it under the terms of the GNU General Public License 1514cf11afSPaul Mackerras * as published by the Free Software Foundation; either version 1614cf11afSPaul Mackerras * 2 of the License, or (at your option) any later version. 1714cf11afSPaul Mackerras */ 1814cf11afSPaul Mackerras 1914cf11afSPaul Mackerras #include <linux/config.h> 2014cf11afSPaul Mackerras #include <linux/errno.h> 2114cf11afSPaul Mackerras #include <linux/sched.h> 2214cf11afSPaul Mackerras #include <linux/kernel.h> 2314cf11afSPaul Mackerras #include <linux/mm.h> 2414cf11afSPaul Mackerras #include <linux/smp.h> 2514cf11afSPaul Mackerras #include <linux/smp_lock.h> 2614cf11afSPaul Mackerras #include <linux/stddef.h> 2714cf11afSPaul Mackerras #include <linux/unistd.h> 2814cf11afSPaul Mackerras #include <linux/ptrace.h> 2914cf11afSPaul Mackerras #include <linux/slab.h> 3014cf11afSPaul Mackerras #include <linux/user.h> 3114cf11afSPaul Mackerras #include <linux/elf.h> 3214cf11afSPaul Mackerras #include <linux/init.h> 3314cf11afSPaul Mackerras #include <linux/prctl.h> 3414cf11afSPaul Mackerras #include <linux/init_task.h> 3514cf11afSPaul Mackerras #include <linux/module.h> 3614cf11afSPaul Mackerras #include <linux/kallsyms.h> 3714cf11afSPaul Mackerras #include <linux/mqueue.h> 3814cf11afSPaul Mackerras #include <linux/hardirq.h> 39*06d67d54SPaul Mackerras #include <linux/utsname.h> 40*06d67d54SPaul Mackerras #include <linux/kprobes.h> 4114cf11afSPaul Mackerras 4214cf11afSPaul Mackerras #include <asm/pgtable.h> 4314cf11afSPaul Mackerras #include <asm/uaccess.h> 4414cf11afSPaul Mackerras #include <asm/system.h> 4514cf11afSPaul Mackerras #include <asm/io.h> 4614cf11afSPaul Mackerras #include <asm/processor.h> 4714cf11afSPaul Mackerras #include <asm/mmu.h> 4814cf11afSPaul Mackerras #include <asm/prom.h> 49*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 50*06d67d54SPaul Mackerras #include <asm/firmware.h> 51*06d67d54SPaul Mackerras #include <asm/plpar_wrappers.h> 52*06d67d54SPaul Mackerras #include <asm/time.h> 53*06d67d54SPaul Mackerras #endif 5414cf11afSPaul Mackerras 5514cf11afSPaul Mackerras extern unsigned long _get_SP(void); 5614cf11afSPaul Mackerras 5714cf11afSPaul Mackerras #ifndef CONFIG_SMP 5814cf11afSPaul Mackerras struct task_struct *last_task_used_math = NULL; 5914cf11afSPaul Mackerras struct task_struct *last_task_used_altivec = NULL; 6014cf11afSPaul Mackerras struct task_struct *last_task_used_spe = NULL; 6114cf11afSPaul Mackerras #endif 6214cf11afSPaul Mackerras 6314cf11afSPaul Mackerras /* 6414cf11afSPaul Mackerras * Make sure the floating-point register state in the 6514cf11afSPaul Mackerras * the thread_struct is up to date for task tsk. 6614cf11afSPaul Mackerras */ 6714cf11afSPaul Mackerras void flush_fp_to_thread(struct task_struct *tsk) 6814cf11afSPaul Mackerras { 6914cf11afSPaul Mackerras if (tsk->thread.regs) { 7014cf11afSPaul Mackerras /* 7114cf11afSPaul Mackerras * We need to disable preemption here because if we didn't, 7214cf11afSPaul Mackerras * another process could get scheduled after the regs->msr 7314cf11afSPaul Mackerras * test but before we have finished saving the FP registers 7414cf11afSPaul Mackerras * to the thread_struct. That process could take over the 7514cf11afSPaul Mackerras * FPU, and then when we get scheduled again we would store 7614cf11afSPaul Mackerras * bogus values for the remaining FP registers. 7714cf11afSPaul Mackerras */ 7814cf11afSPaul Mackerras preempt_disable(); 7914cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_FP) { 8014cf11afSPaul Mackerras #ifdef CONFIG_SMP 8114cf11afSPaul Mackerras /* 8214cf11afSPaul Mackerras * This should only ever be called for current or 8314cf11afSPaul Mackerras * for a stopped child process. Since we save away 8414cf11afSPaul Mackerras * the FP register state on context switch on SMP, 8514cf11afSPaul Mackerras * there is something wrong if a stopped child appears 8614cf11afSPaul Mackerras * to still have its FP state in the CPU registers. 8714cf11afSPaul Mackerras */ 8814cf11afSPaul Mackerras BUG_ON(tsk != current); 8914cf11afSPaul Mackerras #endif 9014cf11afSPaul Mackerras giveup_fpu(current); 9114cf11afSPaul Mackerras } 9214cf11afSPaul Mackerras preempt_enable(); 9314cf11afSPaul Mackerras } 9414cf11afSPaul Mackerras } 9514cf11afSPaul Mackerras 9614cf11afSPaul Mackerras void enable_kernel_fp(void) 9714cf11afSPaul Mackerras { 9814cf11afSPaul Mackerras WARN_ON(preemptible()); 9914cf11afSPaul Mackerras 10014cf11afSPaul Mackerras #ifdef CONFIG_SMP 10114cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_FP)) 10214cf11afSPaul Mackerras giveup_fpu(current); 10314cf11afSPaul Mackerras else 10414cf11afSPaul Mackerras giveup_fpu(NULL); /* just enables FP for kernel */ 10514cf11afSPaul Mackerras #else 10614cf11afSPaul Mackerras giveup_fpu(last_task_used_math); 10714cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 10814cf11afSPaul Mackerras } 10914cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_fp); 11014cf11afSPaul Mackerras 11114cf11afSPaul Mackerras int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs) 11214cf11afSPaul Mackerras { 11314cf11afSPaul Mackerras if (!tsk->thread.regs) 11414cf11afSPaul Mackerras return 0; 11514cf11afSPaul Mackerras flush_fp_to_thread(current); 11614cf11afSPaul Mackerras 11714cf11afSPaul Mackerras memcpy(fpregs, &tsk->thread.fpr[0], sizeof(*fpregs)); 11814cf11afSPaul Mackerras 11914cf11afSPaul Mackerras return 1; 12014cf11afSPaul Mackerras } 12114cf11afSPaul Mackerras 12214cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 12314cf11afSPaul Mackerras void enable_kernel_altivec(void) 12414cf11afSPaul Mackerras { 12514cf11afSPaul Mackerras WARN_ON(preemptible()); 12614cf11afSPaul Mackerras 12714cf11afSPaul Mackerras #ifdef CONFIG_SMP 12814cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_VEC)) 12914cf11afSPaul Mackerras giveup_altivec(current); 13014cf11afSPaul Mackerras else 13114cf11afSPaul Mackerras giveup_altivec(NULL); /* just enable AltiVec for kernel - force */ 13214cf11afSPaul Mackerras #else 13314cf11afSPaul Mackerras giveup_altivec(last_task_used_altivec); 13414cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 13514cf11afSPaul Mackerras } 13614cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_altivec); 13714cf11afSPaul Mackerras 13814cf11afSPaul Mackerras /* 13914cf11afSPaul Mackerras * Make sure the VMX/Altivec register state in the 14014cf11afSPaul Mackerras * the thread_struct is up to date for task tsk. 14114cf11afSPaul Mackerras */ 14214cf11afSPaul Mackerras void flush_altivec_to_thread(struct task_struct *tsk) 14314cf11afSPaul Mackerras { 14414cf11afSPaul Mackerras if (tsk->thread.regs) { 14514cf11afSPaul Mackerras preempt_disable(); 14614cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_VEC) { 14714cf11afSPaul Mackerras #ifdef CONFIG_SMP 14814cf11afSPaul Mackerras BUG_ON(tsk != current); 14914cf11afSPaul Mackerras #endif 15014cf11afSPaul Mackerras giveup_altivec(current); 15114cf11afSPaul Mackerras } 15214cf11afSPaul Mackerras preempt_enable(); 15314cf11afSPaul Mackerras } 15414cf11afSPaul Mackerras } 15514cf11afSPaul Mackerras 15614cf11afSPaul Mackerras int dump_task_altivec(struct pt_regs *regs, elf_vrregset_t *vrregs) 15714cf11afSPaul Mackerras { 15814cf11afSPaul Mackerras flush_altivec_to_thread(current); 15914cf11afSPaul Mackerras memcpy(vrregs, ¤t->thread.vr[0], sizeof(*vrregs)); 16014cf11afSPaul Mackerras return 1; 16114cf11afSPaul Mackerras } 16214cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 16314cf11afSPaul Mackerras 16414cf11afSPaul Mackerras #ifdef CONFIG_SPE 16514cf11afSPaul Mackerras 16614cf11afSPaul Mackerras void enable_kernel_spe(void) 16714cf11afSPaul Mackerras { 16814cf11afSPaul Mackerras WARN_ON(preemptible()); 16914cf11afSPaul Mackerras 17014cf11afSPaul Mackerras #ifdef CONFIG_SMP 17114cf11afSPaul Mackerras if (current->thread.regs && (current->thread.regs->msr & MSR_SPE)) 17214cf11afSPaul Mackerras giveup_spe(current); 17314cf11afSPaul Mackerras else 17414cf11afSPaul Mackerras giveup_spe(NULL); /* just enable SPE for kernel - force */ 17514cf11afSPaul Mackerras #else 17614cf11afSPaul Mackerras giveup_spe(last_task_used_spe); 17714cf11afSPaul Mackerras #endif /* __SMP __ */ 17814cf11afSPaul Mackerras } 17914cf11afSPaul Mackerras EXPORT_SYMBOL(enable_kernel_spe); 18014cf11afSPaul Mackerras 18114cf11afSPaul Mackerras void flush_spe_to_thread(struct task_struct *tsk) 18214cf11afSPaul Mackerras { 18314cf11afSPaul Mackerras if (tsk->thread.regs) { 18414cf11afSPaul Mackerras preempt_disable(); 18514cf11afSPaul Mackerras if (tsk->thread.regs->msr & MSR_SPE) { 18614cf11afSPaul Mackerras #ifdef CONFIG_SMP 18714cf11afSPaul Mackerras BUG_ON(tsk != current); 18814cf11afSPaul Mackerras #endif 18914cf11afSPaul Mackerras giveup_spe(current); 19014cf11afSPaul Mackerras } 19114cf11afSPaul Mackerras preempt_enable(); 19214cf11afSPaul Mackerras } 19314cf11afSPaul Mackerras } 19414cf11afSPaul Mackerras 19514cf11afSPaul Mackerras int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs) 19614cf11afSPaul Mackerras { 19714cf11afSPaul Mackerras flush_spe_to_thread(current); 19814cf11afSPaul Mackerras /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */ 19914cf11afSPaul Mackerras memcpy(evrregs, ¤t->thread.evr[0], sizeof(u32) * 35); 20014cf11afSPaul Mackerras return 1; 20114cf11afSPaul Mackerras } 20214cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 20314cf11afSPaul Mackerras 20414cf11afSPaul Mackerras static void set_dabr_spr(unsigned long val) 20514cf11afSPaul Mackerras { 20614cf11afSPaul Mackerras mtspr(SPRN_DABR, val); 20714cf11afSPaul Mackerras } 20814cf11afSPaul Mackerras 20914cf11afSPaul Mackerras int set_dabr(unsigned long dabr) 21014cf11afSPaul Mackerras { 21114cf11afSPaul Mackerras int ret = 0; 21214cf11afSPaul Mackerras 21314cf11afSPaul Mackerras #ifdef CONFIG_PPC64 21414cf11afSPaul Mackerras if (firmware_has_feature(FW_FEATURE_XDABR)) { 21514cf11afSPaul Mackerras /* We want to catch accesses from kernel and userspace */ 21614cf11afSPaul Mackerras unsigned long flags = H_DABRX_KERNEL|H_DABRX_USER; 21714cf11afSPaul Mackerras ret = plpar_set_xdabr(dabr, flags); 21814cf11afSPaul Mackerras } else if (firmware_has_feature(FW_FEATURE_DABR)) { 21914cf11afSPaul Mackerras ret = plpar_set_dabr(dabr); 22014cf11afSPaul Mackerras } else 22114cf11afSPaul Mackerras #endif 22214cf11afSPaul Mackerras set_dabr_spr(dabr); 22314cf11afSPaul Mackerras 22414cf11afSPaul Mackerras return ret; 22514cf11afSPaul Mackerras } 22614cf11afSPaul Mackerras 227*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 228*06d67d54SPaul Mackerras DEFINE_PER_CPU(struct cpu_usage, cpu_usage_array); 22914cf11afSPaul Mackerras static DEFINE_PER_CPU(unsigned long, current_dabr); 230*06d67d54SPaul Mackerras #endif 23114cf11afSPaul Mackerras 23214cf11afSPaul Mackerras struct task_struct *__switch_to(struct task_struct *prev, 23314cf11afSPaul Mackerras struct task_struct *new) 23414cf11afSPaul Mackerras { 23514cf11afSPaul Mackerras struct thread_struct *new_thread, *old_thread; 23614cf11afSPaul Mackerras unsigned long flags; 23714cf11afSPaul Mackerras struct task_struct *last; 23814cf11afSPaul Mackerras 23914cf11afSPaul Mackerras #ifdef CONFIG_SMP 24014cf11afSPaul Mackerras /* avoid complexity of lazy save/restore of fpu 24114cf11afSPaul Mackerras * by just saving it every time we switch out if 24214cf11afSPaul Mackerras * this task used the fpu during the last quantum. 24314cf11afSPaul Mackerras * 24414cf11afSPaul Mackerras * If it tries to use the fpu again, it'll trap and 24514cf11afSPaul Mackerras * reload its fp regs. So we don't have to do a restore 24614cf11afSPaul Mackerras * every switch, just a save. 24714cf11afSPaul Mackerras * -- Cort 24814cf11afSPaul Mackerras */ 24914cf11afSPaul Mackerras if (prev->thread.regs && (prev->thread.regs->msr & MSR_FP)) 25014cf11afSPaul Mackerras giveup_fpu(prev); 25114cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 25214cf11afSPaul Mackerras /* 25314cf11afSPaul Mackerras * If the previous thread used altivec in the last quantum 25414cf11afSPaul Mackerras * (thus changing altivec regs) then save them. 25514cf11afSPaul Mackerras * We used to check the VRSAVE register but not all apps 25614cf11afSPaul Mackerras * set it, so we don't rely on it now (and in fact we need 25714cf11afSPaul Mackerras * to save & restore VSCR even if VRSAVE == 0). -- paulus 25814cf11afSPaul Mackerras * 25914cf11afSPaul Mackerras * On SMP we always save/restore altivec regs just to avoid the 26014cf11afSPaul Mackerras * complexity of changing processors. 26114cf11afSPaul Mackerras * -- Cort 26214cf11afSPaul Mackerras */ 26314cf11afSPaul Mackerras if (prev->thread.regs && (prev->thread.regs->msr & MSR_VEC)) 26414cf11afSPaul Mackerras giveup_altivec(prev); 26514cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 26614cf11afSPaul Mackerras #ifdef CONFIG_SPE 26714cf11afSPaul Mackerras /* 26814cf11afSPaul Mackerras * If the previous thread used spe in the last quantum 26914cf11afSPaul Mackerras * (thus changing spe regs) then save them. 27014cf11afSPaul Mackerras * 27114cf11afSPaul Mackerras * On SMP we always save/restore spe regs just to avoid the 27214cf11afSPaul Mackerras * complexity of changing processors. 27314cf11afSPaul Mackerras */ 27414cf11afSPaul Mackerras if ((prev->thread.regs && (prev->thread.regs->msr & MSR_SPE))) 27514cf11afSPaul Mackerras giveup_spe(prev); 276c0c0d996SPaul Mackerras #endif /* CONFIG_SPE */ 277c0c0d996SPaul Mackerras 278c0c0d996SPaul Mackerras #else /* CONFIG_SMP */ 279c0c0d996SPaul Mackerras #ifdef CONFIG_ALTIVEC 280c0c0d996SPaul Mackerras /* Avoid the trap. On smp this this never happens since 281c0c0d996SPaul Mackerras * we don't set last_task_used_altivec -- Cort 282c0c0d996SPaul Mackerras */ 283c0c0d996SPaul Mackerras if (new->thread.regs && last_task_used_altivec == new) 284c0c0d996SPaul Mackerras new->thread.regs->msr |= MSR_VEC; 285c0c0d996SPaul Mackerras #endif /* CONFIG_ALTIVEC */ 286c0c0d996SPaul Mackerras #ifdef CONFIG_SPE 28714cf11afSPaul Mackerras /* Avoid the trap. On smp this this never happens since 28814cf11afSPaul Mackerras * we don't set last_task_used_spe 28914cf11afSPaul Mackerras */ 29014cf11afSPaul Mackerras if (new->thread.regs && last_task_used_spe == new) 29114cf11afSPaul Mackerras new->thread.regs->msr |= MSR_SPE; 29214cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 293c0c0d996SPaul Mackerras 29414cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 29514cf11afSPaul Mackerras 29614cf11afSPaul Mackerras #ifdef CONFIG_PPC64 /* for now */ 29714cf11afSPaul Mackerras if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr)) { 29814cf11afSPaul Mackerras set_dabr(new->thread.dabr); 29914cf11afSPaul Mackerras __get_cpu_var(current_dabr) = new->thread.dabr; 30014cf11afSPaul Mackerras } 301*06d67d54SPaul Mackerras 302*06d67d54SPaul Mackerras flush_tlb_pending(); 30314cf11afSPaul Mackerras #endif 30414cf11afSPaul Mackerras 30514cf11afSPaul Mackerras new_thread = &new->thread; 30614cf11afSPaul Mackerras old_thread = ¤t->thread; 307*06d67d54SPaul Mackerras 308*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 309*06d67d54SPaul Mackerras /* 310*06d67d54SPaul Mackerras * Collect processor utilization data per process 311*06d67d54SPaul Mackerras */ 312*06d67d54SPaul Mackerras if (firmware_has_feature(FW_FEATURE_SPLPAR)) { 313*06d67d54SPaul Mackerras struct cpu_usage *cu = &__get_cpu_var(cpu_usage_array); 314*06d67d54SPaul Mackerras long unsigned start_tb, current_tb; 315*06d67d54SPaul Mackerras start_tb = old_thread->start_tb; 316*06d67d54SPaul Mackerras cu->current_tb = current_tb = mfspr(SPRN_PURR); 317*06d67d54SPaul Mackerras old_thread->accum_tb += (current_tb - start_tb); 318*06d67d54SPaul Mackerras new_thread->start_tb = current_tb; 319*06d67d54SPaul Mackerras } 320*06d67d54SPaul Mackerras #endif 321*06d67d54SPaul Mackerras 32214cf11afSPaul Mackerras local_irq_save(flags); 32314cf11afSPaul Mackerras last = _switch(old_thread, new_thread); 32414cf11afSPaul Mackerras 32514cf11afSPaul Mackerras local_irq_restore(flags); 32614cf11afSPaul Mackerras 32714cf11afSPaul Mackerras return last; 32814cf11afSPaul Mackerras } 32914cf11afSPaul Mackerras 330*06d67d54SPaul Mackerras static int instructions_to_print = 16; 331*06d67d54SPaul Mackerras 332*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 333*06d67d54SPaul Mackerras #define BAD_PC(pc) ((REGION_ID(pc) != KERNEL_REGION_ID) && \ 334*06d67d54SPaul Mackerras (REGION_ID(pc) != VMALLOC_REGION_ID)) 335*06d67d54SPaul Mackerras #else 336*06d67d54SPaul Mackerras #define BAD_PC(pc) ((pc) < KERNELBASE) 337*06d67d54SPaul Mackerras #endif 338*06d67d54SPaul Mackerras 339*06d67d54SPaul Mackerras static void show_instructions(struct pt_regs *regs) 340*06d67d54SPaul Mackerras { 341*06d67d54SPaul Mackerras int i; 342*06d67d54SPaul Mackerras unsigned long pc = regs->nip - (instructions_to_print * 3 / 4 * 343*06d67d54SPaul Mackerras sizeof(int)); 344*06d67d54SPaul Mackerras 345*06d67d54SPaul Mackerras printk("Instruction dump:"); 346*06d67d54SPaul Mackerras 347*06d67d54SPaul Mackerras for (i = 0; i < instructions_to_print; i++) { 348*06d67d54SPaul Mackerras int instr; 349*06d67d54SPaul Mackerras 350*06d67d54SPaul Mackerras if (!(i % 8)) 351*06d67d54SPaul Mackerras printk("\n"); 352*06d67d54SPaul Mackerras 353*06d67d54SPaul Mackerras if (BAD_PC(pc) || __get_user(instr, (unsigned int *)pc)) { 354*06d67d54SPaul Mackerras printk("XXXXXXXX "); 355*06d67d54SPaul Mackerras } else { 356*06d67d54SPaul Mackerras if (regs->nip == pc) 357*06d67d54SPaul Mackerras printk("<%08x> ", instr); 358*06d67d54SPaul Mackerras else 359*06d67d54SPaul Mackerras printk("%08x ", instr); 360*06d67d54SPaul Mackerras } 361*06d67d54SPaul Mackerras 362*06d67d54SPaul Mackerras pc += sizeof(int); 363*06d67d54SPaul Mackerras } 364*06d67d54SPaul Mackerras 365*06d67d54SPaul Mackerras printk("\n"); 366*06d67d54SPaul Mackerras } 367*06d67d54SPaul Mackerras 368*06d67d54SPaul Mackerras static struct regbit { 369*06d67d54SPaul Mackerras unsigned long bit; 370*06d67d54SPaul Mackerras const char *name; 371*06d67d54SPaul Mackerras } msr_bits[] = { 372*06d67d54SPaul Mackerras {MSR_EE, "EE"}, 373*06d67d54SPaul Mackerras {MSR_PR, "PR"}, 374*06d67d54SPaul Mackerras {MSR_FP, "FP"}, 375*06d67d54SPaul Mackerras {MSR_ME, "ME"}, 376*06d67d54SPaul Mackerras {MSR_IR, "IR"}, 377*06d67d54SPaul Mackerras {MSR_DR, "DR"}, 378*06d67d54SPaul Mackerras {0, NULL} 379*06d67d54SPaul Mackerras }; 380*06d67d54SPaul Mackerras 381*06d67d54SPaul Mackerras static void printbits(unsigned long val, struct regbit *bits) 382*06d67d54SPaul Mackerras { 383*06d67d54SPaul Mackerras const char *sep = ""; 384*06d67d54SPaul Mackerras 385*06d67d54SPaul Mackerras printk("<"); 386*06d67d54SPaul Mackerras for (; bits->bit; ++bits) 387*06d67d54SPaul Mackerras if (val & bits->bit) { 388*06d67d54SPaul Mackerras printk("%s%s", sep, bits->name); 389*06d67d54SPaul Mackerras sep = ","; 390*06d67d54SPaul Mackerras } 391*06d67d54SPaul Mackerras printk(">"); 392*06d67d54SPaul Mackerras } 393*06d67d54SPaul Mackerras 394*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 395*06d67d54SPaul Mackerras #define REG "%016lX" 396*06d67d54SPaul Mackerras #define REGS_PER_LINE 4 397*06d67d54SPaul Mackerras #define LAST_VOLATILE 13 398*06d67d54SPaul Mackerras #else 399*06d67d54SPaul Mackerras #define REG "%08lX" 400*06d67d54SPaul Mackerras #define REGS_PER_LINE 8 401*06d67d54SPaul Mackerras #define LAST_VOLATILE 12 402*06d67d54SPaul Mackerras #endif 403*06d67d54SPaul Mackerras 40414cf11afSPaul Mackerras void show_regs(struct pt_regs * regs) 40514cf11afSPaul Mackerras { 40614cf11afSPaul Mackerras int i, trap; 40714cf11afSPaul Mackerras 408*06d67d54SPaul Mackerras printk("NIP: "REG" LR: "REG" CTR: "REG"\n", 409*06d67d54SPaul Mackerras regs->nip, regs->link, regs->ctr); 410*06d67d54SPaul Mackerras printk("REGS: %p TRAP: %04lx %s (%s)\n", 411*06d67d54SPaul Mackerras regs, regs->trap, print_tainted(), system_utsname.release); 412*06d67d54SPaul Mackerras printk("MSR: "REG" ", regs->msr); 413*06d67d54SPaul Mackerras printbits(regs->msr, msr_bits); 414*06d67d54SPaul Mackerras printk(" CR: %08lX XER: %08lX\n", regs->ccr, regs->xer); 41514cf11afSPaul Mackerras trap = TRAP(regs); 41614cf11afSPaul Mackerras if (trap == 0x300 || trap == 0x600) 417*06d67d54SPaul Mackerras printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr); 418*06d67d54SPaul Mackerras printk("TASK = %p[%d] '%s' THREAD: %p", 41914cf11afSPaul Mackerras current, current->pid, current->comm, current->thread_info); 42014cf11afSPaul Mackerras 42114cf11afSPaul Mackerras #ifdef CONFIG_SMP 42214cf11afSPaul Mackerras printk(" CPU: %d", smp_processor_id()); 42314cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 42414cf11afSPaul Mackerras 42514cf11afSPaul Mackerras for (i = 0; i < 32; i++) { 426*06d67d54SPaul Mackerras if ((i % REGS_PER_LINE) == 0) 42714cf11afSPaul Mackerras printk("\n" KERN_INFO "GPR%02d: ", i); 428*06d67d54SPaul Mackerras printk(REG " ", regs->gpr[i]); 429*06d67d54SPaul Mackerras if (i == LAST_VOLATILE && !FULL_REGS(regs)) 43014cf11afSPaul Mackerras break; 43114cf11afSPaul Mackerras } 43214cf11afSPaul Mackerras printk("\n"); 43314cf11afSPaul Mackerras #ifdef CONFIG_KALLSYMS 43414cf11afSPaul Mackerras /* 43514cf11afSPaul Mackerras * Lookup NIP late so we have the best change of getting the 43614cf11afSPaul Mackerras * above info out without failing 43714cf11afSPaul Mackerras */ 438*06d67d54SPaul Mackerras printk("NIP ["REG"] ", regs->nip); 43914cf11afSPaul Mackerras print_symbol("%s\n", regs->nip); 440*06d67d54SPaul Mackerras printk("LR ["REG"] ", regs->link); 44114cf11afSPaul Mackerras print_symbol("%s\n", regs->link); 44214cf11afSPaul Mackerras #endif 44314cf11afSPaul Mackerras show_stack(current, (unsigned long *) regs->gpr[1]); 444*06d67d54SPaul Mackerras if (!user_mode(regs)) 445*06d67d54SPaul Mackerras show_instructions(regs); 44614cf11afSPaul Mackerras } 44714cf11afSPaul Mackerras 44814cf11afSPaul Mackerras void exit_thread(void) 44914cf11afSPaul Mackerras { 450*06d67d54SPaul Mackerras kprobe_flush_task(current); 451*06d67d54SPaul Mackerras 45214cf11afSPaul Mackerras #ifndef CONFIG_SMP 45314cf11afSPaul Mackerras if (last_task_used_math == current) 45414cf11afSPaul Mackerras last_task_used_math = NULL; 45514cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 45614cf11afSPaul Mackerras if (last_task_used_altivec == current) 45714cf11afSPaul Mackerras last_task_used_altivec = NULL; 45814cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 45914cf11afSPaul Mackerras #ifdef CONFIG_SPE 46014cf11afSPaul Mackerras if (last_task_used_spe == current) 46114cf11afSPaul Mackerras last_task_used_spe = NULL; 46214cf11afSPaul Mackerras #endif 46314cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 46414cf11afSPaul Mackerras } 46514cf11afSPaul Mackerras 46614cf11afSPaul Mackerras void flush_thread(void) 46714cf11afSPaul Mackerras { 468*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 469*06d67d54SPaul Mackerras struct thread_info *t = current_thread_info(); 470*06d67d54SPaul Mackerras 471*06d67d54SPaul Mackerras if (t->flags & _TIF_ABI_PENDING) 472*06d67d54SPaul Mackerras t->flags ^= (_TIF_ABI_PENDING | _TIF_32BIT); 473*06d67d54SPaul Mackerras #endif 474*06d67d54SPaul Mackerras kprobe_flush_task(current); 475*06d67d54SPaul Mackerras 47614cf11afSPaul Mackerras #ifndef CONFIG_SMP 47714cf11afSPaul Mackerras if (last_task_used_math == current) 47814cf11afSPaul Mackerras last_task_used_math = NULL; 47914cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 48014cf11afSPaul Mackerras if (last_task_used_altivec == current) 48114cf11afSPaul Mackerras last_task_used_altivec = NULL; 48214cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 48314cf11afSPaul Mackerras #ifdef CONFIG_SPE 48414cf11afSPaul Mackerras if (last_task_used_spe == current) 48514cf11afSPaul Mackerras last_task_used_spe = NULL; 48614cf11afSPaul Mackerras #endif 48714cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 48814cf11afSPaul Mackerras 48914cf11afSPaul Mackerras #ifdef CONFIG_PPC64 /* for now */ 49014cf11afSPaul Mackerras if (current->thread.dabr) { 49114cf11afSPaul Mackerras current->thread.dabr = 0; 49214cf11afSPaul Mackerras set_dabr(0); 49314cf11afSPaul Mackerras } 49414cf11afSPaul Mackerras #endif 49514cf11afSPaul Mackerras } 49614cf11afSPaul Mackerras 49714cf11afSPaul Mackerras void 49814cf11afSPaul Mackerras release_thread(struct task_struct *t) 49914cf11afSPaul Mackerras { 50014cf11afSPaul Mackerras } 50114cf11afSPaul Mackerras 50214cf11afSPaul Mackerras /* 50314cf11afSPaul Mackerras * This gets called before we allocate a new thread and copy 50414cf11afSPaul Mackerras * the current task into it. 50514cf11afSPaul Mackerras */ 50614cf11afSPaul Mackerras void prepare_to_copy(struct task_struct *tsk) 50714cf11afSPaul Mackerras { 50814cf11afSPaul Mackerras flush_fp_to_thread(current); 50914cf11afSPaul Mackerras flush_altivec_to_thread(current); 51014cf11afSPaul Mackerras flush_spe_to_thread(current); 51114cf11afSPaul Mackerras } 51214cf11afSPaul Mackerras 51314cf11afSPaul Mackerras /* 51414cf11afSPaul Mackerras * Copy a thread.. 51514cf11afSPaul Mackerras */ 516*06d67d54SPaul Mackerras int copy_thread(int nr, unsigned long clone_flags, unsigned long usp, 517*06d67d54SPaul Mackerras unsigned long unused, struct task_struct *p, 518*06d67d54SPaul Mackerras struct pt_regs *regs) 51914cf11afSPaul Mackerras { 52014cf11afSPaul Mackerras struct pt_regs *childregs, *kregs; 52114cf11afSPaul Mackerras extern void ret_from_fork(void); 52214cf11afSPaul Mackerras unsigned long sp = (unsigned long)p->thread_info + THREAD_SIZE; 52314cf11afSPaul Mackerras 52414cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 52514cf11afSPaul Mackerras /* Copy registers */ 52614cf11afSPaul Mackerras sp -= sizeof(struct pt_regs); 52714cf11afSPaul Mackerras childregs = (struct pt_regs *) sp; 52814cf11afSPaul Mackerras *childregs = *regs; 52914cf11afSPaul Mackerras if ((childregs->msr & MSR_PR) == 0) { 53014cf11afSPaul Mackerras /* for kernel thread, set `current' and stackptr in new task */ 53114cf11afSPaul Mackerras childregs->gpr[1] = sp + sizeof(struct pt_regs); 532*06d67d54SPaul Mackerras #ifdef CONFIG_PPC32 53314cf11afSPaul Mackerras childregs->gpr[2] = (unsigned long) p; 534*06d67d54SPaul Mackerras #else 535*06d67d54SPaul Mackerras clear_ti_thread_flag(p->thread_info, TIF_32BIT); 536*06d67d54SPaul Mackerras #endif 53714cf11afSPaul Mackerras p->thread.regs = NULL; /* no user register state */ 53814cf11afSPaul Mackerras } else { 53914cf11afSPaul Mackerras childregs->gpr[1] = usp; 54014cf11afSPaul Mackerras p->thread.regs = childregs; 541*06d67d54SPaul Mackerras if (clone_flags & CLONE_SETTLS) { 542*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 543*06d67d54SPaul Mackerras if (!test_thread_flag(TIF_32BIT)) 544*06d67d54SPaul Mackerras childregs->gpr[13] = childregs->gpr[6]; 545*06d67d54SPaul Mackerras else 546*06d67d54SPaul Mackerras #endif 54714cf11afSPaul Mackerras childregs->gpr[2] = childregs->gpr[6]; 54814cf11afSPaul Mackerras } 549*06d67d54SPaul Mackerras } 55014cf11afSPaul Mackerras childregs->gpr[3] = 0; /* Result from fork() */ 55114cf11afSPaul Mackerras sp -= STACK_FRAME_OVERHEAD; 55214cf11afSPaul Mackerras 55314cf11afSPaul Mackerras /* 55414cf11afSPaul Mackerras * The way this works is that at some point in the future 55514cf11afSPaul Mackerras * some task will call _switch to switch to the new task. 55614cf11afSPaul Mackerras * That will pop off the stack frame created below and start 55714cf11afSPaul Mackerras * the new task running at ret_from_fork. The new task will 55814cf11afSPaul Mackerras * do some house keeping and then return from the fork or clone 55914cf11afSPaul Mackerras * system call, using the stack frame created above. 56014cf11afSPaul Mackerras */ 56114cf11afSPaul Mackerras sp -= sizeof(struct pt_regs); 56214cf11afSPaul Mackerras kregs = (struct pt_regs *) sp; 56314cf11afSPaul Mackerras sp -= STACK_FRAME_OVERHEAD; 56414cf11afSPaul Mackerras p->thread.ksp = sp; 56514cf11afSPaul Mackerras 566*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 567*06d67d54SPaul Mackerras if (cpu_has_feature(CPU_FTR_SLB)) { 568*06d67d54SPaul Mackerras unsigned long sp_vsid = get_kernel_vsid(sp); 569*06d67d54SPaul Mackerras 570*06d67d54SPaul Mackerras sp_vsid <<= SLB_VSID_SHIFT; 571*06d67d54SPaul Mackerras sp_vsid |= SLB_VSID_KERNEL; 572*06d67d54SPaul Mackerras if (cpu_has_feature(CPU_FTR_16M_PAGE)) 573*06d67d54SPaul Mackerras sp_vsid |= SLB_VSID_L; 574*06d67d54SPaul Mackerras 575*06d67d54SPaul Mackerras p->thread.ksp_vsid = sp_vsid; 576*06d67d54SPaul Mackerras } 577*06d67d54SPaul Mackerras 578*06d67d54SPaul Mackerras /* 579*06d67d54SPaul Mackerras * The PPC64 ABI makes use of a TOC to contain function 580*06d67d54SPaul Mackerras * pointers. The function (ret_from_except) is actually a pointer 581*06d67d54SPaul Mackerras * to the TOC entry. The first entry is a pointer to the actual 582*06d67d54SPaul Mackerras * function. 583*06d67d54SPaul Mackerras */ 584*06d67d54SPaul Mackerras kregs->nip = *((unsigned long *)ret_from_fork); 585*06d67d54SPaul Mackerras #else 586*06d67d54SPaul Mackerras kregs->nip = (unsigned long)ret_from_fork; 58714cf11afSPaul Mackerras p->thread.last_syscall = -1; 588*06d67d54SPaul Mackerras #endif 58914cf11afSPaul Mackerras 59014cf11afSPaul Mackerras return 0; 59114cf11afSPaul Mackerras } 59214cf11afSPaul Mackerras 59314cf11afSPaul Mackerras /* 59414cf11afSPaul Mackerras * Set up a thread for executing a new program 59514cf11afSPaul Mackerras */ 596*06d67d54SPaul Mackerras void start_thread(struct pt_regs *regs, unsigned long start, unsigned long sp) 59714cf11afSPaul Mackerras { 59814cf11afSPaul Mackerras set_fs(USER_DS); 599*06d67d54SPaul Mackerras 600*06d67d54SPaul Mackerras /* 601*06d67d54SPaul Mackerras * If we exec out of a kernel thread then thread.regs will not be 602*06d67d54SPaul Mackerras * set. Do it now. 603*06d67d54SPaul Mackerras */ 604*06d67d54SPaul Mackerras if (!current->thread.regs) { 605*06d67d54SPaul Mackerras unsigned long childregs = (unsigned long)current->thread_info + 606*06d67d54SPaul Mackerras THREAD_SIZE; 607*06d67d54SPaul Mackerras childregs -= sizeof(struct pt_regs); 608*06d67d54SPaul Mackerras current->thread.regs = (struct pt_regs *)childregs; 609*06d67d54SPaul Mackerras } 610*06d67d54SPaul Mackerras 61114cf11afSPaul Mackerras memset(regs->gpr, 0, sizeof(regs->gpr)); 61214cf11afSPaul Mackerras regs->ctr = 0; 61314cf11afSPaul Mackerras regs->link = 0; 61414cf11afSPaul Mackerras regs->xer = 0; 61514cf11afSPaul Mackerras regs->ccr = 0; 61614cf11afSPaul Mackerras regs->gpr[1] = sp; 617*06d67d54SPaul Mackerras 618*06d67d54SPaul Mackerras #ifdef CONFIG_PPC32 619*06d67d54SPaul Mackerras regs->mq = 0; 620*06d67d54SPaul Mackerras regs->nip = start; 62114cf11afSPaul Mackerras regs->msr = MSR_USER; 622*06d67d54SPaul Mackerras #else 623*06d67d54SPaul Mackerras if (test_thread_flag(TIF_32BIT)) { 624*06d67d54SPaul Mackerras unsigned long entry, toc, load_addr = regs->gpr[2]; 625*06d67d54SPaul Mackerras 626*06d67d54SPaul Mackerras /* start is a relocated pointer to the function descriptor for 627*06d67d54SPaul Mackerras * the elf _start routine. The first entry in the function 628*06d67d54SPaul Mackerras * descriptor is the entry address of _start and the second 629*06d67d54SPaul Mackerras * entry is the TOC value we need to use. 630*06d67d54SPaul Mackerras */ 631*06d67d54SPaul Mackerras __get_user(entry, (unsigned long __user *)start); 632*06d67d54SPaul Mackerras __get_user(toc, (unsigned long __user *)start+1); 633*06d67d54SPaul Mackerras 634*06d67d54SPaul Mackerras /* Check whether the e_entry function descriptor entries 635*06d67d54SPaul Mackerras * need to be relocated before we can use them. 636*06d67d54SPaul Mackerras */ 637*06d67d54SPaul Mackerras if (load_addr != 0) { 638*06d67d54SPaul Mackerras entry += load_addr; 639*06d67d54SPaul Mackerras toc += load_addr; 640*06d67d54SPaul Mackerras } 641*06d67d54SPaul Mackerras regs->nip = entry; 642*06d67d54SPaul Mackerras regs->gpr[2] = toc; 643*06d67d54SPaul Mackerras regs->msr = MSR_USER64; 644*06d67d54SPaul Mackerras } else { 645*06d67d54SPaul Mackerras regs->nip = start; 646*06d67d54SPaul Mackerras regs->gpr[2] = 0; 647*06d67d54SPaul Mackerras regs->msr = MSR_USER32; 648*06d67d54SPaul Mackerras } 649*06d67d54SPaul Mackerras #endif 650*06d67d54SPaul Mackerras 65114cf11afSPaul Mackerras #ifndef CONFIG_SMP 65214cf11afSPaul Mackerras if (last_task_used_math == current) 65314cf11afSPaul Mackerras last_task_used_math = NULL; 65414cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 65514cf11afSPaul Mackerras if (last_task_used_altivec == current) 65614cf11afSPaul Mackerras last_task_used_altivec = NULL; 65714cf11afSPaul Mackerras #endif 65814cf11afSPaul Mackerras #ifdef CONFIG_SPE 65914cf11afSPaul Mackerras if (last_task_used_spe == current) 66014cf11afSPaul Mackerras last_task_used_spe = NULL; 66114cf11afSPaul Mackerras #endif 66214cf11afSPaul Mackerras #endif /* CONFIG_SMP */ 66314cf11afSPaul Mackerras memset(current->thread.fpr, 0, sizeof(current->thread.fpr)); 66414cf11afSPaul Mackerras current->thread.fpscr = 0; 66514cf11afSPaul Mackerras #ifdef CONFIG_ALTIVEC 66614cf11afSPaul Mackerras memset(current->thread.vr, 0, sizeof(current->thread.vr)); 66714cf11afSPaul Mackerras memset(¤t->thread.vscr, 0, sizeof(current->thread.vscr)); 668*06d67d54SPaul Mackerras current->thread.vscr.u[3] = 0x00010000; /* Java mode disabled */ 66914cf11afSPaul Mackerras current->thread.vrsave = 0; 67014cf11afSPaul Mackerras current->thread.used_vr = 0; 67114cf11afSPaul Mackerras #endif /* CONFIG_ALTIVEC */ 67214cf11afSPaul Mackerras #ifdef CONFIG_SPE 67314cf11afSPaul Mackerras memset(current->thread.evr, 0, sizeof(current->thread.evr)); 67414cf11afSPaul Mackerras current->thread.acc = 0; 67514cf11afSPaul Mackerras current->thread.spefscr = 0; 67614cf11afSPaul Mackerras current->thread.used_spe = 0; 67714cf11afSPaul Mackerras #endif /* CONFIG_SPE */ 67814cf11afSPaul Mackerras } 67914cf11afSPaul Mackerras 68014cf11afSPaul Mackerras #define PR_FP_ALL_EXCEPT (PR_FP_EXC_DIV | PR_FP_EXC_OVF | PR_FP_EXC_UND \ 68114cf11afSPaul Mackerras | PR_FP_EXC_RES | PR_FP_EXC_INV) 68214cf11afSPaul Mackerras 68314cf11afSPaul Mackerras int set_fpexc_mode(struct task_struct *tsk, unsigned int val) 68414cf11afSPaul Mackerras { 68514cf11afSPaul Mackerras struct pt_regs *regs = tsk->thread.regs; 68614cf11afSPaul Mackerras 68714cf11afSPaul Mackerras /* This is a bit hairy. If we are an SPE enabled processor 68814cf11afSPaul Mackerras * (have embedded fp) we store the IEEE exception enable flags in 68914cf11afSPaul Mackerras * fpexc_mode. fpexc_mode is also used for setting FP exception 69014cf11afSPaul Mackerras * mode (asyn, precise, disabled) for 'Classic' FP. */ 69114cf11afSPaul Mackerras if (val & PR_FP_EXC_SW_ENABLE) { 69214cf11afSPaul Mackerras #ifdef CONFIG_SPE 69314cf11afSPaul Mackerras tsk->thread.fpexc_mode = val & 69414cf11afSPaul Mackerras (PR_FP_EXC_SW_ENABLE | PR_FP_ALL_EXCEPT); 695*06d67d54SPaul Mackerras return 0; 69614cf11afSPaul Mackerras #else 69714cf11afSPaul Mackerras return -EINVAL; 69814cf11afSPaul Mackerras #endif 699*06d67d54SPaul Mackerras } 700*06d67d54SPaul Mackerras 70114cf11afSPaul Mackerras /* on a CONFIG_SPE this does not hurt us. The bits that 70214cf11afSPaul Mackerras * __pack_fe01 use do not overlap with bits used for 70314cf11afSPaul Mackerras * PR_FP_EXC_SW_ENABLE. Additionally, the MSR[FE0,FE1] bits 70414cf11afSPaul Mackerras * on CONFIG_SPE implementations are reserved so writing to 70514cf11afSPaul Mackerras * them does not change anything */ 70614cf11afSPaul Mackerras if (val > PR_FP_EXC_PRECISE) 70714cf11afSPaul Mackerras return -EINVAL; 70814cf11afSPaul Mackerras tsk->thread.fpexc_mode = __pack_fe01(val); 70914cf11afSPaul Mackerras if (regs != NULL && (regs->msr & MSR_FP) != 0) 71014cf11afSPaul Mackerras regs->msr = (regs->msr & ~(MSR_FE0|MSR_FE1)) 71114cf11afSPaul Mackerras | tsk->thread.fpexc_mode; 71214cf11afSPaul Mackerras return 0; 71314cf11afSPaul Mackerras } 71414cf11afSPaul Mackerras 71514cf11afSPaul Mackerras int get_fpexc_mode(struct task_struct *tsk, unsigned long adr) 71614cf11afSPaul Mackerras { 71714cf11afSPaul Mackerras unsigned int val; 71814cf11afSPaul Mackerras 71914cf11afSPaul Mackerras if (tsk->thread.fpexc_mode & PR_FP_EXC_SW_ENABLE) 72014cf11afSPaul Mackerras #ifdef CONFIG_SPE 72114cf11afSPaul Mackerras val = tsk->thread.fpexc_mode; 72214cf11afSPaul Mackerras #else 72314cf11afSPaul Mackerras return -EINVAL; 72414cf11afSPaul Mackerras #endif 72514cf11afSPaul Mackerras else 72614cf11afSPaul Mackerras val = __unpack_fe01(tsk->thread.fpexc_mode); 72714cf11afSPaul Mackerras return put_user(val, (unsigned int __user *) adr); 72814cf11afSPaul Mackerras } 72914cf11afSPaul Mackerras 730*06d67d54SPaul Mackerras #define TRUNC_PTR(x) ((typeof(x))(((unsigned long)(x)) & 0xffffffff)) 731*06d67d54SPaul Mackerras 73214cf11afSPaul Mackerras int sys_clone(unsigned long clone_flags, unsigned long usp, 73314cf11afSPaul Mackerras int __user *parent_tidp, void __user *child_threadptr, 73414cf11afSPaul Mackerras int __user *child_tidp, int p6, 73514cf11afSPaul Mackerras struct pt_regs *regs) 73614cf11afSPaul Mackerras { 73714cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 73814cf11afSPaul Mackerras if (usp == 0) 73914cf11afSPaul Mackerras usp = regs->gpr[1]; /* stack pointer for child */ 740*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 741*06d67d54SPaul Mackerras if (test_thread_flag(TIF_32BIT)) { 742*06d67d54SPaul Mackerras parent_tidp = TRUNC_PTR(parent_tidp); 743*06d67d54SPaul Mackerras child_tidp = TRUNC_PTR(child_tidp); 744*06d67d54SPaul Mackerras } 745*06d67d54SPaul Mackerras #endif 74614cf11afSPaul Mackerras return do_fork(clone_flags, usp, regs, 0, parent_tidp, child_tidp); 74714cf11afSPaul Mackerras } 74814cf11afSPaul Mackerras 74914cf11afSPaul Mackerras int sys_fork(unsigned long p1, unsigned long p2, unsigned long p3, 75014cf11afSPaul Mackerras unsigned long p4, unsigned long p5, unsigned long p6, 75114cf11afSPaul Mackerras struct pt_regs *regs) 75214cf11afSPaul Mackerras { 75314cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 75414cf11afSPaul Mackerras return do_fork(SIGCHLD, regs->gpr[1], regs, 0, NULL, NULL); 75514cf11afSPaul Mackerras } 75614cf11afSPaul Mackerras 75714cf11afSPaul Mackerras int sys_vfork(unsigned long p1, unsigned long p2, unsigned long p3, 75814cf11afSPaul Mackerras unsigned long p4, unsigned long p5, unsigned long p6, 75914cf11afSPaul Mackerras struct pt_regs *regs) 76014cf11afSPaul Mackerras { 76114cf11afSPaul Mackerras CHECK_FULL_REGS(regs); 76214cf11afSPaul Mackerras return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs->gpr[1], 76314cf11afSPaul Mackerras regs, 0, NULL, NULL); 76414cf11afSPaul Mackerras } 76514cf11afSPaul Mackerras 76614cf11afSPaul Mackerras int sys_execve(unsigned long a0, unsigned long a1, unsigned long a2, 76714cf11afSPaul Mackerras unsigned long a3, unsigned long a4, unsigned long a5, 76814cf11afSPaul Mackerras struct pt_regs *regs) 76914cf11afSPaul Mackerras { 77014cf11afSPaul Mackerras int error; 77114cf11afSPaul Mackerras char *filename; 77214cf11afSPaul Mackerras 77314cf11afSPaul Mackerras filename = getname((char __user *) a0); 77414cf11afSPaul Mackerras error = PTR_ERR(filename); 77514cf11afSPaul Mackerras if (IS_ERR(filename)) 77614cf11afSPaul Mackerras goto out; 77714cf11afSPaul Mackerras flush_fp_to_thread(current); 77814cf11afSPaul Mackerras flush_altivec_to_thread(current); 77914cf11afSPaul Mackerras flush_spe_to_thread(current); 78020c8c210SPaul Mackerras error = do_execve(filename, (char __user * __user *) a1, 78120c8c210SPaul Mackerras (char __user * __user *) a2, regs); 78214cf11afSPaul Mackerras if (error == 0) { 78314cf11afSPaul Mackerras task_lock(current); 78414cf11afSPaul Mackerras current->ptrace &= ~PT_DTRACE; 78514cf11afSPaul Mackerras task_unlock(current); 78614cf11afSPaul Mackerras } 78714cf11afSPaul Mackerras putname(filename); 78814cf11afSPaul Mackerras out: 78914cf11afSPaul Mackerras return error; 79014cf11afSPaul Mackerras } 79114cf11afSPaul Mackerras 79214cf11afSPaul Mackerras static int validate_sp(unsigned long sp, struct task_struct *p, 79314cf11afSPaul Mackerras unsigned long nbytes) 79414cf11afSPaul Mackerras { 79514cf11afSPaul Mackerras unsigned long stack_page = (unsigned long)p->thread_info; 79614cf11afSPaul Mackerras 79714cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 79814cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 79914cf11afSPaul Mackerras return 1; 80014cf11afSPaul Mackerras 80114cf11afSPaul Mackerras #ifdef CONFIG_IRQSTACKS 80214cf11afSPaul Mackerras stack_page = (unsigned long) hardirq_ctx[task_cpu(p)]; 80314cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 80414cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 80514cf11afSPaul Mackerras return 1; 80614cf11afSPaul Mackerras 80714cf11afSPaul Mackerras stack_page = (unsigned long) softirq_ctx[task_cpu(p)]; 80814cf11afSPaul Mackerras if (sp >= stack_page + sizeof(struct thread_struct) 80914cf11afSPaul Mackerras && sp <= stack_page + THREAD_SIZE - nbytes) 81014cf11afSPaul Mackerras return 1; 81114cf11afSPaul Mackerras #endif 81214cf11afSPaul Mackerras 81314cf11afSPaul Mackerras return 0; 81414cf11afSPaul Mackerras } 81514cf11afSPaul Mackerras 816*06d67d54SPaul Mackerras #ifdef CONFIG_PPC64 817*06d67d54SPaul Mackerras #define MIN_STACK_FRAME 112 /* same as STACK_FRAME_OVERHEAD, in fact */ 818*06d67d54SPaul Mackerras #define FRAME_LR_SAVE 2 819*06d67d54SPaul Mackerras #define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD + 288) 820*06d67d54SPaul Mackerras #define REGS_MARKER 0x7265677368657265ul 821*06d67d54SPaul Mackerras #define FRAME_MARKER 12 822*06d67d54SPaul Mackerras #else 823*06d67d54SPaul Mackerras #define MIN_STACK_FRAME 16 824*06d67d54SPaul Mackerras #define FRAME_LR_SAVE 1 825*06d67d54SPaul Mackerras #define INT_FRAME_SIZE (sizeof(struct pt_regs) + STACK_FRAME_OVERHEAD) 826*06d67d54SPaul Mackerras #define REGS_MARKER 0x72656773ul 827*06d67d54SPaul Mackerras #define FRAME_MARKER 2 828*06d67d54SPaul Mackerras #endif 82914cf11afSPaul Mackerras 830*06d67d54SPaul Mackerras unsigned long get_wchan(struct task_struct *p) 831*06d67d54SPaul Mackerras { 832*06d67d54SPaul Mackerras unsigned long ip, sp; 833*06d67d54SPaul Mackerras int count = 0; 834*06d67d54SPaul Mackerras 835*06d67d54SPaul Mackerras if (!p || p == current || p->state == TASK_RUNNING) 836*06d67d54SPaul Mackerras return 0; 837*06d67d54SPaul Mackerras 838*06d67d54SPaul Mackerras sp = p->thread.ksp; 839*06d67d54SPaul Mackerras if (!validate_sp(sp, p, MIN_STACK_FRAME)) 840*06d67d54SPaul Mackerras return 0; 841*06d67d54SPaul Mackerras 842*06d67d54SPaul Mackerras do { 843*06d67d54SPaul Mackerras sp = *(unsigned long *)sp; 844*06d67d54SPaul Mackerras if (!validate_sp(sp, p, MIN_STACK_FRAME)) 845*06d67d54SPaul Mackerras return 0; 846*06d67d54SPaul Mackerras if (count > 0) { 847*06d67d54SPaul Mackerras ip = ((unsigned long *)sp)[FRAME_LR_SAVE]; 848*06d67d54SPaul Mackerras if (!in_sched_functions(ip)) 849*06d67d54SPaul Mackerras return ip; 850*06d67d54SPaul Mackerras } 851*06d67d54SPaul Mackerras } while (count++ < 16); 852*06d67d54SPaul Mackerras return 0; 853*06d67d54SPaul Mackerras } 854*06d67d54SPaul Mackerras EXPORT_SYMBOL(get_wchan); 855*06d67d54SPaul Mackerras 856*06d67d54SPaul Mackerras static int kstack_depth_to_print = 64; 85714cf11afSPaul Mackerras 85814cf11afSPaul Mackerras void show_stack(struct task_struct *tsk, unsigned long *stack) 85914cf11afSPaul Mackerras { 860*06d67d54SPaul Mackerras unsigned long sp, ip, lr, newsp; 86114cf11afSPaul Mackerras int count = 0; 862*06d67d54SPaul Mackerras int firstframe = 1; 86314cf11afSPaul Mackerras 86414cf11afSPaul Mackerras sp = (unsigned long) stack; 86514cf11afSPaul Mackerras if (tsk == NULL) 86614cf11afSPaul Mackerras tsk = current; 86714cf11afSPaul Mackerras if (sp == 0) { 86814cf11afSPaul Mackerras if (tsk == current) 86914cf11afSPaul Mackerras asm("mr %0,1" : "=r" (sp)); 87014cf11afSPaul Mackerras else 87114cf11afSPaul Mackerras sp = tsk->thread.ksp; 87214cf11afSPaul Mackerras } 87314cf11afSPaul Mackerras 874*06d67d54SPaul Mackerras lr = 0; 875*06d67d54SPaul Mackerras printk("Call Trace:\n"); 87614cf11afSPaul Mackerras do { 877*06d67d54SPaul Mackerras if (!validate_sp(sp, tsk, MIN_STACK_FRAME)) 878*06d67d54SPaul Mackerras return; 879*06d67d54SPaul Mackerras 880*06d67d54SPaul Mackerras stack = (unsigned long *) sp; 881*06d67d54SPaul Mackerras newsp = stack[0]; 882*06d67d54SPaul Mackerras ip = stack[FRAME_LR_SAVE]; 883*06d67d54SPaul Mackerras if (!firstframe || ip != lr) { 884*06d67d54SPaul Mackerras printk("["REG"] ["REG"] ", sp, ip); 885*06d67d54SPaul Mackerras print_symbol("%s", ip); 886*06d67d54SPaul Mackerras if (firstframe) 887*06d67d54SPaul Mackerras printk(" (unreliable)"); 888*06d67d54SPaul Mackerras printk("\n"); 88914cf11afSPaul Mackerras } 890*06d67d54SPaul Mackerras firstframe = 0; 891*06d67d54SPaul Mackerras 892*06d67d54SPaul Mackerras /* 893*06d67d54SPaul Mackerras * See if this is an exception frame. 894*06d67d54SPaul Mackerras * We look for the "regshere" marker in the current frame. 895*06d67d54SPaul Mackerras */ 896*06d67d54SPaul Mackerras if (validate_sp(sp, tsk, INT_FRAME_SIZE) 897*06d67d54SPaul Mackerras && stack[FRAME_MARKER] == REGS_MARKER) { 898*06d67d54SPaul Mackerras struct pt_regs *regs = (struct pt_regs *) 899*06d67d54SPaul Mackerras (sp + STACK_FRAME_OVERHEAD); 900*06d67d54SPaul Mackerras printk("--- Exception: %lx", regs->trap); 901*06d67d54SPaul Mackerras print_symbol(" at %s\n", regs->nip); 902*06d67d54SPaul Mackerras lr = regs->link; 903*06d67d54SPaul Mackerras print_symbol(" LR = %s\n", lr); 904*06d67d54SPaul Mackerras firstframe = 1; 90514cf11afSPaul Mackerras } 906*06d67d54SPaul Mackerras 907*06d67d54SPaul Mackerras sp = newsp; 908*06d67d54SPaul Mackerras } while (count++ < kstack_depth_to_print); 909*06d67d54SPaul Mackerras } 910*06d67d54SPaul Mackerras 911*06d67d54SPaul Mackerras void dump_stack(void) 912*06d67d54SPaul Mackerras { 913*06d67d54SPaul Mackerras show_stack(current, NULL); 914*06d67d54SPaul Mackerras } 915*06d67d54SPaul Mackerras EXPORT_SYMBOL(dump_stack); 916