config UNIX98_PTYS
bool "Unix98 PTY support"
- ---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
+
+config UNIX98_PTY_COUNT
+ int "Maximum number of Unix98 PTYs in use (0-2048)"
+ depends on UNIX98_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"
-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
$(Q)$(MAKE) $(build)=$@
export SUBARCH USER_CFLAGS OS
-
-all: linux
-
-define archhelp
- echo '* linux - Binary kernel image (./linux)'
-endef
#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-objs := hostaudio_kern.o hostaudio_user.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
#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)
{
.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;
#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;
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)
{
}
#include "asm/uaccess.h"
#include "kern_util.h"
#include "init.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"
+#include "hostaudio.h"
/* Only changed from linux_main at boot time */
char *dsp = HOSTAUDIO_DEV_DSP;
{
struct hostaudio_state *state = file->private_data;
void *kbuf;
- int ret;
+ int err;
#ifdef DEBUG
printk("hostaudio: read called, count = %d\n", count);
if(kbuf == NULL)
return(-ENOMEM);
- ret = os_read_file(state->fd, kbuf, count);
- if(ret < 0)
+ err = hostaudio_read_user(state, kbuf, count, ppos);
+ if(err < 0)
goto out;
- if(copy_to_user(buffer, kbuf, ret))
- ret = -EFAULT;
+ if(copy_to_user(buffer, kbuf, err))
+ err = -EFAULT;
out:
kfree(kbuf);
- return(ret);
+ return(err);
}
static ssize_t hostaudio_write(struct file *file, const char *buffer,
{
struct hostaudio_state *state = file->private_data;
void *kbuf;
- int ret;
+ int err;
#ifdef DEBUG
printk("hostaudio: write called, count = %d\n", count);
if(kbuf == NULL)
return(-ENOMEM);
- ret = -EFAULT;
+ err = -EFAULT;
if(copy_from_user(kbuf, buffer, count))
goto out;
- ret = os_write_file(state->fd, kbuf, count);
- if(ret < 0)
+ err = hostaudio_write_user(state, kbuf, count, ppos);
+ if(err < 0)
goto out;
out:
kfree(kbuf);
- return(ret);
+ return(err);
}
static unsigned int hostaudio_poll(struct file *file,
{
struct hostaudio_state *state = file->private_data;
unsigned long data = 0;
- int ret;
+ int err;
#ifdef DEBUG
printk("hostaudio: ioctl called, cmd = %u\n", cmd);
break;
}
- ret = os_ioctl_generic(state->fd, cmd, (unsigned long) &data);
+ err = hostaudio_ioctl_user(state, cmd, (unsigned long) &data);
switch(cmd){
case SNDCTL_DSP_SPEED:
break;
}
- return(ret);
+ return(err);
}
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 = os_open_file(dsp, of_set_rw(OPENFLAGS(), r, w), 0);
-
+ ret = hostaudio_open_user(state, r, w, dsp);
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);
}
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
- if(state->fd >= 0){
- os_close_file(state->fd);
- state->fd = -1;
- }
-
+ ret = hostaudio_release_user(state);
kfree(state);
- return(0);
+ return(ret);
}
/* /dev/mixer file operations */
printk("hostmixer: ioctl called\n");
#endif
- return(os_ioctl_generic(state->fd, cmd, arg));
+ return(hostmixer_ioctl_mixdev_user(state, cmd, arg));
}
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 = os_open_file(mixer, of_set_rw(OPENFLAGS(), r, w), 0);
+ ret = hostmixer_open_mixdev_user(state, r, w, mixer);
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);
}
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
- if(state->fd >= 0){
- os_close_file(state->fd);
- state->fd = -1;
- }
+ ret = hostmixer_release_mixdev_user(state);
kfree(state);
- return(0);
+ return(ret);
}
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);
#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"
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;
}
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)
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;
return;
}
- err = os_make_pty_raw(master);
- if (err < 0)
- panic("check_sigio : os_make_pty_raw failed, errno = %d\n", -err);
+ /* 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_sigio_async(master, slave);
if(err < 0)
#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
segv(fault.addr, 0, FAULT_WRITE(fault.is_write), 1, NULL);
}
-/*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)
+static void handle_trap(int pid, union uml_pt_regs *regs)
{
int err, syscall_nr, status;
return;
}
- 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_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);
}
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);
- 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);
+ err = ptrace(PTRACE_SYSCALL, pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, errno = %d\n",
errno);
handle_segv(pid);
break;
case SIGTRAP:
- handle_trap(pid, regs, local_using_sysemu);
+ handle_trap(pid, regs);
break;
case SIGIO:
case SIGVTALRM:
restore_registers(regs);
- /*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;
-
+ op = singlestepping_skas() ? PTRACE_SINGLESTEP :
+ PTRACE_SYSCALL;
err = ptrace(op, pid, 0, 0);
if(err)
panic("userspace - PTRACE_SYSCALL failed, "
#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;
if(!jail || debug)
remap_data(UML_ROUND_DOWN(&_stext), UML_ROUND_UP(&_etext), 1);
remap_data(UML_ROUND_DOWN(&_sdata), UML_ROUND_UP(&_edata), 1);
- remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(brk_start), 1);
+ remap_data(UML_ROUND_DOWN(&__bss_start), UML_ROUND_UP(&_end), 1);
}
#ifdef CONFIG_HOST_2G_2G
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
-#include <termios.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
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)
{
static inline void arch_free_page(struct page *page, int order) { }
#endif
-extern struct page *
+extern struct page *
FASTCALL(__alloc_pages(unsigned int, unsigned int, struct zonelist *));
-
-static inline struct page *alloc_pages_node(int nid, unsigned int gfp_mask,
- unsigned int order)
+static inline struct page * alloc_pages_node(int nid, unsigned int gfp_mask,
+ unsigned int order)
{
if (unlikely(order >= MAX_ORDER))
return NULL;
- return __alloc_pages(gfp_mask, order,
+ return __alloc_pages(gfp_mask, order,
NODE_DATA(nid)->node_zonelists + (gfp_mask & GFP_ZONEMASK));
}