dump_stack: unify debug information printed by show_regs()
[linux-3.10.git] / arch / alpha / kernel / process.c
index 7acad70..ab80a80 100644 (file)
@@ -8,33 +8,30 @@
  * This file handles the architecture-dependent parts of process handling.
  */
 
-#include <linux/config.h>
 #include <linux/errno.h>
 #include <linux/module.h>
 #include <linux/sched.h>
 #include <linux/kernel.h>
 #include <linux/mm.h>
 #include <linux/smp.h>
-#include <linux/smp_lock.h>
 #include <linux/stddef.h>
 #include <linux/unistd.h>
 #include <linux/ptrace.h>
-#include <linux/slab.h>
 #include <linux/user.h>
-#include <linux/a.out.h>
-#include <linux/utsname.h>
 #include <linux/time.h>
 #include <linux/major.h>
 #include <linux/stat.h>
+#include <linux/vt.h>
 #include <linux/mman.h>
 #include <linux/elfcore.h>
 #include <linux/reboot.h>
 #include <linux/tty.h>
 #include <linux/console.h>
+#include <linux/slab.h>
+#include <linux/rcupdate.h>
 
 #include <asm/reg.h>
 #include <asm/uaccess.h>
-#include <asm/system.h>
 #include <asm/io.h>
 #include <asm/pgtable.h>
 #include <asm/hwrpb.h>
  * Power off function, if any
  */
 void (*pm_power_off)(void) = machine_power_off;
-
-void
-cpu_idle(void)
-{
-       set_thread_flag(TIF_POLLING_NRFLAG);
-
-       while (1) {
-               /* FIXME -- EV6 and LCA45 know how to power down
-                  the CPU.  */
-
-               while (!need_resched())
-                       cpu_relax();
-               schedule();
-       }
-}
-
+EXPORT_SYMBOL(pm_power_off);
 
 struct halt_info {
        int mode;
@@ -94,7 +76,8 @@ common_shutdown_1(void *generic_ptr)
        if (cpuid != boot_cpuid) {
                flags |= 0x00040000UL; /* "remain halted" */
                *pflags = flags;
-               clear_bit(cpuid, &cpu_present_mask);
+               set_cpu_present(cpuid, false);
+               set_cpu_possible(cpuid, false);
                halt();
        }
 #endif
@@ -120,8 +103,9 @@ common_shutdown_1(void *generic_ptr)
 
 #ifdef CONFIG_SMP
        /* Wait for the secondaries to halt. */
-       cpu_clear(boot_cpuid, cpu_possible_map);
-       while (cpus_weight(cpu_possible_map))
+       set_cpu_present(boot_cpuid, false);
+       set_cpu_possible(boot_cpuid, false);
+       while (cpumask_weight(cpu_present_mask))
                barrier();
 #endif
 
@@ -161,7 +145,7 @@ common_shutdown(int mode, char *restart_cmd)
        struct halt_info args;
        args.mode = mode;
        args.restart_cmd = restart_cmd;
-       on_each_cpu(common_shutdown_1, &args, 1, 0);
+       on_each_cpu(common_shutdown_1, &args, 0);
 }
 
 void
@@ -191,6 +175,7 @@ machine_power_off(void)
 void
 show_regs(struct pt_regs *regs)
 {
+       show_regs_print_info(KERN_DEFAULT);
        dik_show_regs(regs, NULL);
 }
 
@@ -200,11 +185,11 @@ show_regs(struct pt_regs *regs)
 void
 start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
 {
-       set_fs(USER_DS);
        regs->pc = pc;
        regs->ps = 8;
        wrusp(sp);
 }
+EXPORT_SYMBOL(start_thread);
 
 /*
  * Free current thread data structures etc..
@@ -232,152 +217,57 @@ release_thread(struct task_struct *dead_task)
 }
 
 /*
- * "alpha_clone()".. By the time we get here, the
- * non-volatile registers have also been saved on the
- * stack. We do some ugly pointer stuff here.. (see
- * also copy_thread)
- *
- * Notice that "fork()" is implemented in terms of clone,
- * with parameters (SIGCHLD, 0).
- */
-int
-alpha_clone(unsigned long clone_flags, unsigned long usp,
-           int __user *parent_tid, int __user *child_tid,
-           unsigned long tls_value, struct pt_regs *regs)
-{
-       if (!usp)
-               usp = rdusp();
-
-       return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
-}
-
-int
-alpha_vfork(struct pt_regs *regs)
-{
-       return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, rdusp(),
-                      regs, 0, NULL, NULL);
-}
-
-/*
  * Copy an alpha thread..
- *
- * Note the "stack_offset" stuff: when returning to kernel mode, we need
- * to have some extra stack-space for the kernel stack that still exists
- * after the "ret_from_fork".  When returning to user mode, we only want
- * the space needed by the syscall stack frame (ie "struct pt_regs").
- * Use the passed "regs" pointer to determine how much space we need
- * for a kernel fork().
  */
 
 int
-copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
-           unsigned long unused,
-           struct task_struct * p, struct pt_regs * regs)
+copy_thread(unsigned long clone_flags, unsigned long usp,
+           unsigned long arg,
+           struct task_struct *p)
 {
        extern void ret_from_fork(void);
+       extern void ret_from_kernel_thread(void);
+
+       struct thread_info *childti = task_thread_info(p);
+       struct pt_regs *childregs = task_pt_regs(p);
+       struct pt_regs *regs = current_pt_regs();
+       struct switch_stack *childstack, *stack;
 
-       struct thread_info *childti = p->thread_info;
-       struct pt_regs * childregs;
-       struct switch_stack * childstack, *stack;
-       unsigned long stack_offset, settls;
-
-       stack_offset = PAGE_SIZE - sizeof(struct pt_regs);
-       if (!(regs->ps & 8))
-               stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
-       childregs = (struct pt_regs *)
-         (stack_offset + PAGE_SIZE + (long) childti);
-               
-       *childregs = *regs;
-       settls = regs->r20;
-       childregs->r0 = 0;
-       childregs->r19 = 0;
-       childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
-       regs->r20 = 0;
-       stack = ((struct switch_stack *) regs) - 1;
        childstack = ((struct switch_stack *) childregs) - 1;
-       *childstack = *stack;
-       childstack->r26 = (unsigned long) ret_from_fork;
-       childti->pcb.usp = usp;
        childti->pcb.ksp = (unsigned long) childstack;
        childti->pcb.flags = 1; /* set FEN, clear everything else */
 
-       /* Set a new TLS for the child thread?  Peek back into the
-          syscall arguments that we saved on syscall entry.  Oops,
-          except we'd have clobbered it with the parent/child set
-          of r20.  Read the saved copy.  */
+       if (unlikely(p->flags & PF_KTHREAD)) {
+               /* kernel thread */
+               memset(childstack, 0,
+                       sizeof(struct switch_stack) + sizeof(struct pt_regs));
+               childstack->r26 = (unsigned long) ret_from_kernel_thread;
+               childstack->r9 = usp;   /* function */
+               childstack->r10 = arg;
+               childregs->hae = alpha_mv.hae_cache,
+               childti->pcb.usp = 0;
+               return 0;
+       }
        /* Note: if CLONE_SETTLS is not set, then we must inherit the
           value from the parent, which will have been set by the block
           copy in dup_task_struct.  This is non-intuitive, but is
           required for proper operation in the case of a threaded
           application calling fork.  */
        if (clone_flags & CLONE_SETTLS)
-               childti->pcb.unique = settls;
-
+               childti->pcb.unique = regs->r20;
+       childti->pcb.usp = usp ?: rdusp();
+       *childregs = *regs;
+       childregs->r0 = 0;
+       childregs->r19 = 0;
+       childregs->r20 = 1;     /* OSF/1 has some strange fork() semantics.  */
+       regs->r20 = 0;
+       stack = ((struct switch_stack *) regs) - 1;
+       *childstack = *stack;
+       childstack->r26 = (unsigned long) ret_from_fork;
        return 0;
 }
 
 /*
- * Fill in the user structure for an ECOFF core dump.
- */
-void
-dump_thread(struct pt_regs * pt, struct user * dump)
-{
-       /* switch stack follows right below pt_regs: */
-       struct switch_stack * sw = ((struct switch_stack *) pt) - 1;
-
-       dump->magic = CMAGIC;
-       dump->start_code  = current->mm->start_code;
-       dump->start_data  = current->mm->start_data;
-       dump->start_stack = rdusp() & ~(PAGE_SIZE - 1);
-       dump->u_tsize = ((current->mm->end_code - dump->start_code)
-                        >> PAGE_SHIFT);
-       dump->u_dsize = ((current->mm->brk + PAGE_SIZE-1 - dump->start_data)
-                        >> PAGE_SHIFT);
-       dump->u_ssize = (current->mm->start_stack - dump->start_stack
-                        + PAGE_SIZE-1) >> PAGE_SHIFT;
-
-       /*
-        * We store the registers in an order/format that is
-        * compatible with DEC Unix/OSF/1 as this makes life easier
-        * for gdb.
-        */
-       dump->regs[EF_V0]  = pt->r0;
-       dump->regs[EF_T0]  = pt->r1;
-       dump->regs[EF_T1]  = pt->r2;
-       dump->regs[EF_T2]  = pt->r3;
-       dump->regs[EF_T3]  = pt->r4;
-       dump->regs[EF_T4]  = pt->r5;
-       dump->regs[EF_T5]  = pt->r6;
-       dump->regs[EF_T6]  = pt->r7;
-       dump->regs[EF_T7]  = pt->r8;
-       dump->regs[EF_S0]  = sw->r9;
-       dump->regs[EF_S1]  = sw->r10;
-       dump->regs[EF_S2]  = sw->r11;
-       dump->regs[EF_S3]  = sw->r12;
-       dump->regs[EF_S4]  = sw->r13;
-       dump->regs[EF_S5]  = sw->r14;
-       dump->regs[EF_S6]  = sw->r15;
-       dump->regs[EF_A3]  = pt->r19;
-       dump->regs[EF_A4]  = pt->r20;
-       dump->regs[EF_A5]  = pt->r21;
-       dump->regs[EF_T8]  = pt->r22;
-       dump->regs[EF_T9]  = pt->r23;
-       dump->regs[EF_T10] = pt->r24;
-       dump->regs[EF_T11] = pt->r25;
-       dump->regs[EF_RA]  = pt->r26;
-       dump->regs[EF_T12] = pt->r27;
-       dump->regs[EF_AT]  = pt->r28;
-       dump->regs[EF_SP]  = rdusp();
-       dump->regs[EF_PS]  = pt->ps;
-       dump->regs[EF_PC]  = pt->pc;
-       dump->regs[EF_GP]  = pt->gp;
-       dump->regs[EF_A0]  = pt->r16;
-       dump->regs[EF_A1]  = pt->r17;
-       dump->regs[EF_A2]  = pt->r18;
-       memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
-}
-
-/*
  * Fill in the user structure for a ELF core dump.
  */
 void
