+static int force_sysemu_disabled = 0;
+
+static int __init nosysemu_cmd_param(char *str, int* add)
+{
+ force_sysemu_disabled = 1;
+ return 0;
+}
+
+__uml_setup("nosysemu", nosysemu_cmd_param,
+ "nosysemu\n"
+ " Turns off syscall emulation patch for ptrace (SYSEMU) on.\n"
+ " SYSEMU is a performance-patch introduced by Laurent Vivier. It changes\n"
+ " behaviour of ptrace() and helps reducing host context switch rate.\n"
+ " To make it working, you need a kernel patch for your host, too.\n"
+ " See http://perso.wanadoo.fr/laurent.vivier/UML/ for further information.\n");
+
+static void __init check_sysemu(void)
+{
+ void *stack;
+ int pid, n, status;
+
+ if (mode_tt)
+ return;
+
+ printk("Checking syscall emulation patch for ptrace...");
+ sysemu_supported = 0;
+ pid = start_ptraced_child(&stack);
+ if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
+ struct user_regs_struct regs;
+
+ 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);
+
+ if (ptrace(PTRACE_GETREGS, pid, 0, ®s) < 0)
+ panic("check_ptrace : failed to read child "
+ "registers, errno = %d", errno);
+ regs.orig_eax = pid;
+ if (ptrace(PTRACE_SETREGS, pid, 0, ®s) < 0)
+ panic("check_ptrace : failed to modify child "
+ "registers, errno = %d", errno);
+
+ stop_ptraced_child(pid, stack, 0);
+
+ sysemu_supported = 1;
+ printk("found\n");
+ }
+ else
+ {
+ stop_ptraced_child(pid, stack, 1);
+ sysemu_supported = 0;
+ printk("missing\n");
+ }
+
+ set_using_sysemu(!force_sysemu_disabled);
+}
+