vserver 1.9.5.x5
[linux-2.6.git] / arch / um / kernel / skas / process.c
index cb748f8..db53368 100644 (file)
@@ -11,6 +11,7 @@
 #include <sched.h>
 #include <sys/wait.h>
 #include <sys/ptrace.h>
+#include <linux/ptrace.h>
 #include <sys/mman.h>
 #include <sys/user.h>
 #include <asm/unistd.h>
 #include "skas_ptrace.h"
 #include "chan_user.h"
 #include "signal_user.h"
+#include "registers.h"
 
 int is_skas_winch(int pid, int fd, void *data)
 {
-       if(pid != getpid())
+       if(pid != os_getpid())
                return(0);
 
        register_winch_irq(-1, fd, -1, data);
        return(1);
 }
 
-/* These are set once at boot time and not changed thereafter */
-
-unsigned long exec_regs[FRAME_SIZE];
-unsigned long exec_fp_regs[HOST_FP_SIZE];
-unsigned long exec_fpx_regs[HOST_XFP_SIZE];
-int have_fpx_regs = 1;
-
 static void handle_segv(int pid)
 {
        struct ptrace_faultinfo fault;
@@ -60,14 +55,10 @@ static void handle_segv(int pid)
 /*To use the same value of using_sysemu as the caller, ask it that value (in local_using_sysemu)*/
 static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu)
 {
-       int err, syscall_nr, status;
+       int err, status;
 
-       syscall_nr = PT_SYSCALL_NR(regs->skas.regs);
-       UPT_SYSCALL_NR(regs) = syscall_nr;
-       if(syscall_nr < 1){
-               relay_signal(SIGTRAP, regs);
-               return;
-       }
+       /* Mark this as a syscall */
+       UPT_SYSCALL_NR(regs) = PT_SYSCALL_NR(regs->skas.regs);
 
        if (!local_using_sysemu)
        {
@@ -82,7 +73,8 @@ static void handle_trap(int pid, union uml_pt_regs *regs, int local_using_sysemu
                              "errno = %d\n", errno);
 
                CATCH_EINTR(err = waitpid(pid, &status, WUNTRACED));
-               if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+               if((err < 0) || !WIFSTOPPED(status) ||
+                  (WSTOPSIG(status) != SIGTRAP + 0x80))
                        panic("handle_trap - failed to wait at end of syscall, "
                              "errno = %d, status = %d\n", errno, status);
        }
@@ -100,6 +92,7 @@ static int userspace_tramp(void *arg)
 }
 
 /* Each element set once, and only accessed by a single processor anyway */
+#undef NR_CPUS
 #define NR_CPUS 1
 int userspace_pid[NR_CPUS];
 
@@ -131,6 +124,10 @@ void start_userspace(int cpu)
                panic("start_userspace : expected SIGSTOP, got status = %d",
                      status);
 
+       if (ptrace(PTRACE_OLDSETOPTIONS, pid, NULL, (void *)PTRACE_O_TRACESYSGOOD) < 0)
+               panic("start_userspace : PTRACE_SETOPTIONS failed, errno=%d\n",
+                     errno);
+
        if(munmap(stack, PAGE_SIZE) < 0)
                panic("start_userspace : munmap failed, errno = %d\n", errno);
 
@@ -142,14 +139,13 @@ void userspace(union uml_pt_regs *regs)
        int err, status, op, pid = userspace_pid[0];
        int local_using_sysemu; /*To prevent races if using_sysemu changes under us.*/
 
-       restore_registers(regs);
+       restore_registers(pid, regs);
                
        local_using_sysemu = get_using_sysemu();
 
-       if (local_using_sysemu)
-               err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
-       else
-               err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+       op = local_using_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL;
+       err = ptrace(op, pid, 0, 0);
+
        if(err)
                panic("userspace - PTRACE_%s failed, errno = %d\n",
                       local_using_sysemu ? "SYSEMU" : "SYSCALL", errno);
@@ -160,16 +156,20 @@ void userspace(union uml_pt_regs *regs)
                              errno);
 
                regs->skas.is_user = 1;
-               save_registers(regs);
+               save_registers(pid, regs);
+               UPT_SYSCALL_NR(regs) = -1; /* Assume: It's not a syscall */
 
                if(WIFSTOPPED(status)){
                        switch(WSTOPSIG(status)){
                        case SIGSEGV:
                                handle_segv(pid);
                                break;
-                       case SIGTRAP:
+                       case SIGTRAP + 0x80:
                                handle_trap(pid, regs, local_using_sysemu);
                                break;
+                       case SIGTRAP:
+                               relay_signal(SIGTRAP, regs);
+                               break;
                        case SIGIO:
                        case SIGVTALRM:
                        case SIGILL:
@@ -183,19 +183,17 @@ void userspace(union uml_pt_regs *regs)
                                       "%d\n", WSTOPSIG(status));
                        }
                        interrupt_end();
