Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / arch / um / kernel / skas / process_kern.c
index 5418f08..2135eaf 100644 (file)
@@ -1,4 +1,4 @@
-/* 
+/*
  * Copyright (C) 2002 Jeff Dike (jdike@karaya.com)
  * Licensed under the GPL
  */
 #include "asm/uaccess.h"
 #include "asm/atomic.h"
 #include "kern_util.h"
-#include "time_user.h"
-#include "signal_user.h"
 #include "skas.h"
 #include "os.h"
 #include "user_util.h"
 #include "tlb.h"
-#include "frame.h"
 #include "kern.h"
 #include "mode.h"
-#include "proc_mm.h"
-
-static atomic_t using_sysemu;
-int sysemu_supported;
-
-void set_using_sysemu(int value)
-{
-       atomic_set(&using_sysemu, sysemu_supported && value);
-}
-
-int get_using_sysemu(void)
-{
-       return atomic_read(&using_sysemu);
-}
+#include "registers.h"
 
-int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data)
-{
-       if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/
-               *eof = 1;
-
-       return strlen(buf);
-}
-
-int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data)
-{
-       char tmp[2];
-
-       if (copy_from_user(tmp, buf, 1))
-               return -EFAULT;
-
-       if (tmp[0] == '0' || tmp[0] == '1')
-               set_using_sysemu(tmp[0] - '0');
-       return count; /*We use the first char, but pretend to write everything*/
-}
-
-int __init make_proc_sysemu(void)
-{
-       struct proc_dir_entry *ent;
-       if (mode_tt || !sysemu_supported)
-               return 0;
-
-       ent = create_proc_entry("sysemu", 0600, &proc_root);
-
-       if (ent == NULL)
-       {
-               printk("Failed to register /proc/sysemu\n");
-               return(0);
-       }
-
-       ent->read_proc  = proc_read_sysemu;
-       ent->write_proc = proc_write_sysemu;
-
-       return 0;
-}
-
-late_initcall(make_proc_sysemu);
-
-int singlestepping_skas(void)
-{
-       int ret = current->ptrace & PT_DTRACE;
-
-       current->ptrace &= ~PT_DTRACE;
-       return(ret);
-}
-
-void *switch_to_skas(void *prev, void *next)
+void switch_to_skas(void *prev, void *next)
 {
        struct task_struct *from, *to;
 
@@ -98,16 +32,13 @@ void *switch_to_skas(void *prev, void *next)
        if(current->pid == 0)
                switch_timers(0);
 
-       to->thread.prev_sched = from;
-       set_current(to);
-
-       switch_threads(&from->thread.mode.skas.switch_buf, 
+       switch_threads(&from->thread.mode.skas.switch_buf,
                       to->thread.mode.skas.switch_buf);
 
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
        if(current->pid == 0)
                switch_timers(1);
-
-       return(current->thread.prev_sched);
 }
 
 extern void schedule_tail(struct task_struct *prev);
@@ -119,8 +50,8 @@ void new_thread_handler(int sig)
 
        fn = current->thread.request.u.thread.proc;
        arg = current->thread.request.u.thread.arg;
-       change_sig(SIGUSR1, 1);
-       thread_wait(&current->thread.mode.skas.switch_buf, 
+       os_usr1_signal(1);
+       thread_wait(&current->thread.mode.skas.switch_buf,
                    current->thread.mode.skas.fork_buf);
 
        if(current->thread.prev_sched != NULL)
@@ -131,8 +62,11 @@ void new_thread_handler(int sig)
         * 0 if it just exits
         */
        n = run_kernel_thread(fn, arg, &current->thread.exec_buf);
-       if(n == 1)
+       if(n == 1){
+               /* Handle any immediate reschedules or signals */
+               interrupt_end();
                userspace(&current->thread.regs.regs);
+       }
        else do_exit(0);
 }
 
@@ -146,14 +80,10 @@ void release_thread_skas(struct task_struct *task)
 {
 }
 
-void exit_thread_skas(void)
-{
-}
-
 void fork_handler(int sig)
 {
-        change_sig(SIGUSR1, 1);
-       thread_wait(&current->thread.mode.skas.switch_buf, 
+       os_usr1_signal(1);
+       thread_wait(&current->thread.mode.skas.switch_buf,
                    current->thread.mode.skas.fork_buf);
        
        force_flush_all();
@@ -161,60 +91,57 @@ void fork_handler(int sig)
                panic("blech");
 
        schedule_tail(current->thread.prev_sched);
+
+       /* XXX: if interrupt_end() calls schedule, this call to
+        * arch_switch_to_skas isn't needed. We could want to apply this to
+        * improve performance. -bb */
+       arch_switch_to_skas(current->thread.prev_sched, current);
+
        current->thread.prev_sched = NULL;
 
+/* Handle any immediate reschedules or signals */
+       interrupt_end();
+
        userspace(&current->thread.regs.regs);
 }
 
 int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp,
-                    unsigned long stack_top, struct task_struct * p, 
+                    unsigned long stack_top, struct task_struct * p,
                     struct pt_regs *regs)
 {
        void (*handler)(int);
 
        if(current->thread.forking){
-               memcpy(&p->thread.regs.regs.skas, 
-                      &current->thread.regs.regs.skas, 
+               memcpy(&p->thread.regs.regs.skas, &regs->regs.skas,
                       sizeof(p->thread.regs.regs.skas));
                REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0);
                if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp;
 
                handler = fork_handler;
+
+               arch_copy_thread(&current->thread.arch, &p->thread.arch);
        }
        else {
-               memcpy(p->thread.regs.regs.skas.regs, exec_regs, 
-                      sizeof(p->thread.regs.regs.skas.regs));
-               memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, 
-                      sizeof(p->thread.regs.regs.skas.fp));
-               memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, 
-                      sizeof(p->thread.regs.regs.skas.xfp));
+               init_thread_registers(&p->thread.regs.regs);
                 p->thread.request.u.thread = current->thread.request.u.thread;
                handler = new_thread_handler;
        }
 