@@ -416,7 +306,7 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
        dest[27] = pt->r27;
        dest[28] = pt->r28;
        dest[29] = pt->gp;
-       dest[30] = rdusp();
+       dest[30] = ti == current_thread_info() ? rdusp() : ti->pcb.usp;
        dest[31] = pt->pc;
 
        /* Once upon a time this was the PS value.  Which is stupid
@@ -424,56 +314,24 @@ dump_elf_thread(elf_greg_t *dest, struct pt_regs *pt, struct thread_info *ti)
           useful value of the thread's UNIQUE field.  */
        dest[32] = ti->pcb.unique;
 }
+EXPORT_SYMBOL(dump_elf_thread);
 
 int
 dump_elf_task(elf_greg_t *dest, struct task_struct *task)
 {
-       struct thread_info *ti;
-       struct pt_regs *pt;
-
-       ti = task->thread_info;
-       pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
-
-       dump_elf_thread(dest, pt, ti);
-
+       dump_elf_thread(dest, task_pt_regs(task), task_thread_info(task));
        return 1;
 }
+EXPORT_SYMBOL(dump_elf_task);
 
 int
 dump_elf_task_fp(elf_fpreg_t *dest, struct task_struct *task)
 {
-       struct thread_info *ti;
-       struct pt_regs *pt;
-       struct switch_stack *sw;
-
-       ti = task->thread_info;
-       pt = (struct pt_regs *)((unsigned long)ti + 2*PAGE_SIZE) - 1;
-       sw = (struct switch_stack *)pt - 1;
-
+       struct switch_stack *sw = (struct switch_stack *)task_pt_regs(task) - 1;
        memcpy(dest, sw->fp, 32 * 8);
-
        return 1;
 }
-
-/*
- * sys_execve() executes a new program.
- */
-asmlinkage int
-do_sys_execve(char __user *ufilename, char __user * __user *argv,
-             char __user * __user *envp, struct pt_regs *regs)
-{
-       int error;
-       char *filename;
-
-       filename = getname(ufilename);
-       error = PTR_ERR(filename);
-       if (IS_ERR(filename))
-               goto out;
-       error = do_execve(filename, argv, envp, regs);
-       putname(filename);
-out:
-       return error;
-}
+EXPORT_SYMBOL(dump_elf_task_fp);
 
 /*
  * Return saved PC of a blocked thread.  This assumes the frame
@@ -490,9 +348,9 @@ out:
  */
 
 unsigned long
-thread_saved_pc(task_t *t)
+thread_saved_pc(struct task_struct *t)
 {
-       unsigned long base = (unsigned long)t->thread_info;
+       unsigned long base = (unsigned long)task_stack_page(t);
        unsigned long fp, sp = task_thread_info(t)->pcb.ksp;
 
        if (sp > base && sp+6*8 < base + 16*1024) {