Merge branch 'for-linus' of git://git.kernel.dk/linux-2.6-block
[sfrench/cifs-2.6.git] / arch / um / kernel / process.c
index 0eae00b3e58895054d69afd0876bedae0bd12631..fc50d2f959d12f44bc6c41171f3cc030d6ad38fa 100644 (file)
@@ -4,19 +4,21 @@
  * Licensed under the GPL
  */
 
-#include "linux/stddef.h"
-#include "linux/err.h"
-#include "linux/hardirq.h"
-#include "linux/mm.h"
-#include "linux/personality.h"
-#include "linux/proc_fs.h"
-#include "linux/ptrace.h"
-#include "linux/random.h"
-#include "linux/sched.h"
-#include "linux/tick.h"
-#include "linux/threads.h"
-#include "asm/pgtable.h"
-#include "asm/uaccess.h"
+#include <linux/stddef.h>
+#include <linux/err.h>
+#include <linux/hardirq.h>
+#include <linux/gfp.h>
+#include <linux/mm.h>
+#include <linux/personality.h>
+#include <linux/proc_fs.h>
+#include <linux/ptrace.h>
+#include <linux/random.h>
+#include <linux/sched.h>
+#include <linux/tick.h>
+#include <linux/threads.h>
+#include <asm/current.h>
+#include <asm/pgtable.h>
+#include <asm/uaccess.h>
 #include "as-layout.h"
 #include "kern_util.h"
 #include "os.h"
@@ -30,7 +32,7 @@
  */
 struct cpu_task cpu_tasks[NR_CPUS] = { [0 ... NR_CPUS - 1] = { -1, NULL } };
 
-static inline int external_pid(struct task_struct *task)
+static inline int external_pid(void)
 {
        /* FIXME: Need to look up userspace_pid by cpu */
        return userspace_pid[0];
@@ -40,7 +42,7 @@ int pid_to_processor_id(int pid)
 {
        int i;
 
-       for(i = 0; i < ncpus; i++) {
+       for (i = 0; i < ncpus; i++) {
                if (cpu_tasks[i].pid == pid)
                        return i;
        }
@@ -60,8 +62,6 @@ unsigned long alloc_stack(int order, int atomic)
        if (atomic)
                flags = GFP_ATOMIC;
        page = __get_free_pages(flags, order);
-       if (page == 0)
-               return 0;
 
        return page;
 }
@@ -80,15 +80,15 @@ int kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
 static inline void set_current(struct task_struct *task)
 {
        cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task)
-               { external_pid(task), task });
+               { external_pid(), task });
 }
 
-extern void arch_switch_to(struct task_struct *from, struct task_struct *to);
+extern void arch_switch_to(struct task_struct *to);
 
 void *_switch_to(void *prev, void *next, void *last)
 {
        struct task_struct *from = prev;
-       struct task_struct *to= next;
+       struct task_struct *to = next;
 
        to->thread.prev_sched = from;
        set_current(to);
@@ -99,13 +99,13 @@ void *_switch_to(void *prev, void *next, void *last)
                switch_threads(&from->thread.switch_buf,
                               &to->thread.switch_buf);
 
-               arch_switch_to(current->thread.prev_sched, current);
+               arch_switch_to(current);
 
                if (current->thread.saved_task)
                        show_regs(&(current->thread.regs));
-               next= current->thread.saved_task;
-               prev= current;
-       } while(current->thread.saved_task);
+               to = current->thread.saved_task;
+               from = current;
+       } while (current->thread.saved_task);
 
        return current->thread.prev_sched;
 
