powerpc/cpumask: Update some comments
[safe/jmp/linux-2.6] / arch / powerpc / kernel / process.c
index d52ded3..9d255b4 100644 (file)
 #include <linux/mqueue.h>
 #include <linux/hardirq.h>
 #include <linux/utsname.h>
+#include <linux/ftrace.h>
+#include <linux/kernel_stat.h>
+#include <linux/personality.h>
+#include <linux/random.h>
 
 #include <asm/pgtable.h>
 #include <asm/uaccess.h>
@@ -47,6 +51,8 @@
 #ifdef CONFIG_PPC64
 #include <asm/firmware.h>
 #endif
+#include <linux/kprobes.h>
+#include <linux/kdebug.h>
 
 extern unsigned long _get_SP(void);
 
@@ -105,29 +111,6 @@ void enable_kernel_fp(void)
 }
 EXPORT_SYMBOL(enable_kernel_fp);
 
-int dump_task_fpu(struct task_struct *tsk, elf_fpregset_t *fpregs)
-{
-#ifdef CONFIG_VSX
-       int i;
-       elf_fpreg_t *reg;
-#endif
-
-       if (!tsk->thread.regs)
-               return 0;
-       flush_fp_to_thread(current);
-
-#ifdef CONFIG_VSX
-       reg = (elf_fpreg_t *)fpregs;
-       for (i = 0; i < ELF_NFPREG - 1; i++, reg++)
-               *reg = tsk->thread.TS_FPR(i);
-       memcpy(reg, &tsk->thread.fpscr, sizeof(elf_fpreg_t));
-#else
-       memcpy(fpregs, &tsk->thread.TS_FPR(0), sizeof(*fpregs));
-#endif
-
-       return 1;
-}
-
 #ifdef CONFIG_ALTIVEC
 void enable_kernel_altivec(void)
 {
@@ -161,35 +144,6 @@ void flush_altivec_to_thread(struct task_struct *tsk)
                preempt_enable();
        }
 }
-
-int dump_task_altivec(struct task_struct *tsk, elf_vrreg_t *vrregs)
-{
-       /* ELF_NVRREG includes the VSCR and VRSAVE which we need to save
-        * separately, see below */
-       const int nregs = ELF_NVRREG - 2;
-       elf_vrreg_t *reg;
-       u32 *dest;
-
-       if (tsk == current)
-               flush_altivec_to_thread(tsk);
-
-       reg = (elf_vrreg_t *)vrregs;
-
-       /* copy the 32 vr registers */
-       memcpy(reg, &tsk->thread.vr[0], nregs * sizeof(*reg));
-       reg += nregs;
-
-       /* copy the vscr */
-       memcpy(reg, &tsk->thread.vscr, sizeof(*reg));
-       reg++;
-
-       /* vrsave is stored in the high 32bit slot of the final 128bits */
-       memset(reg, 0, sizeof(*reg));
-       dest = (u32 *)reg;
-       *dest = tsk->thread.vrsave;
-
-       return 1;
-}
 #endif /* CONFIG_ALTIVEC */
 
 #ifdef CONFIG_VSX
@@ -211,6 +165,13 @@ void enable_kernel_vsx(void)
 EXPORT_SYMBOL(enable_kernel_vsx);
 #endif
 
+void giveup_vsx(struct task_struct *tsk)
+{
+       giveup_fpu(tsk);
+       giveup_altivec(tsk);
+       __giveup_vsx(tsk);
+}
+
 void flush_vsx_to_thread(struct task_struct *tsk)
 {
        if (tsk->thread.regs) {
@@ -224,48 +185,8 @@ void flush_vsx_to_thread(struct task_struct *tsk)
                preempt_enable();
        }
 }
-
-/*
- * This dumps the lower half 64bits of the first 32 VSX registers.
- * This needs to be called with dump_task_fp and dump_task_altivec to
- * get all the VSX state.
- */
-int dump_task_vsx(struct task_struct *tsk, elf_vrreg_t *vrregs)
-{
-       elf_vrreg_t *reg;
-       double buf[32];
-       int i;
-
-       if (tsk == current)
-               flush_vsx_to_thread(tsk);
-
-       reg = (elf_vrreg_t *)vrregs;
-
-       for (i = 0; i < 32 ; i++)
-               buf[i] = current->thread.fpr[i][TS_VSRLOWOFFSET];
-       memcpy(reg, buf, sizeof(buf));
-
-       return 1;
-}
 #endif /* CONFIG_VSX */
 
