# This is Blaisorblade's sysemu patch for UML, cleaned up some, and with # support added for tt mode. This adds support to UML for Laurent Vivier's # context-switch-reducing sysemu patch. Index: um/arch/um/include/ptrace_user.h =================================================================== --- um.orig/arch/um/include/ptrace_user.h 2004-09-10 12:12:24.000000000 -0400 +++ um/arch/um/include/ptrace_user.h 2004-09-10 12:13:06.000000000 -0400 @@ -8,6 +8,13 @@ #include "sysdep/ptrace_user.h" +/* syscall emulation path in ptrace */ +#ifndef PTRACE_SYSEMU +#define PTRACE_SYSEMU 31 +#endif + +extern int use_sysemu; + extern int ptrace_getregs(long pid, unsigned long *regs_out); extern int ptrace_setregs(long pid, unsigned long *regs_in); extern int ptrace_getfpregs(long pid, unsigned long *regs_out); Index: um/arch/um/kernel/process.c =================================================================== --- um.orig/arch/um/kernel/process.c 2004-09-10 12:12:24.000000000 -0400 +++ um/arch/um/kernel/process.c 2004-09-10 12:13:06.000000000 -0400 @@ -19,6 +19,7 @@ #include #include #include +#include #include "user_util.h" #include "kern_util.h" #include "user.h" @@ -185,6 +186,8 @@ panic("check_ptrace : munmap failed, errno = %d", errno); } +int use_sysemu = 0; + void __init check_ptrace(void) { void *stack; @@ -217,6 +220,34 @@ } stop_ptraced_child(pid, stack, 0); printk("OK\n"); + + printk("Checking syscall emulation patch for ptrace..."); + pid = start_ptraced_child(&stack); + if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) { + CATCH_EINTR(n = waitpid(pid, &status, WUNTRACED)); + if(n < 0) + panic("check_ptrace : wait failed, errno = %d", errno); + + if(!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGTRAP)) + panic("check_ptrace : expected SIGTRAP, " + "got status = %d", status); + + + n = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_RET_OFFSET, + os_getpid()); + if(n < 0) + panic("check_ptrace : failed to modify system " + "call return, errno = %d", errno); + + stop_ptraced_child(pid, stack, 0); + + printk("OK\n"); + use_sysemu = 1; + } + else { + printk("missing\n"); + stop_ptraced_child(pid, stack, 1); + } } int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr) Index: um/arch/um/kernel/skas/process.c =================================================================== --- um.orig/arch/um/kernel/skas/process.c 2004-09-10 12:12:24.000000000 -0400 +++ um/arch/um/kernel/skas/process.c 2004-09-10 12:13:06.000000000 -0400 @@ -67,22 +67,25 @@ return; } + handle_syscall(regs); + if(use_sysemu) + return; + err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid); if(err < 0) - panic("handle_trap - nullifying syscall failed errno = %d\n", + 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, " + panic("handle_trap - continuing to end of syscall failed, " "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)) panic("handle_trap - failed to wait at end of syscall, " "errno = %d, status = %d\n", errno, status); - - handle_syscall(regs); } static int userspace_tramp(void *arg) @@ -134,11 +137,12 @@ void userspace(union uml_pt_regs *regs) { - int err, status, op, pid = userspace_pid[0]; + int err, status, op, do_syscall, pid = userspace_pid[0]; + do_syscall = use_sysemu ? PTRACE_SYSEMU : PTRACE_SYSCALL; restore_registers(regs); - err = ptrace(PTRACE_SYSCALL, pid, 0, 0); + err = ptrace(do_syscall, pid, 0, 0); if(err) panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", errno); @@ -176,8 +180,7 @@ restore_registers(regs); - op = singlestepping_skas() ? PTRACE_SINGLESTEP : - PTRACE_SYSCALL; + op = singlestepping_skas() ? PTRACE_SINGLESTEP : do_syscall; err = ptrace(op, pid, 0, 0); if(err) panic("userspace - PTRACE_SYSCALL failed, " Index: um/arch/um/kernel/tt/syscall_user.c =================================================================== --- um.orig/arch/um/kernel/tt/syscall_user.c 2004-09-10 12:12:24.000000000 -0400 +++ um/arch/um/kernel/tt/syscall_user.c 2004-09-10 12:13:06.000000000 -0400 @@ -70,6 +70,9 @@ ((unsigned long *) PT_IP(proc_regs) <= &_etext)) tracer_panic("I'm tracing myself and I can't get out"); + if(use_sysemu) + return(1); + if(ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid) < 0) tracer_panic("do_syscall : Nullifying syscall failed, " Index: um/arch/um/kernel/tt/tracer.c =================================================================== --- um.orig/arch/um/kernel/tt/tracer.c 2004-09-10 12:12:24.000000000 -0400 +++ um/arch/um/kernel/tt/tracer.c 2004-09-10 12:13:06.000000000 -0400 @@ -184,6 +184,7 @@ unsigned long eip = 0; int status, pid = 0, sig = 0, cont_type, tracing = 0, op = 0; int last_index, proc_id = 0, n, err, old_tracing = 0, strace = 0; + int cont_syscall; capture_signal_stack(); signal(SIGPIPE, SIG_IGN); @@ -297,6 +298,8 @@ tracing = is_tracing(task); old_tracing = tracing; + cont_syscall = use_sysemu ? PTRACE_SYSEMU : + PTRACE_SYSCALL; switch(sig){ case SIGUSR1: sig = 0; @@ -330,7 +333,8 @@ continue; } tracing = 0; - if(do_syscall(task, pid)) sig = SIGUSR2; + if(do_syscall(task, pid)) + sig = SIGUSR2; else clear_singlestep(task); break; case SIGPROF: @@ -369,7 +373,7 @@ if(tracing){ if(singlestepping_tt(task)) cont_type = PTRACE_SINGLESTEP; - else cont_type = PTRACE_SYSCALL; + else cont_type = cont_syscall; } else cont_type = PTRACE_CONT;