-       new_thread(p->thread_info, &p->thread.mode.skas.switch_buf,
+       new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf,
                   &p->thread.mode.skas.fork_buf, handler);
        return(0);
 }
 
-int new_mm(int from)
+int new_mm(unsigned long stack)
 {
-       struct proc_mm_op copy;
-       int n, fd;
+       int fd;
 
        fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0);
        if(fd < 0)
                return(fd);
 
-       if(from != -1){
-               copy = ((struct proc_mm_op) { .op       = MM_COPY_SEGMENTS,
-                                             .u        =
-                                             { .copy_segments  = from } } );
-               n = os_write_file(fd, &copy, sizeof(copy));
-               if(n != sizeof(copy))
-                       printk("new_mm : /proc/mm copy_segments failed, "
-                              "err = %d\n", -n);
-       }
+       if(skas_needs_stub)
+               map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack);
 
        return(fd);
 }
@@ -243,17 +170,18 @@ static int start_kernel_proc(void *unused)
        return(0);
 }
 
+extern int userspace_pid[];
+
 int start_uml_skas(void)
 {
-       start_userspace(0);
-       capture_signal_stack();
+       if(proc_mm)
+               userspace_pid[0] = start_userspace(0);
 
        init_new_thread_signals(1);
-       uml_idle_timer();
 
        init_task.thread.request.u.thread.proc = start_kernel_proc;
        init_task.thread.request.u.thread.arg = NULL;
-       return(start_idle_thread(init_task.thread_info,
+       return(start_idle_thread(task_stack_page(&init_task),
                                 &init_task.thread.mode.skas.switch_buf,
                                 &init_task.thread.mode.skas.fork_buf));
 }
@@ -270,13 +198,30 @@ int thread_pid_skas(struct task_struct *task)
        return(userspace_pid[0]);
 }
 
-/*
- * Overrides for Emacs so that we follow Linus's tabbing style.
- * Emacs will notice this stuff at the end of the file and automatically
- * adjust the settings for this buffer only.  This must remain at the end
- * of the file.
- * ---------------------------------------------------------------------------
- * Local variables:
- * c-file-style: "linux"
- * End:
- */
+void kill_off_processes_skas(void)
+{
+       if(proc_mm)
+#warning need to loop over userspace_pids in kill_off_processes_skas
+               os_kill_ptraced_process(userspace_pid[0], 1);
+       else {
+               struct task_struct *p;
+               int pid, me;
+
+               me = os_getpid();
+               for_each_process(p){
+                       if(p->mm == NULL)
+                               continue;
+
+                       pid = p->mm->context.skas.id.u.pid;
+                       os_kill_ptraced_process(pid, 1);
+               }
+       }
+}
+
+unsigned long current_stub_stack(void)
+{
+       if(current->mm == NULL)
+               return(0);
+
+       return(current->mm->context.skas.id.stack);
+}