-int dump_task_vector(struct task_struct *tsk, elf_vrregset_t *vrregs)
-{
-       int rc = 0;
-       elf_vrreg_t *regs = (elf_vrreg_t *)vrregs;
-#ifdef CONFIG_ALTIVEC
-       rc = dump_task_altivec(tsk, regs);
-       if (rc)
-               return rc;
-       regs += ELF_NVRREG;
-#endif
-
-#ifdef CONFIG_VSX
-       rc = dump_task_vsx(tsk, regs);
-#endif
-       return rc;
-}
-
 #ifdef CONFIG_SPE
 
 void enable_kernel_spe(void)
@@ -296,14 +217,6 @@ void flush_spe_to_thread(struct task_struct *tsk)
                preempt_enable();
        }
 }
-
-int dump_spe(struct pt_regs *regs, elf_vrregset_t *evrregs)
-{
-       flush_spe_to_thread(current);
-       /* We copy u32 evr[32] + u64 acc + u32 spefscr -> 35 */
-       memcpy(evrregs, &current->thread.evr[0], sizeof(u32) * 35);
-       return 1;
-}
 #endif /* CONFIG_SPE */
 
 #ifndef CONFIG_SMP
@@ -332,21 +245,140 @@ void discard_lazy_cpu_state(void)
 }
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+void do_send_trap(struct pt_regs *regs, unsigned long address,
+                 unsigned long error_code, int signal_code, int breakpt)
+{
+       siginfo_t info;
+
+       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+                       11, SIGSEGV) == NOTIFY_STOP)
+               return;
+
+       /* Deliver the signal to userspace */
+       info.si_signo = SIGTRAP;
+       info.si_errno = breakpt;        /* breakpoint or watchpoint id */
+       info.si_code = signal_code;
+       info.si_addr = (void __user *)address;
+       force_sig_info(SIGTRAP, &info, current);
+}
+#else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
+void do_dabr(struct pt_regs *regs, unsigned long address,
+                   unsigned long error_code)
+{
+       siginfo_t info;
+
+       if (notify_die(DIE_DABR_MATCH, "dabr_match", regs, error_code,
+                       11, SIGSEGV) == NOTIFY_STOP)
+               return;
+
+       if (debugger_dabr_match(regs))
+               return;
+
+       /* Clear the DABR */
+       set_dabr(0);
+
+       /* Deliver the signal to userspace */
+       info.si_signo = SIGTRAP;
+       info.si_errno = 0;
+       info.si_code = TRAP_HWBKPT;
+       info.si_addr = (void __user *)address;
+       force_sig_info(SIGTRAP, &info, current);
+}
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
+
 static DEFINE_PER_CPU(unsigned long, current_dabr);
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+/*
+ * Set the debug registers back to their default "safe" values.
+ */
+static void set_debug_reg_defaults(struct thread_struct *thread)
+{
+       thread->iac1 = thread->iac2 = 0;
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       thread->iac3 = thread->iac4 = 0;
+#endif
+       thread->dac1 = thread->dac2 = 0;
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+       thread->dvc1 = thread->dvc2 = 0;
+#endif
+       thread->dbcr0 = 0;
+#ifdef CONFIG_BOOKE
+       /*
+        * Force User/Supervisor bits to b11 (user-only MSR[PR]=1)
+        */
+       thread->dbcr1 = DBCR1_IAC1US | DBCR1_IAC2US |   \
+                       DBCR1_IAC3US | DBCR1_IAC4US;
+       /*
+        * Force Data Address Compare User/Supervisor bits to be User-only
+        * (0b11 MSR[PR]=1) and set all other bits in DBCR2 register to be 0.
+        */
+       thread->dbcr2 = DBCR2_DAC1US | DBCR2_DAC2US;
+#else
+       thread->dbcr1 = 0;
+#endif
+}
+
+static void prime_debug_regs(struct thread_struct *thread)
+{
+       mtspr(SPRN_IAC1, thread->iac1);
+       mtspr(SPRN_IAC2, thread->iac2);
+#if CONFIG_PPC_ADV_DEBUG_IACS > 2
+       mtspr(SPRN_IAC3, thread->iac3);
+       mtspr(SPRN_IAC4, thread->iac4);
+#endif
+       mtspr(SPRN_DAC1, thread->dac1);
+       mtspr(SPRN_DAC2, thread->dac2);
+#if CONFIG_PPC_ADV_DEBUG_DVCS > 0
+       mtspr(SPRN_DVC1, thread->dvc1);
+       mtspr(SPRN_DVC2, thread->dvc2);
+#endif
+       mtspr(SPRN_DBCR0, thread->dbcr0);
+       mtspr(SPRN_DBCR1, thread->dbcr1);
+#ifdef CONFIG_BOOKE
+       mtspr(SPRN_DBCR2, thread->dbcr2);
+#endif
+}
+/*
+ * Unless neither the old or new thread are making use of the
+ * debug registers, set the debug registers from the values
+ * stored in the new thread.
+ */
+static void switch_booke_debug_regs(struct thread_struct *new_thread)
+{
+       if ((current->thread.dbcr0 & DBCR0_IDM)
+               || (new_thread->dbcr0 & DBCR0_IDM))
+                       prime_debug_regs(new_thread);
+}
+#else  /* !CONFIG_PPC_ADV_DEBUG_REGS */
+static void set_debug_reg_defaults(struct thread_struct *thread)
+{
+       if (thread->dabr) {
+               thread->dabr = 0;
+               set_dabr(0);
+       }
+}
+#endif /* CONFIG_PPC_ADV_DEBUG_REGS */
+
 int set_dabr(unsigned long dabr)
 {
        __get_cpu_var(current_dabr) = dabr;
 
-#ifdef CONFIG_PPC_MERGE                /* XXX for now */
        if (ppc_md.set_dabr)
                return ppc_md.set_dabr(dabr);
-#endif
 
        /* XXX should we have a CPU_FTR_HAS_DABR ? */
-#if defined(CONFIG_PPC64) || defined(CONFIG_6xx)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+       mtspr(SPRN_DAC1, dabr);
+#ifdef CONFIG_PPC_47x
+       isync();
+#endif
+#elif defined(CONFIG_PPC_BOOK3S)
        mtspr(SPRN_DABR, dabr);
 #endif
+
+
        return 0;
 }
 
