fedora core 6 1.2949 + vserver 2.2.0
[linux-2.6.git] / arch / alpha / kernel / process.c
index 297e4b4..c151863 100644 (file)
@@ -8,7 +8,6 @@
  * 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>
@@ -26,6 +25,7 @@
 #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 "proto.h"
 #include "pci_impl.h"
 
-void default_idle(void)
-{
-       barrier();
-}
+/*
+ * Power off function, if any
+ */
+void (*pm_power_off)(void) = machine_power_off;
+EXPORT_SYMBOL(pm_power_off);
 
 void
 cpu_idle(void)
 {
+       set_thread_flag(TIF_POLLING_NRFLAG);
+
        while (1) {
-               void (*idle)(void) = default_idle;
                /* FIXME -- EV6 and LCA45 know how to power down
                   the CPU.  */
 
                while (!need_resched())
-                       idle();
+                       cpu_relax();
                schedule();
        }
 }
@@ -93,7 +95,7 @@ common_shutdown_1(void *generic_ptr)
        if (cpuid != boot_cpuid) {
                flags |= 0x00040000UL; /* "remain halted" */
                *pflags = flags;
-               clear_bit(cpuid, &cpu_present_mask);
+               cpu_clear(cpuid, cpu_present_map);
                halt();
        }
 #endif
@@ -119,14 +121,18 @@ common_shutdown_1(void *generic_ptr)
 
 #ifdef CONFIG_SMP
        /* Wait for the secondaries to halt. */
-       clear_bit(boot_cpuid, &cpu_present_mask);
-       while (cpu_present_mask)
+       cpu_clear(boot_cpuid, cpu_present_map);
+       while (cpus_weight(cpu_present_map))
                barrier();
 #endif
 
        /* If booted from SRM, reset some of the original environment. */
        if (alpha_using_srm) {
 #ifdef CONFIG_DUMMY_CONSOLE
+               /* If we've gotten here after SysRq-b, leave interrupt
+                  context before taking over the console. */
+               if (in_interrupt())
+                       irq_exit();
                /* This has the effect of resetting the VGA video origin.  */
                take_over_console(&dummy_con, 0, MAX_NR_CONSOLES-1, 1);
 #endif
@@ -165,7 +171,6 @@ machine_restart(char *restart_cmd)
        common_shutdown(LINUX_REBOOT_CMD_RESTART, restart_cmd);
 }
 
-EXPORT_SYMBOL(machine_restart);
 
 void
 machine_halt(void)
@@ -173,7 +178,6 @@ machine_halt(void)
        common_shutdown(LINUX_REBOOT_CMD_HALT, NULL);
 }
 
-EXPORT_SYMBOL(machine_halt);
 
 void
 machine_power_off(void)
@@ -181,7 +185,6 @@ machine_power_off(void)
        common_shutdown(LINUX_REBOOT_CMD_POWER_OFF, NULL);
 }
 
-EXPORT_SYMBOL(machine_power_off);
 
 /* Used by sysrq-p, among others.  I don't believe r9-r15 are ever
    saved in the context it's used.  */
@@ -189,7 +192,7 @@ EXPORT_SYMBOL(machine_power_off);
 void
 show_regs(struct pt_regs *regs)
 {
-       dik_show_regs(regs, 0);
+       dik_show_regs(regs, NULL);
 }
 
 /*
@@ -203,6 +206,7 @@ start_thread(struct pt_regs * regs, unsigned long pc, unsigned long sp)
        regs->ps = 8;
        wrusp(sp);
 }
+EXPORT_SYMBOL(start_thread);
 
 /*
  * Free current thread data structures etc..
@@ -239,14 +243,14 @@ release_thread(struct task_struct *dead_task)
  * with parameters (SIGCHLD, 0).
  */
 int
-alpha_clone(unsigned long clone_flags, unsigned long usp, int *parent_tid,
-           int *child_tid, unsigned long tls_value, struct pt_regs *regs)
+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 & ~CLONE_IDLETASK, usp, regs, 0,
-                      parent_tid, child_tid);
+       return do_fork(clone_flags, usp, regs, 0, parent_tid, child_tid);
 }
 
 int
@@ -274,7 +278,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
 {
        extern void ret_from_fork(void);
 
-       struct thread_info *childti = p->thread_info;
+       struct thread_info *childti = task_thread_info(p);
        struct pt_regs * childregs;
        struct switch_stack * childstack, *stack;
        unsigned long stack_offset, settls;
@@ -283,7 +287,7 @@ copy_thread(int nr, unsigned long clone_flags, unsigned long usp,
        if (!(regs->ps & 8))
                stack_offset = (PAGE_SIZE-1) & (unsigned long) regs;
        childregs = (struct pt_regs *)
-         (stack_offset + PAGE_SIZE + (long) childti);
+         (stack_offset + PAGE_SIZE + task_stack_page(p));
                
        *childregs = *regs;
        settls = regs->r20;
@@ -374,6 +378,7 @@ dump_thread(struct pt_regs * pt, struct user * dump)
        dump->regs[EF_A2]  = pt->r18;
        memcpy((char *)dump->regs + EF_SIZE, sw->fp, 32 * 8);
 }
+EXPORT_SYMBOL(dump_thread);
 
 /*
  * Fill in the user structure for a ELF core dump.
@@ -422,51 +427,31 @@ 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;
 }
+EXPORT_SYMBOL(dump_elf_task_fp);
 
 /*
  * sys_execve() executes a new program.
- *
- * This works due to the alpha calling sequence: the first 6 args
- * are gotten from registers, while the rest is on the stack, so
- * we get a0-a5 for free, and then magically find "struct pt_regs"
- * on the stack for us..
- *
- * Don't do this at home.
  */
 asmlinkage int
-sys_execve(char *ufilename, char **argv, char **envp,
-          unsigned long a3, unsigned long a4, unsigned long a5,
-          struct pt_regs regs)
+do_sys_execve(char __user *ufilename, char __user * __user *argv,
+             char __user * __user *envp, struct pt_regs *regs)
 {
        int error;
        char *filename;
@@ -475,7 +460,7 @@ sys_execve(char *ufilename, char **argv, char **envp,
        error = PTR_ERR(filename);
        if (IS_ERR(filename))
                goto out;
-       error = do_execve(filename, argv, envp, &regs);
+       error = do_execve(filename, argv, envp, regs);
        putname(filename);
 out:
        return error;
@@ -496,10 +481,10 @@ 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 fp, sp = t->thread_info->pcb.ksp;
+       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) {
                fp = ((unsigned long*)sp)[6];
@@ -510,12 +495,6 @@ thread_saved_pc(task_t *t)
        return 0;
 }
 
-/*
- * These bracket the sleeping functions..
- */
-#define first_sched    ((unsigned long) scheduling_functions_start_here)
-#define last_sched     ((unsigned long) scheduling_functions_end_here)
-
 unsigned long
 get_wchan(struct task_struct *p)
 {
@@ -534,8 +513,8 @@ get_wchan(struct task_struct *p)
         */
 
        pc = thread_saved_pc(p);
-       if (pc >= first_sched && pc < last_sched) {
-               schedule_frame = ((unsigned long *)p->thread_info->pcb.ksp)[6];
+       if (in_sched_functions(pc)) {
+               schedule_frame = ((unsigned long *)task_thread_info(p)->pcb.ksp)[6];
                return ((unsigned long *)schedule_frame)[12];
        }
        return pc;