From: Mark Huang <mlhuang@cs.princeton.edu>
Date: Thu, 29 Jul 2004 19:50:30 +0000 (+0000)
Subject: Merge BlaisorBlade patch uml-linux-2.6.7-01-bb1-complete.patch
X-Git-Tag: before-ipod-patch~4
X-Git-Url: http://git.onelab.eu/?a=commitdiff_plain;h=ad677697bb295fb472c37ba869457f7c9878d2c5;p=linux-2.6.git

Merge BlaisorBlade patch uml-linux-2.6.7-01-bb1-complete.patch
---

diff --git a/arch/um/Kconfig_char b/arch/um/Kconfig_char
index a21cbbc7e..1d5a0e54c 100644
--- a/arch/um/Kconfig_char
+++ b/arch/um/Kconfig_char
@@ -108,11 +108,60 @@ config SSL_CHAN
 
 config UNIX98_PTYS
 	bool "Unix98 PTY support"
-
-config UNIX98_PTY_COUNT
-	int "Maximum number of Unix98 PTYs in use (0-2048)"
-	depends on UNIX98_PTYS
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx for
+	  masters and /dev/ttyxx for slaves of pseudo terminals. This scheme
+	  has a number of problems. The GNU C library glibc 2.1 and later,
+	  however, supports the Unix98 naming standard: in order to acquire a
+	  pseudo terminal, a process opens /dev/ptmx; the number of the pseudo
+	  terminal is then made available to the process and the pseudo
+	  terminal slave can be accessed as /dev/pts/<number>. What was
+	  traditionally /dev/ttyp2 will then be /dev/pts/2, for example.
+
+	  All modern Linux systems use the Unix98 ptys.  Say Y unless
+	  you're on an embedded system and want to conserve memory.
+
+config LEGACY_PTYS
+	bool "Legacy (BSD) PTY support"
+	default y
+	---help---
+	  A pseudo terminal (PTY) is a software device consisting of two
+	  halves: a master and a slave. The slave device behaves identical to
+	  a physical terminal; the master device is used by a process to
+	  read data from and write data to the slave, thereby emulating a
+	  terminal. Typical programs for the master side are telnet servers
+	  and xterms.
+
+	  Linux has traditionally used the BSD-like names /dev/ptyxx
+	  for masters and /dev/ttyxx for slaves of pseudo
+	  terminals. This scheme has a number of problems, including
+	  security.  This option enables these legacy devices; on most
+	  systems, it is safe to say N.
+
+
+config LEGACY_PTY_COUNT
+	int "Maximum number of legacy PTY in use"
+	depends on LEGACY_PTYS
 	default "256"
+	---help---
+	  The maximum number of legacy PTYs that can be used at any one time.
+	  The default is 256, and should be more than enough.  Embedded
+	  systems may want to reduce this to save memory.
+
+	  When not in use, each legacy PTY occupies 12 bytes on 32-bit
+	  architectures and 24 bytes on 64-bit architectures.
+
+#config UNIX98_PTY_COUNT
+#	int "Maximum number of Unix98 PTYs in use (0-2048)"
+#	depends on UNIX98_PTYS
+#	default "256"
 
 config WATCHDOG
 	bool "Watchdog Timer Support"
diff --git a/arch/um/Makefile b/arch/um/Makefile
index 4e9bbefe4..27f1fe25d 100644
--- a/arch/um/Makefile
+++ b/arch/um/Makefile
@@ -61,6 +61,8 @@ CFLAGS += $(CFLAGS-y) -D__arch_um__ -DSUBARCH=\"$(SUBARCH)\" \
 	-D_LARGEFILE64_SOURCE $(ARCH_INCLUDE) -Derrno=kernel_errno \
 	-Dsigprocmask=kernel_sigprocmask $(MODE_INCLUDE)
 
+CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
+
 LINK_WRAPS = -Wl,--wrap,malloc -Wl,--wrap,free -Wl,--wrap,calloc
 
 # These are needed for clean and mrproper, since in that case .config is not
@@ -207,3 +209,9 @@ $(ARCH_DIR)/util: FORCE
 	$(Q)$(MAKE) $(build)=$@
 
 export SUBARCH USER_CFLAGS OS 
+
+all: linux
+
+define archhelp
+  echo  '* linux	- Binary kernel image (./linux)'
+endef
diff --git a/arch/um/drivers/Makefile b/arch/um/drivers/Makefile
index 7dd15474b..ba1aabbd7 100644
--- a/arch/um/drivers/Makefile
+++ b/arch/um/drivers/Makefile
@@ -15,7 +15,7 @@ mcast-objs := mcast_kern.o mcast_user.o
 #pcap-objs := pcap_kern.o pcap_user.o $(PCAP)
 net-objs := net_kern.o net_user.o
 mconsole-objs := mconsole_kern.o mconsole_user.o
-hostaudio-objs := hostaudio_kern.o hostaudio_user.o
+hostaudio-objs := hostaudio_kern.o
 ubd-objs := ubd_kern.o ubd_user.o
 port-objs := port_kern.o port_user.o
 harddog-objs := harddog_kern.o harddog_user.o
diff --git a/arch/um/drivers/chan_kern.c b/arch/um/drivers/chan_kern.c
index 56e19fa7b..3158f575a 100644
--- a/arch/um/drivers/chan_kern.c
+++ b/arch/um/drivers/chan_kern.c
@@ -17,6 +17,7 @@
 #include "irq_user.h"
 #include "sigio.h"
 #include "line.h"