@@ -163,8 +163,6 @@ void new_thread_handler(void)
 void fork_handler(void)
 {
        force_flush_all();
-       if (current->thread.prev_sched == NULL)
-               panic("blech");
 
        schedule_tail(current->thread.prev_sched);
 
@@ -173,7 +171,7 @@ void fork_handler(void)
         * arch_switch_to isn't needed. We could want to apply this to
         * improve performance. -bb
         */
-       arch_switch_to(current->thread.prev_sched, current);
+       arch_switch_to(current);
 
        current->thread.prev_sched = NULL;
 
@@ -204,7 +202,7 @@ int copy_thread(int nr, unsigned long clone_flags, unsigned long sp,
                arch_copy_thread(&current->thread.arch, &p->thread.arch);
        }
        else {
-               init_thread_registers(&p->thread.regs.regs);
+               get_safe_registers(p->thread.regs.regs.gp);
                p->thread.request.u.thread = current->thread.request.u.thread;
                handler = new_thread_handler;
        }
@@ -237,7 +235,7 @@ void default_idle(void)
 {
        unsigned long long nsecs;
 
-       while(1) {
+       while (1) {
                /* endless idle loop with no priority at all */
 
                /*
@@ -256,57 +254,10 @@ void default_idle(void)
 
 void cpu_idle(void)
 {
-       cpu_tasks[current_thread->cpu].pid = os_getpid();
+       cpu_tasks[current_thread_info()->cpu].pid = os_getpid();
        default_idle();
 }
 
-void *um_virt_to_phys(struct task_struct *task, unsigned long addr,
-                     pte_t *pte_out)
-{
-       pgd_t *pgd;
-       pud_t *pud;
-       pmd_t *pmd;
-       pte_t *pte;
-       pte_t ptent;
-
-       if (task->mm == NULL)
-               return ERR_PTR(-EINVAL);
-       pgd = pgd_offset(task->mm, addr);
-       if (!pgd_present(*pgd))
-               return ERR_PTR(-EINVAL);
-
-       pud = pud_offset(pgd, addr);
-       if (!pud_present(*pud))
-               return ERR_PTR(-EINVAL);
-
-       pmd = pmd_offset(pud, addr);
-       if (!pmd_present(*pmd))
-               return ERR_PTR(-EINVAL);
-
-       pte = pte_offset_kernel(pmd, addr);
-       ptent = *pte;
-       if (!pte_present(ptent))
-               return ERR_PTR(-EINVAL);
-
-       if (pte_out != NULL)
-               *pte_out = ptent;
-       return (void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK);
-}
-
-char *current_cmd(void)
-{
-#if defined(CONFIG_SMP) || defined(CONFIG_HIGHMEM)
-       return "(Unknown)";
-#else
-       void *addr = um_virt_to_phys(current, current->mm->arg_start, NULL);
-       return IS_ERR(addr) ? "(Unknown)": __va((unsigned long) addr);
-#endif
-}
-
-void dump_thread(struct pt_regs *regs, struct user *u)
-{
-}
-
 int __cant_sleep(void) {
        return in_atomic() || irqs_disabled() || in_interrupt();
        /* Is in_interrupt() really needed? */
@@ -317,7 +268,7 @@ int user_context(unsigned long sp)
        unsigned long stack;
 
        stack = sp & (PAGE_MASK << CONFIG_KERNEL_STACK_ORDER);
-       return stack != (unsigned long) current_thread;
+       return stack != (unsigned long) current_thread_info();
 }
 
 extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end;
@@ -331,7 +282,7 @@ void do_uml_exitcalls(void)
                (*call)();
 }
 
-char *uml_strdup(char *string)
+char *uml_strdup(const char *string)
 {
        return kstrdup(string, GFP_KERNEL);
 }
@@ -359,7 +310,7 @@ int strlen_user_proc(char __user *str)
 int smp_sigio_handler(void)
 {
 #ifdef CONFIG_SMP
-       int cpu = current_thread->cpu;
+       int cpu = current_thread_info()->cpu;
        IPI_handler(cpu);
        if (cpu != 0)
                return 1;
@@ -369,7 +320,7 @@ int smp_sigio_handler(void)
 
 int cpu(void)
 {
-       return current_thread->cpu;
+       return current_thread_info()->cpu;
 }
 
 static atomic_t using_sysemu = ATOMIC_INIT(0);
@@ -435,7 +386,7 @@ int singlestepping(void * t)
 {
        struct task_struct *task = t ? t : current;
 
-       if ( ! (task->ptrace & PT_DTRACE) )
+       if (!(task->ptrace & PT_DTRACE))
                return 0;
 
        if (task->thread.singlestep_syscall)
@@ -459,3 +410,46 @@ unsigned long arch_align_stack(unsigned long sp)
        return sp & ~0xf;
 }
 #endif
+
+unsigned long get_wchan(struct task_struct *p)
+{
+       unsigned long stack_page, sp, ip;
+       bool seen_sched = 0;
+
+       if ((p == NULL) || (p == current) || (p->state == TASK_RUNNING))
+               return 0;
+
+       stack_page = (unsigned long) task_stack_page(p);
+       /* Bail if the process has no kernel stack for some reason */
+       if (stack_page == 0)
+               return 0;
+
+       sp = p->thread.switch_buf->JB_SP;
+       /*
+        * Bail if the stack pointer is below the bottom of the kernel
+        * stack for some reason
+        */
+       if (sp < stack_page)
+               return 0;
+
+       while (sp < stack_page + THREAD_SIZE) {
+               ip = *((unsigned long *) sp);
+               if (in_sched_functions(ip))
+                       /* Ignore everything until we're above the scheduler */
+                       seen_sched = 1;
+               else if (kernel_text_address(ip) && seen_sched)
+                       return ip;
+
+               sp += sizeof(unsigned long);
+       }
+
+       return 0;
+}
+
+int elf_core_copy_fpregs(struct task_struct *t, elf_fpregset_t *fpu)
+{
+       int cpu = current_thread_info()->cpu;
+
+       return save_fp_registers(userspace_pid[cpu], (unsigned long *) fpu);
+}
+