]> git.hungrycats.org Git - linux/commitdiff
[PATCH] uml: Adds /proc/sysemu to toggle SYSEMU usage.
authorPaolo \'Blaisorblade\' Giarrusso <blaisorblade_spam@yahoo.it>
Tue, 24 Aug 2004 04:16:48 +0000 (21:16 -0700)
committerLinus Torvalds <torvalds@ppc970.osdl.org>
Tue, 24 Aug 2004 04:16:48 +0000 (21:16 -0700)
Adds /proc/sysemu to toggle SYSEMU usage.

Signed-off-by: Paolo 'Blaisorblade' Giarrusso <blaisorblade_spam@yahoo.it>
Cc: Jeff Dike <jdike@addtoit.com>
Signed-off-by: Andrew Morton <akpm@osdl.org>
Signed-off-by: Linus Torvalds <torvalds@osdl.org>
arch/um/kernel/process.c
arch/um/kernel/skas/include/ptrace-skas.h
arch/um/kernel/skas/process.c
arch/um/kernel/skas/process_kern.c

index 1bbd0438defd35e5b90161de6a832d2f4543e5b8..b9daca7cf8e84e7dadccdd6288416b6001eb8b64 100644 (file)
@@ -246,7 +246,7 @@ void __init check_ptrace(void)
        printk("OK\n");
 
        printk("Checking syscall emulation patch for ptrace...");
-       use_sysemu = 0;
+       set_using_sysemu(0);
        pid = start_ptraced_child(&stack);
        if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
                struct user_regs_struct regs;
@@ -269,7 +269,7 @@ void __init check_ptrace(void)
 
                if (!force_sysemu_disabled) {
                        printk("found\n");
-                       use_sysemu = 1;
+                       set_using_sysemu(1);
                } else {
                        printk("found but disabled\n");
                }
index 95ae96df7335d30671aa0c353c8c0e25e12fa3dc..3173a1b55a83d8ea60b71b3311dd28d3dbfd44ab 100644 (file)
@@ -15,7 +15,9 @@
 #ifndef PTRACE_SYSEMU
 #define PTRACE_SYSEMU 31
 #endif
-extern int use_sysemu;
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
 
 #include "skas_ptregs.h"
 
index 6c400085b8391074ab1716ab4d9320410dec672e..4d6eac0518294f158f3c13020b6dfb90cecca7db 100644 (file)
 #include "chan_user.h"
 #include "signal_user.h"
 
-#ifdef PTRACE_SYSEMU
-int use_sysemu = 0;
-#endif
-
 int is_skas_winch(int pid, int fd, void *data)
 {
        if(pid != getpid())
@@ -61,7 +57,8 @@ static void handle_segv(int pid)
        segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
 }
 
-static void handle_trap(int pid, union uml_pt_regs *regs)
+/*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;
 
@@ -72,27 +69,23 @@ static void handle_trap(int pid, union uml_pt_regs *regs)
                return;
        }
 
-#ifdef PTRACE_SYSEMU
-       if (!use_sysemu)
+       if (!local_using_sysemu)
        {
-#endif
-       err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-       if(err < 0)
-               panic("handle_trap - nullifying syscall failed errno = %d\n", 
-                     errno);
+               err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
+               if(err < 0)
+                       panic("handle_trap - nullifying syscall failed errno = %d\n",
+                             errno);
 
-       err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
-       if(err < 0)
-               panic("handle_trap - continuing to end of syscall failed, "
-                     "errno = %d\n", errno);
+               err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+               if(err < 0)
+                       panic("handle_trap - continuing to end of syscall failed, "
+                             "errno = %d\n", errno);
 
-       err = waitpid(pid, &status, WUNTRACED);
-       if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
-               panic("handle_trap - failed to wait at end of syscall, "
-                     "errno = %d, status = %d\n", errno, status);
-#ifdef PTRACE_SYSEMU
+               err = waitpid(pid, &status, WUNTRACED);
+               if((err < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP))
+                       panic("handle_trap - failed to wait at end of syscall, "
+                             "errno = %d, status = %d\n", errno, status);
        }
-#endif
 
        handle_syscall(regs);
 }
@@ -147,15 +140,16 @@ void start_userspace(int cpu)
 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);
                
-#ifdef PTRACE_SYSEMU
-       if (use_sysemu)
+       local_using_sysemu = get_using_sysemu();
+
+       if (local_using_sysemu)
                err = ptrace(PTRACE_SYSEMU, pid, 0, 0);
        else
-#endif
-       err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+               err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
        if(err)
                panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
                       errno);
@@ -174,7 +168,7 @@ void userspace(union uml_pt_regs *regs)
                                handle_segv(pid);
                                break;
                        case SIGTRAP:
-                               handle_trap(pid, regs);
+                               handle_trap(pid, regs, local_using_sysemu);
                                break;
                        case SIGIO:
                        case SIGVTALRM:
@@ -193,14 +187,16 @@ void userspace(union uml_pt_regs *regs)
 
                restore_registers(regs);
 
-#ifdef PTRACE_SYSEMU
-               if (use_sysemu)
+               /*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
-#endif
-               op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
-                       PTRACE_SYSCALL;
+                       op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+                               PTRACE_SYSCALL;
+
                err = ptrace(op, pid, 0, 0);
                if(err)
                        panic("userspace - PTRACE_SYSCALL failed, "
index 52de0124f78ae1c54763d77dea5f263f916c39a5..7f4afe41e2854e435df8cee71f4fafdf0f852596 100644 (file)
@@ -6,6 +6,12 @@
 #include "linux/sched.h"
 #include "linux/slab.h"
 #include "linux/ptrace.h"
+#include "linux/proc_fs.h"
+#include "linux/file.h"
+#include "linux/errno.h"
+#include "linux/init.h"
+#include "asm/uaccess.h"
+#include "asm/atomic.h"
 #include "kern_util.h"
 #include "time_user.h"
 #include "signal_user.h"
 #include "kern.h"
 #include "mode.h"
 
+#ifdef PTRACE_SYSEMU
+static atomic_t using_sysemu;
+#endif
+
+void set_using_sysemu(int value)
+{
+       atomic_set(&using_sysemu, value);
+}
+
+int get_using_sysemu(void)
+{
+       return atomic_read(&using_sysemu);
+}
+
+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;
+
+       ent = create_proc_entry("sysemu", 00600, &proc_root);
+       ent->read_proc  = proc_read_sysemu;
+       ent->write_proc = proc_write_sysemu;
+
+       if (ent == NULL)
+       {
+               printk("Failed to register /proc/sysemu\n");
+               return(0);
+       }
+
+       return 0;
+}
+
+late_initcall(make_proc_sysemu);
+
 int singlestepping_skas(void)
 {
        int ret = current->ptrace & PT_DTRACE;