+#include "os.h"
 
 static void *not_configged_init(char *str, int device, struct chan_opts *opts)
 {
@@ -87,6 +88,52 @@ static struct chan_ops not_configged_ops = {
 	.winch		= 0,
 };
 
+void generic_close(int fd, void *unused)
+{
+	os_close_file(fd);
+}
+
+int generic_read(int fd, char *c_out, void *unused)
+{
+	int n;
+
+	n = os_read_file(fd, c_out, sizeof(*c_out));
+
+	if(n == -EAGAIN)
+		return(0);
+	else if(n == 0)
+		return(-EIO);
+	return(n);
+}
+
+int generic_write(int fd, const char *buf, int n, void *unused)
+{
+	return(os_write_file(fd, buf, n));
+}
+
+int generic_window_size(int fd, void *unused, unsigned short *rows_out,
+			unsigned short *cols_out)
+{
+	int rows, cols;
+	int ret;
+
+	ret = os_window_size(fd, &rows, &cols);
+	if(ret < 0)
+		return(ret);
+
+	ret = ((*rows_out != rows) || (*cols_out != cols));
+
+	*rows_out = rows;
+	*cols_out = cols;
+
+	return(ret);
+}
+
+void generic_free(void *data)
+{
+	kfree(data);
+}
+
 static void tty_receive_char(struct tty_struct *tty, char ch)
 {
 	if(tty == NULL) return;
diff --git a/arch/um/drivers/chan_user.c b/arch/um/drivers/chan_user.c
index 7319ddd17..1ff87e7a3 100644
--- a/arch/um/drivers/chan_user.c
+++ b/arch/um/drivers/chan_user.c
@@ -21,31 +21,6 @@
 #include "choose-mode.h"
 #include "mode.h"
 
-void generic_close(int fd, void *unused)
-{
-	os_close_file(fd);
-}
-
-int generic_read(int fd, char *c_out, void *unused)
-{
-	int n;
-
-	n = os_read_file(fd, c_out, sizeof(*c_out));
-
-	if(n == -EAGAIN) 
-		return(0);
-	else if(n == 0) 
-		return(-EIO);
-	return(n);
-}
-
-/* XXX Trivial wrapper around os_write_file */
-
-int generic_write(int fd, const char *buf, int n, void *unused)
-{
-	return(os_write_file(fd, buf, n));
-}
-
 int generic_console_write(int fd, const char *buf, int n, void *unused)
 {
 	struct termios save, new;
@@ -62,29 +37,6 @@ int generic_console_write(int fd, const char *buf, int n, void *unused)
 	return(err);
 }
 
-int generic_window_size(int fd, void *unused, unsigned short *rows_out,
-			unsigned short *cols_out)
-{
-	int rows, cols;
-	int ret;
-
-	ret = os_window_size(fd, &rows, &cols);
-	if(ret < 0)
-		return(ret);
-
-	ret = ((*rows_out != rows) || (*cols_out != cols));
-
-	*rows_out = rows;
-	*cols_out = cols;
-
-	return(ret);
-}
-
-void generic_free(void *data)
-{
-	kfree(data);
-}
-
 static void winch_handler(int sig)
 {
 }
diff --git a/arch/um/drivers/hostaudio_kern.c b/arch/um/drivers/hostaudio_kern.c
index 9f9ae2730..03282cc42 100644
--- a/arch/um/drivers/hostaudio_kern.c
+++ b/arch/um/drivers/hostaudio_kern.c
@@ -13,7 +13,18 @@
 #include "asm/uaccess.h"
 #include "kern_util.h"
 #include "init.h"
-#include "hostaudio.h"
+#include "os.h"
+
+struct hostaudio_state {
+  int fd;
+};
+
+struct hostmixer_state {
+  int fd;
+};
+
+#define HOSTAUDIO_DEV_DSP "/dev/sound/dsp"
+#define HOSTAUDIO_DEV_MIXER "/dev/sound/mixer"
 
 /* Only changed from linux_main at boot time */
 char *dsp = HOSTAUDIO_DEV_DSP;
@@ -61,7 +72,7 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
 {
         struct hostaudio_state *state = file->private_data;
 	void *kbuf;
-	int err;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: read called, count = %d\n", count);
@@ -71,16 +82,16 @@ static ssize_t hostaudio_read(struct file *file, char *buffer, size_t count,
 	if(kbuf == NULL)
 		return(-ENOMEM);
 
-        err = hostaudio_read_user(state, kbuf, count, ppos);
-	if(err < 0)
+	ret = os_read_file(state->fd, kbuf, count);
+	if(ret < 0)
 		goto out;
 
-	if(copy_to_user(buffer, kbuf, err))
-		err = -EFAULT;
+	if(copy_to_user(buffer, kbuf, ret))
+		ret = -EFAULT;
 
  out:
 	kfree(kbuf);
-	return(err);
+	return(ret);
 }
 
 static ssize_t hostaudio_write(struct file *file, const char *buffer, 
@@ -88,7 +99,7 @@ static ssize_t hostaudio_write(struct file *file, const char *buffer,
 {
         struct hostaudio_state *state = file->private_data;
 	void *kbuf;
-	int err;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: write called, count = %d\n", count);
@@ -98,17 +109,17 @@ static ssize_t hostaudio_write(struct file *file, const char *buffer,
 	if(kbuf == NULL)
 		return(-ENOMEM);
 
-	err = -EFAULT;
+	ret = -EFAULT;
 	if(copy_from_user(kbuf, buffer, count))
 		goto out;
 
-        err = hostaudio_write_user(state, kbuf, count, ppos);
-	if(err < 0)
+	ret = os_write_file(state->fd, kbuf, count);
+	if(ret < 0)
 		goto out;
 
  out:
 	kfree(kbuf);
-	return(err);
+	return(ret);
 }
 
 static unsigned int hostaudio_poll(struct file *file, 
@@ -128,7 +139,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
 {
         struct hostaudio_state *state = file->private_data;
 	unsigned long data = 0;
-	int err;
+	int ret;
 
 #ifdef DEBUG
         printk("hostaudio: ioctl called, cmd = %u\n", cmd);
@@ -147,7 +158,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
-        err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
+	ret = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
 
 	switch(cmd){
 	case SNDCTL_DSP_SPEED:
@@ -163,7 +174,7 @@ static int hostaudio_ioctl(struct inode *inode, struct file *file,
 		break;
 	}
 
-	return(err);
+	return(ret);
 }
 
 static int hostaudio_open(struct inode *inode, struct file *file)
@@ -182,12 +193,17 @@ static int hostaudio_open(struct inode *inode, struct file *file)
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostaudio_open_user(state, r, w, dsp);
+	ret = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
+
         if(ret < 0){
+		printk("hostaudio_open failed to open '%s', err = %d\n",
+		       dsp, -ret);
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
+
         file->private_data = state;
         return(0);
 }
@@ -195,16 +211,19 @@ static int hostaudio_open(struct inode *inode, struct file *file)
 static int hostaudio_release(struct inode *inode, struct file *file)
 {
         struct hostaudio_state *state = file->private_data;
-        int ret;
 
 #ifdef DEBUG
         printk("hostaudio: release called\n");
 #endif
 
-        ret = hostaudio_release_user(state);
+	if(state->fd >= 0){
+		os_close_file(state->fd);
+		state->fd = -1;
+	}
+
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 /* /dev/mixer file operations */
@@ -218,7 +237,7 @@ static int hostmixer_ioctl_mixdev(struct inode *inode, struct file *file,
         printk("hostmixer: ioctl called\n");
 #endif
 
-        return(hostmixer_ioctl_mixdev_user(state, cmd, arg));
+	return(os_ioctl_generic(state->fd, cmd, arg));
 }
 
 static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
@@ -237,13 +256,17 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
         if(file->f_mode & FMODE_READ) r = 1;
         if(file->f_mode & FMODE_WRITE) w = 1;
 
-        ret = hostmixer_open_mixdev_user(state, r, w, mixer);
+	ret = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
         
         if(ret < 0){
+		printk("hostaudio_open_mixdev failed to open '%s', err = %d\n",
+		       dsp, -ret);
 		kfree(state);
 		return(ret);
         }
 
+	state->fd = ret;
+
         file->private_data = state;
         return(0);
 }
@@ -251,16 +274,18 @@ static int hostmixer_open_mixdev(struct inode *inode, struct file *file)
 static int hostmixer_release(struct inode *inode, struct file *file)
 {
         struct hostmixer_state *state = file->private_data;
-	int ret;
 
 #ifdef DEBUG
         printk("hostmixer: release called\n");
 #endif
 
-        ret = hostmixer_release_mixdev_user(state);
+	if(state->fd >= 0){
+		os_close_file(state->fd);
+		state->fd = -1;
+	}
         kfree(state);
 
-        return(ret);
+	return(0);
 }
 
 
diff --git a/arch/um/drivers/hostaudio_user.c b/arch/um/drivers/hostaudio_user.c
deleted file mode 100644
index b89fefb4a..000000000
--- a/arch/um/drivers/hostaudio_user.c
+++ /dev/null
@@ -1,130 +0,0 @@
-/* 
- * Copyright (C) 2002 Steve Schmidtke 
- * Licensed under the GPL
- */
-
-#include <sys/types.h>
-#include <unistd.h>
-#include <errno.h>
-#include "hostaudio.h"
-#include "user_util.h"
-#include "kern_util.h"
-#include "user.h"
-#include "os.h"
-
-/* /dev/dsp file operations */
-
-ssize_t hostaudio_read_user(struct hostaudio_state *state, char *buffer, 
-			    size_t count, loff_t *ppos)
-{
-#ifdef DEBUG
-        printk("hostaudio: read_user called, count = %d\n", count);
-#endif
-
-	return(os_read_file(state->fd, buffer, count));
-}
-
-ssize_t hostaudio_write_user(struct hostaudio_state *state, const char *buffer,
-			     size_t count, loff_t *ppos)
-{
-#ifdef DEBUG
-        printk("hostaudio: write_user called, count = %d\n", count);
-#endif
-
-	return(os_write_file(state->fd, buffer, count));
-}
-
-int hostaudio_ioctl_user(struct hostaudio_state *state, unsigned int cmd, 
-			 unsigned long arg)
-{
-#ifdef DEBUG
-        printk("hostaudio: ioctl_user called, cmd = %u\n", cmd);
-#endif
-
-	return(os_ioctl_generic(state->fd, cmd, arg));
-}
-
-int hostaudio_open_user(struct hostaudio_state *state, int r, int w, char *dsp)
-{
-#ifdef DEBUG
-        printk("hostaudio: open_user called\n");
-#endif
-
-	state->fd = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-
-	if(state->fd < 0) {
-		printk("hostaudio_open_user failed to open '%s', err = %d\n",
-		       dsp, -state->fd);
-		return(state->fd); 
-	}
-        
-	return(0);
-}
-
-int hostaudio_release_user(struct hostaudio_state *state)
-{
-#ifdef DEBUG
-        printk("hostaudio: release called\n");
-#endif
-	if(state->fd >= 0){
-		os_close_file(state->fd);
-		state->fd = -1;
-	}
-
-        return(0);
-}
-
-/* /dev/mixer file operations */
-
-int hostmixer_ioctl_mixdev_user(struct hostmixer_state *state, 
-				unsigned int cmd, unsigned long arg)
-{
-#ifdef DEBUG
-        printk("hostmixer: ioctl_user called cmd = %u\n",cmd);
-#endif
-
-	return(os_ioctl_generic(state->fd, cmd, arg));
-}
-
-int hostmixer_open_mixdev_user(struct hostmixer_state *state, int r, int w,
-			       char *mixer)
-{
-#ifdef DEBUG
-        printk("hostmixer: open_user called\n");
-#endif
-
-        state->fd = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
-
-	if(state->fd < 0) {
-	        printk("hostaudio_open_mixdev_user failed to open '%s', "
-		       "err = %d\n", mixer, state->fd);
-		return(state->fd); 
-	}
-        
-	return(0);
-}
-
-int hostmixer_release_mixdev_user(struct hostmixer_state *state)
-{
-#ifdef DEBUG
-        printk("hostmixer: release_user called\n");
-#endif
-
-        if(state->fd >= 0){
-		os_close_file(state->fd);
-		state->fd = -1;
-        }
-
-        return 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:
- */
diff --git a/arch/um/include/os.h b/arch/um/include/os.h
index 269156ede..1ea6838f2 100644
--- a/arch/um/include/os.h
+++ b/arch/um/include/os.h
@@ -130,6 +130,7 @@ extern int os_get_ifname(int fd, char *namebuf);
 extern int os_set_slip(int fd);
 extern int os_set_owner(int fd, int pid);
 extern int os_sigio_async(int master, int slave);
+extern int os_make_pty_raw(int master);
 extern int os_mode_fd(int fd, int mode);
 
 extern int os_seek_file(int fd, __u64 offset);
diff --git a/arch/um/kernel/process.c b/arch/um/kernel/process.c
index 01ad09884..516f7356e 100644
--- a/arch/um/kernel/process.c
+++ b/arch/um/kernel/process.c
@@ -19,6 +19,7 @@
 #include <asm/sigcontext.h>
 #include <asm/unistd.h>
 #include <asm/page.h>
+#include <asm/user.h>
 #include "user_util.h"
 #include "kern_util.h"
 #include "user.h"
@@ -195,6 +196,22 @@ static void stop_ptraced_child(int pid, void *stack, int exitcode)
 		panic("check_ptrace : munmap failed, errno = %d", errno);
 }
 
+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");
+
 void __init check_ptrace(void)
 {
 	void *stack;
@@ -227,6 +244,42 @@ void __init check_ptrace(void)
 	}
 	stop_ptraced_child(pid, stack, 0);
 	printk("OK\n");
+
+	printk("Checking syscall emulation patch for ptrace...");
+	set_using_sysemu(0);
+	pid = start_ptraced_child(&stack);
+	if(ptrace(PTRACE_SYSEMU, pid, 0, 0) >= 0) {
+		struct user_regs_struct regs;
+
+		if (waitpid(pid, &status, WUNTRACED) < 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, &regs) < 0)
+			panic("check_ptrace : failed to read child "
+			      "registers, errno = %d", errno);
+		regs.orig_eax = pid;
+		if (ptrace(PTRACE_SETREGS, pid, 0, &regs) < 0)
+			panic("check_ptrace : failed to modify child "
+			      "registers, errno = %d", errno);
+
+		stop_ptraced_child(pid, stack, 0);
+
+		if (!force_sysemu_disabled) {
+			printk("found\n");
+			set_using_sysemu(1);
+		} else {
+			printk("found but disabled\n");
+		}
+	}
+	else
+	{
+		printk("missing\n");
+		stop_ptraced_child(pid, stack, 1);
+	}
+
 }
 
 int run_kernel_thread(int (*fn)(void *), void *arg, void **jmp_ptr)
diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c
index 6a9b38978..b8a64cb18 100644
--- a/arch/um/kernel/sigio_user.c
+++ b/arch/um/kernel/sigio_user.c
@@ -50,7 +50,6 @@ static void openpty_cb(void *arg)
 void __init check_one_sigio(void (*proc)(int, int))
 {
 	struct sigaction old, new;
-	struct termios tt;
 	struct openpty_arg pty = { .master = -1, .slave = -1 };
 	int master, slave, err;
 
@@ -68,12 +67,9 @@ void __init check_one_sigio(void (*proc)(int, int))
 		return;
 	}
 
-	/* XXX These can fail with EINTR */
-	if(tcgetattr(master, &tt) < 0)
-		panic("check_sigio : tcgetattr failed, errno = %d\n", errno);
-	cfmakeraw(&tt);
-	if(tcsetattr(master, TCSADRAIN, &tt) < 0)
-		panic("check_sigio : tcsetattr failed, errno = %d\n", errno);
+	err = os_make_pty_raw(master);
+	if (err < 0)
+		panic("check_sigio : os_make_pty_raw failed, errno = %d\n", -err);
 
 	err = os_sigio_async(master, slave);
 	if(err < 0)
diff --git a/arch/um/kernel/skas/include/ptrace-skas.h b/arch/um/kernel/skas/include/ptrace-skas.h
index f5c5268cc..3173a1b55 100644
--- a/arch/um/kernel/skas/include/ptrace-skas.h
+++ b/arch/um/kernel/skas/include/ptrace-skas.h
@@ -10,6 +10,15 @@
 
 #ifdef UML_CONFIG_MODE_SKAS
 
+/* syscall emulation path in ptrace */
+
+#ifndef PTRACE_SYSEMU
+#define PTRACE_SYSEMU 31
+#endif
+
+void set_using_sysemu(int value);
+int get_using_sysemu(void);
+
 #include "skas_ptregs.h"
 
 #define HOST_FRAME_SIZE 17
diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c
index 7e489869d..13c3bb155 100644
--- a/arch/um/kernel/skas/process.c
+++ b/arch/um/kernel/skas/process.c
@@ -57,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;
 
@@ -68,20 +69,23 @@ static void handle_trap(int pid, union uml_pt_regs *regs)
 		return;
 	}
 
-	err = ptrace(PTRACE_POKEUSER, pid, PT_SYSCALL_NR_OFFSET, __NR_getpid);
-	if(err < 0)
-	        panic("handle_trap - nullifying syscall failed errno = %d\n", 
-		      errno);
+	if (!local_using_sysemu)
+	{
+		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);
+		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);
+	}
 
 	handle_syscall(regs);
 }
@@ -136,10 +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);
 		
-	err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
+	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);
 	if(err)
 		panic("userspace - PTRACE_SYSCALL failed, errno = %d\n", 
 		       errno);