+
+                       /* Avoid -ERESTARTSYS handling in host */
+                       PT_SYSCALL_NR(regs->skas.regs) = -1;
                }
 
-               restore_registers(regs);
+               restore_registers(pid, regs);
 
                /*Now we ended the syscall, so re-read local_using_sysemu.*/
                local_using_sysemu = get_using_sysemu();
 
-               if (local_using_sysemu)
-                       op = singlestepping_skas() ? PTRACE_SINGLESTEP :
-                               PTRACE_SYSEMU;
-               else
-                       op = singlestepping_skas() ? PTRACE_SINGLESTEP :
-                               PTRACE_SYSCALL;
+               op = SELECT_PTRACE_OPERATION(local_using_sysemu, singlestepping(NULL));
 
                err = ptrace(op, pid, 0, 0);
                if(err)
@@ -226,9 +224,10 @@ void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr,
        block_signals();
        if(sigsetjmp(fork_buf, 1) == 0)
                new_thread_proc(stack, handler);
-       set_signals(flags);
 
        remove_sigstack();
+
+       set_signals(flags);
 }
 
 void thread_wait(void *sw, void *fb)
@@ -241,58 +240,6 @@ void thread_wait(void *sw, void *fb)
                siglongjmp(*fork_buf, 1);
 }
 
-static int move_registers(int pid, int int_op, int fp_op,
-                         union uml_pt_regs *regs, unsigned long *fp_regs)
-{
-       if(ptrace(int_op, pid, 0, regs->skas.regs) < 0)
-               return(-errno);
-       if(ptrace(fp_op, pid, 0, fp_regs) < 0)
-               return(-errno);
-       return(0);
-}
-
-void save_registers(union uml_pt_regs *regs)
-{
-       unsigned long *fp_regs;
-       int err, fp_op;
-
-       if(have_fpx_regs){
-               fp_op = PTRACE_GETFPXREGS;
-               fp_regs = regs->skas.xfp;
-       }
-       else {
-               fp_op = PTRACE_GETFPREGS;
-               fp_regs = regs->skas.fp;
-       }
-
-       err = move_registers(userspace_pid[0], PTRACE_GETREGS, fp_op, regs,
-                            fp_regs);
-       if(err)
-               panic("save_registers - saving registers failed, errno = %d\n",
-                     -err);
-}
-
-void restore_registers(union uml_pt_regs *regs)
-{
-       unsigned long *fp_regs;
-       int err, fp_op;
-
-       if(have_fpx_regs){
-               fp_op = PTRACE_SETFPXREGS;
-               fp_regs = regs->skas.xfp;
-       }
-       else {
-               fp_op = PTRACE_SETFPREGS;
-               fp_regs = regs->skas.fp;
-       }
-
-       err = move_registers(userspace_pid[0], PTRACE_SETREGS, fp_op, regs,
-                            fp_regs);
-       if(err)
-               panic("restore_registers - saving registers failed, "
-                     "errno = %d\n", -err);
-}
-
 void switch_threads(void *me, void *next)
 {
        sigjmp_buf my_buf, **me_ptr = me, *next_buf = next;
@@ -389,30 +336,7 @@ void switch_mm_skas(int mm_fd)
 void kill_off_processes_skas(void)
 {
 #warning need to loop over userspace_pids in kill_off_processes_skas
-       os_kill_process(userspace_pid[0], 1);
-}
-
-void init_registers(int pid)
-{
-       int err;
-
-       if(ptrace(PTRACE_GETREGS, pid, 0, exec_regs) < 0)
-               panic("check_ptrace : PTRACE_GETREGS failed, errno = %d", 
-                     errno);
-
-       err = ptrace(PTRACE_GETFPXREGS, pid, 0, exec_fpx_regs);
-       if(!err)
-               return;
-
-       have_fpx_regs = 0;
-       if(errno != EIO)
-               panic("check_ptrace : PTRACE_GETFPXREGS failed, errno = %d", 
-                     errno);
-
-       err = ptrace(PTRACE_GETFPREGS, pid, 0, exec_fp_regs);
-       if(err)
-               panic("check_ptrace : PTRACE_GETFPREGS failed, errno = %d", 
-                     errno);
+       os_kill_ptraced_process(userspace_pid[0], 1);
 }
 
 /*