From ad677697bb295fb472c37ba869457f7c9878d2c5 Mon Sep 17 00:00:00 2001 From: Mark Huang Date: Thu, 29 Jul 2004 19:50:30 +0000 Subject: [PATCH] Merge BlaisorBlade patch uml-linux-2.6.7-01-bb1-complete.patch --- arch/um/Kconfig_char | 57 +++++++++- arch/um/Makefile | 8 ++ arch/um/drivers/Makefile | 2 +- arch/um/drivers/chan_kern.c | 47 ++++++++ arch/um/drivers/chan_user.c | 48 -------- arch/um/drivers/hostaudio_kern.c | 73 ++++++++---- arch/um/drivers/hostaudio_user.c | 130 ---------------------- arch/um/include/os.h | 1 + arch/um/kernel/process.c | 53 +++++++++ arch/um/kernel/sigio_user.c | 10 +- arch/um/kernel/skas/include/ptrace-skas.h | 9 ++ arch/um/kernel/skas/process.c | 52 ++++++--- arch/um/kernel/skas/process_kern.c | 59 ++++++++++ arch/um/os-Linux/file.c | 27 +++++ scripts/basic/fixdep.c | 9 ++ 15 files changed, 354 insertions(+), 231 deletions(-) delete mode 100644 arch/um/drivers/hostaudio_user.c 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/. 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 -#include -#include -#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 #include #include +#include #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, ®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); + + 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 #include #include +#include #include #include #include @@ -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 #include @@ -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); -- 2.47.0