@@ -158,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:
@@ -177,8 +187,16 @@ void userspace(union uml_pt_regs *regs)
 
 		restore_registers(regs);
 
-		op = singlestepping_skas() ? PTRACE_SINGLESTEP : 
-			PTRACE_SYSCALL;
+		/*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;
+
 		err = ptrace(op, pid, 0, 0);
 		if(err)
 			panic("userspace - PTRACE_SYSCALL failed, "
diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c
index ec62366ac..5bb40a3f7 100644
--- a/arch/um/kernel/skas/process_kern.c
+++ b/arch/um/kernel/skas/process_kern.c
@@ -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"
@@ -17,6 +23,59 @@
 #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;
diff --git a/arch/um/os-Linux/file.c b/arch/um/os-Linux/file.c
index 4083bf96c..5241b7fad 100644
--- a/arch/um/os-Linux/file.c
+++ b/arch/um/os-Linux/file.c
@@ -8,6 +8,7 @@
 #include <errno.h>
 #include <fcntl.h>
 #include <signal.h>
+#include <termios.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/socket.h>
@@ -132,6 +133,32 @@ int os_new_tty_pgrp(int fd, int pid)
 	return(0);
 }
 
+int os_make_pty_raw(int master)
+{
+	struct termios tt;
+	int err;
+
+	while (((err = tcgetattr(master, &tt)) < 0) && errno == EINTR)
+		;
+	if(err < 0) {
+		printk("os_make_pty_raw : tcgetattr failed, errno = %d\n", errno);
+		goto fail;
+	}
+
+	cfmakeraw(&tt);
+
+	while (((err = tcsetattr(master, TCSADRAIN, &tt)) < 0) && errno == EINTR)
+		;
+	if(err < 0) {
+		printk("os_make_pty_raw : tcsetattr failed, errno = %d\n", errno);
+		goto fail;
+	}
+
+	return 0;
+fail:
+	return -errno;
+}
+
 /* FIXME: ensure namebuf in os_get_if_name is big enough */
 int os_get_ifname(int fd, char* namebuf)
 {
diff --git a/scripts/basic/fixdep.c b/scripts/basic/fixdep.c
index 8bd644222..4cda24e15 100644
--- a/scripts/basic/fixdep.c
+++ b/scripts/basic/fixdep.c
@@ -93,6 +93,14 @@
  * (Note: it'd be easy to port over the complete mkdep state machine,
  *  but I don't think the added complexity is worth it)
  */
+/*
+ * Note 2: if somebody writes HELLO_CONFIG_BOOM in a file, it will depend onto
+ * CONFIG_BOOM. This could seem a bug (not too hard to fix), but please do not
+ * fix it! Some UserModeLinux files (look at arch/um/) call CONFIG_BOOM as
+ * UML_CONFIG_BOOM, to avoid conflicts with /usr/include/linux/autoconf.h,
+ * through arch/um/include/uml-config.h; this fixdep "bug" makes sure that
+ * those files will have correct dependencies.
+ */
 
 #include <sys/types.h>
 #include <sys/stat.h>
@@ -310,6 +318,7 @@ void parse_dep_file(void *map, size_t len)
 		}
 		memcpy(s, m, p-m); s[p-m] = 0;
 		if (strrcmp(s, "include/linux/autoconf.h") &&
+		    strrcmp(s, "arch/um/include/uml-config.h") &&
 		    strrcmp(s, ".ver")) {
 			printf("  %s \\\n", s);
 			do_config_file(s);