@@ -390,7 +422,8 @@ struct task_struct *__switch_to(struct task_struct *prev,
 #endif /* CONFIG_ALTIVEC */
 #ifdef CONFIG_VSX
        if (prev->thread.regs && (prev->thread.regs->msr & MSR_VSX))
-               giveup_vsx(prev);
+               /* VMX and FPU registers are already save here */
+               __giveup_vsx(prev);
 #endif /* CONFIG_VSX */
 #ifdef CONFIG_SPE
        /*
@@ -426,8 +459,13 @@ struct task_struct *__switch_to(struct task_struct *prev,
 
 #endif /* CONFIG_SMP */
 
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
+       switch_booke_debug_regs(&new->thread);
+#else
        if (unlikely(__get_cpu_var(current_dabr) != new->thread.dabr))
                set_dabr(new->thread.dabr);
+#endif
+
 
        new_thread = &new->thread;
        old_thread = &current->thread;
@@ -519,6 +557,8 @@ static struct regbit {
        {MSR_VEC,       "VEC"},
        {MSR_VSX,       "VSX"},
        {MSR_ME,        "ME"},
+       {MSR_CE,        "CE"},
+       {MSR_DE,        "DE"},
        {MSR_IR,        "IR"},
        {MSR_DR,        "DR"},
        {0,             NULL}
@@ -560,7 +600,7 @@ void show_regs(struct pt_regs * regs)
        printk("  CR: %08lx  XER: %08lx\n", regs->ccr, regs->xer);
        trap = TRAP(regs);
        if (trap == 0x300 || trap == 0x600)
-#if defined(CONFIG_4xx) || defined(CONFIG_BOOKE)
+#ifdef CONFIG_PPC_ADV_DEBUG_REGS
                printk("DEAR: "REG", ESR: "REG"\n", regs->dar, regs->dsisr);
 #else
                printk("DAR: "REG", DSISR: "REG"\n", regs->dar, regs->dsisr);
@@ -574,7 +614,7 @@ void show_regs(struct pt_regs * regs)
 
        for (i = 0;  i < 32;  i++) {
                if ((i % REGS_PER_LINE) == 0)
-                       printk("\n" KERN_INFO "GPR%02d: ", i);
+                       printk("\nGPR%02d: ", i);
                printk(REG " ", regs->gpr[i]);
                if (i == LAST_VOLATILE && !FULL_REGS(regs))
                        break;
@@ -585,10 +625,8 @@ void show_regs(struct pt_regs * regs)
         * Lookup NIP late so we have the best change of getting the
         * above info out without failing
         */
-       printk("NIP ["REG"] ", regs->nip);
-       print_symbol("%s\n", regs->nip);
-       printk("LR ["REG"] ", regs->link);
-       print_symbol("%s\n", regs->link);
+       printk("NIP ["REG"] %pS\n", regs->nip, (void *)regs->nip);
+       printk("LR ["REG"] %pS\n", regs->link, (void *)regs->link);
 #endif
        show_stack(current, (unsigned long *) regs->gpr[1]);
        if (!user_mode(regs))
@@ -602,24 +640,9 @@ void exit_thread(void)
 
 void flush_thread(void)
 {
-#ifdef CONFIG_PPC64
-       struct thread_info *t = current_thread_info();
-
-       if (test_ti_thread_flag(t, TIF_ABI_PENDING)) {
-               clear_ti_thread_flag(t, TIF_ABI_PENDING);
-               if (test_ti_thread_flag(t, TIF_32BIT))
-                       clear_ti_thread_flag(t, TIF_32BIT);
-               else
-                       set_ti_thread_flag(t, TIF_32BIT);
-       }
-#endif
-
        discard_lazy_cpu_state();
 
-       if (current->thread.dabr) {
-               current->thread.dabr = 0;
-               set_dabr(0);
-       }
+       set_debug_reg_defaults(&current->thread);
 }
 
 void
@@ -642,7 +665,7 @@ void prepare_to_copy(struct task_struct *tsk)
 /*
  * Copy a thread..
  */
-int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
+int copy_thread(unsigned long clone_flags, unsigned long usp,
                unsigned long unused, struct task_struct *p,
                struct pt_regs *regs)
 {
@@ -694,7 +717,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        p->thread.ksp_limit = (unsigned long)task_stack_page(p) +
                                _ALIGN_UP(sizeof(struct thread_info), 16);
 
-#ifdef CONFIG_PPC64
+#ifdef CONFIG_PPC_STD_MMU_64
        if (cpu_has_feature(CPU_FTR_SLB)) {
                unsigned long sp_vsid;
                unsigned long llp = mmu_psize_defs[mmu_linear_psize].sllp;
@@ -708,6 +731,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
                sp_vsid |= SLB_VSID_KERNEL | llp;
                p->thread.ksp_vsid = sp_vsid;
        }
+#endif /* CONFIG_PPC_STD_MMU_64 */
 
        /*
         * The PPC64 ABI makes use of a TOC to contain function 
@@ -715,6 +739,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
         * to the TOC entry.  The first entry is a pointer to the actual
         * function.
         */
+#ifdef CONFIG_PPC64
        kregs->nip = *((unsigned long *)ret_from_fork);
 #else
        kregs->nip = (unsigned long)ret_from_fork;
@@ -1048,13 +1073,25 @@ unsigned long get_wchan(struct task_struct *p)
        return 0;
 }
 
-static int kstack_depth_to_print = 64;
+static int kstack_depth_to_print = CONFIG_PRINT_STACK_DEPTH;
 
 void show_stack(struct task_struct *tsk, unsigned long *stack)
 {
        unsigned long sp, ip, lr, newsp;
        int count = 0;
        int firstframe = 1;
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+       int curr_frame = current->curr_ret_stack;
+       extern void return_to_handler(void);
+       unsigned long rth = (unsigned long)return_to_handler;
+       unsigned long mrth = -1;
+#ifdef CONFIG_PPC64
+       extern void mod_return_to_handler(void);
+       rth = *(unsigned long *)rth;
+       mrth = (unsigned long)mod_return_to_handler;
+       mrth = *(unsigned long *)mrth;
+#endif
+#endif
 
        sp = (unsigned long) stack;
        if (tsk == NULL)
@@ -1076,8 +1113,14 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
                newsp = stack[0];
                ip = stack[STACK_FRAME_LR_SAVE];
                if (!firstframe || ip != lr) {
-                       printk("["REG"] ["REG"] ", sp, ip);
-                       print_symbol("%s", ip);
+                       printk("["REG"] ["REG"] %pS", sp, ip, (void *)ip);
+#ifdef CONFIG_FUNCTION_GRAPH_TRACER
+                       if ((ip == rth || ip == mrth) && curr_frame >= 0) {
+                               printk(" (%pS)",
+                                      (void *)current->ret_stack[curr_frame].ret);
+                               curr_frame--;
+                       }
+#endif
                        if (firstframe)
                                printk(" (unreliable)");
                        printk("\n");
@@ -1092,10 +1135,9 @@ void show_stack(struct task_struct *tsk, unsigned long *stack)
                    && stack[STACK_FRAME_MARKER] == STACK_FRAME_REGS_MARKER) {
                        struct pt_regs *regs = (struct pt_regs *)
                                (sp + STACK_FRAME_OVERHEAD);
-                       printk("--- Exception: %lx", regs->trap);
-                       print_symbol(" at %s\n", regs->nip);
                        lr = regs->link;
-                       print_symbol("    LR = %s\n", lr);
+                       printk("--- Exception: %lx at %pS\n    LR = %pS\n",
+                              regs->trap, (void *)regs->nip, (void *)lr);
                        firstframe = 1;
                }
 
@@ -1171,3 +1213,58 @@ void thread_info_cache_init(void)
 }
 
 #endif /* THREAD_SHIFT < PAGE_SHIFT */
+
+unsigned long arch_align_stack(unsigned long sp)
+{
+       if (!(current->personality & ADDR_NO_RANDOMIZE) && randomize_va_space)
+               sp -= get_random_int() & ~PAGE_MASK;
+       return sp & ~0xf;
+}
+
+static inline unsigned long brk_rnd(void)
+{
+        unsigned long rnd = 0;
+
+       /* 8MB for 32bit, 1GB for 64bit */
+       if (is_32bit_task())
+               rnd = (long)(get_random_int() % (1<<(23-PAGE_SHIFT)));
+       else
+               rnd = (long)(get_random_int() % (1<<(30-PAGE_SHIFT)));
+
+       return rnd << PAGE_SHIFT;
+}
+
+unsigned long arch_randomize_brk(struct mm_struct *mm)
+{
+       unsigned long base = mm->brk;
+       unsigned long ret;
+
+#ifdef CONFIG_PPC_STD_MMU_64
+       /*
+        * If we are using 1TB segments and we are allowed to randomise
+        * the heap, we can put it above 1TB so it is backed by a 1TB
+        * segment. Otherwise the heap will be in the bottom 1TB
+        * which always uses 256MB segments and this may result in a
+        * performance penalty.
+        */
+       if (!is_32bit_task() && (mmu_highuser_ssize == MMU_SEGSIZE_1T))
+               base = max_t(unsigned long, mm->brk, 1UL << SID_SHIFT_1T);
+#endif
+
+       ret = PAGE_ALIGN(base + brk_rnd());
+
+       if (ret < mm->brk)
+               return mm->brk;
+
+       return ret;
+}
+
+unsigned long randomize_et_dyn(unsigned long base)
+{
+       unsigned long ret = PAGE_ALIGN(base + brk_rnd());
+
+       if (ret < base)
+               return base;
+
+       return ret;
+}