diff options
Diffstat (limited to 'arch/um/kernel')
24 files changed, 264 insertions, 425 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index fe08971b64c..a2d93065b2d 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -6,16 +6,14 @@ extra-y := vmlinux.lds clean-files := -obj-y = config.o exec_kern.o exitcode.o \ - init_task.o irq.o ksyms.o mem.o physmem.o \ - process_kern.o ptrace.o reboot.o resource.o sigio_kern.o \ - signal_kern.o smp.o syscall_kern.o sysrq.o \ - time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o +obj-y = config.o exec.o exitcode.o init_task.o irq.o ksyms.o mem.o \ + physmem.o process_kern.o ptrace.o reboot.o resource.o sigio.o \ + signal.o smp.o syscall.o sysrq.o time.o tlb.o trap.o uaccess.o \ + um_arch.o umid.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o obj-$(CONFIG_GCOV) += gmon_syms.o -obj-$(CONFIG_SYSCALL_DEBUG) += syscall.o obj-$(CONFIG_MODE_TT) += tt/ obj-$(CONFIG_MODE_SKAS) += skas/ diff --git a/arch/um/kernel/dyn.lds.S b/arch/um/kernel/dyn.lds.S index 2517ecb8bf2..68ed24df5c8 100644 --- a/arch/um/kernel/dyn.lds.S +++ b/arch/um/kernel/dyn.lds.S @@ -26,6 +26,7 @@ SECTIONS /* Read-only sections, merged into text segment: */ .hash : { *(.hash) } + .gnu.hash : { *(.gnu.hash) } .dynsym : { *(.dynsym) } .dynstr : { *(.dynstr) } .gnu.version : { *(.gnu.version) } diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec.c index c0cb627bf59..fc38a6d5906 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -31,18 +31,27 @@ void start_thread(struct pt_regs *regs, unsigned long eip, unsigned long esp) CHOOSE_MODE_PROC(start_thread_tt, start_thread_skas, regs, eip, esp); } +#ifdef CONFIG_TTY_LOG +extern void log_exec(char **argv, void *tty); +#endif + static long execve1(char *file, char __user * __user *argv, char __user *__user *env) { long error; #ifdef CONFIG_TTY_LOG - log_exec(argv, current->tty); + task_lock(current); + log_exec(argv, current->signal->tty); + task_unlock(current); #endif error = do_execve(file, argv, env, ¤t->thread.regs); if (error == 0){ task_lock(current); current->ptrace &= ~PT_DTRACE; +#ifdef SUBARCH_EXECVE1 + SUBARCH_EXECVE1(¤t->thread.regs.regs); +#endif task_unlock(current); set_cmdline(current_cmd()); } diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index bfd0bdc8cd4..589c69a7504 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -110,18 +110,7 @@ void sigio_handler(int sig, union uml_pt_regs *regs) free_irqs(); } -static void maybe_sigio_broken(int fd, int type) -{ - if (os_isatty(fd)) { - if ((type == IRQ_WRITE) && !pty_output_sigio) { - write_sigio_workaround(); - add_sigio_fd(fd, 0); - } else if ((type == IRQ_READ) && !pty_close_sigio) { - write_sigio_workaround(); - add_sigio_fd(fd, 1); - } - } -} +static DEFINE_SPINLOCK(irq_lock); int activate_fd(int irq, int fd, int type, void *dev_id) { @@ -166,7 +155,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) * this is called only from process context, and can be locked with * a semaphore. */ - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); for (irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next) { if ((irq_fd->fd == fd) && (irq_fd->type == type)) { printk("Registering fd %d twice\n", fd); @@ -199,7 +188,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) * so we will not be able to put new pollfd struct to pollfds * then we free the buffer tmp_fds and try again. */ - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); kfree(tmp_pfd); tmp_pfd = NULL; @@ -207,24 +196,24 @@ int activate_fd(int irq, int fd, int type, void *dev_id) if (tmp_pfd == NULL) goto out_kfree; - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); } /*-------------*/ *last_irq_ptr = new_fd; last_irq_ptr = &new_fd->next; - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); /* This calls activate_fd, so it has to be outside the critical * section. */ - maybe_sigio_broken(fd, type); + maybe_sigio_broken(fd, (type == IRQ_READ)); return(0); out_unlock: - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); out_kfree: kfree(new_fd); out: @@ -235,9 +224,9 @@ static void free_irq_by_cb(int (*test)(struct irq_fd *, void *), void *arg) { unsigned long flags; - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); os_free_irq_by_cb(test, arg, active_fds, &last_irq_ptr); - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); } struct irq_and_dev { @@ -304,19 +293,19 @@ void reactivate_fd(int fd, int irqnum) unsigned long flags; int i; - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); irq = find_irq_by_fd(fd, irqnum, &i); if (irq == NULL) { - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); return; } os_set_pollfd(i, irq->fd); - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); /* This calls activate_fd, so it has to be outside the critical * section. */ - maybe_sigio_broken(fd, irq->type); + maybe_sigio_broken(fd, (irq->type == IRQ_READ)); } void deactivate_fd(int fd, int irqnum) @@ -325,13 +314,13 @@ void deactivate_fd(int fd, int irqnum) unsigned long flags; int i; - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); irq = find_irq_by_fd(fd, irqnum, &i); if (irq == NULL) goto out; os_set_pollfd(i, -1); out: - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); } int deactivate_all_fds(void) @@ -350,13 +339,14 @@ int deactivate_all_fds(void) return 0; } +#ifdef CONFIG_MODE_TT void forward_interrupts(int pid) { struct irq_fd *irq; unsigned long flags; int err; - flags = irq_lock(); + spin_lock_irqsave(&irq_lock, flags); for (irq = active_fds; irq != NULL; irq = irq->next) { err = os_set_owner(irq->fd, pid); if (err < 0) { @@ -369,8 +359,9 @@ void forward_interrupts(int pid) irq->pid = pid; } - irq_unlock(flags); + spin_unlock_irqrestore(&irq_lock, flags); } +#endif /* * do_IRQ handles all normal device IRQ's (the special @@ -403,21 +394,6 @@ int um_request_irq(unsigned int irq, int fd, int type, EXPORT_SYMBOL(um_request_irq); EXPORT_SYMBOL(reactivate_fd); -static DEFINE_SPINLOCK(irq_spinlock); - -unsigned long irq_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&irq_spinlock, flags); - return flags; -} - -void irq_unlock(unsigned long flags) -{ - spin_unlock_irqrestore(&irq_spinlock, flags); -} - /* hw_interrupt_type must define (startup || enable) && * (shutdown || disable) && end */ static void dummy(unsigned int irq) diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index 432cf0b97a1..c97045d6d89 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -88,12 +88,6 @@ EXPORT_SYMBOL(dump_thread); EXPORT_SYMBOL(do_gettimeofday); EXPORT_SYMBOL(do_settimeofday); -/* This is here because UML expands lseek to sys_lseek, not to a system - * call instruction. - */ -EXPORT_SYMBOL(sys_lseek); -EXPORT_SYMBOL(sys_wait4); - #ifdef CONFIG_SMP /* required for SMP */ diff --git a/arch/um/kernel/mem.c b/arch/um/kernel/mem.c index 44e41a35f00..61280167c56 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -24,8 +24,6 @@ #include "init.h" #include "kern_constants.h" -extern char __binary_start; - /* Changed during early boot */ unsigned long *empty_zero_page = NULL; unsigned long *empty_bad_page = NULL; @@ -65,8 +63,6 @@ static void setup_highmem(unsigned long highmem_start, void mem_init(void) { - unsigned long start; - max_low_pfn = (high_physmem - uml_physmem) >> PAGE_SHIFT; /* clear the zero-page */ @@ -81,13 +77,6 @@ void mem_init(void) free_bootmem(__pa(brk_end), uml_reserved - brk_end); uml_reserved = brk_end; - /* Fill in any hole at the start of the binary */ - start = (unsigned long) &__binary_start & PAGE_MASK; - if(uml_physmem != start){ - map_memory(uml_physmem, __pa(uml_physmem), start - uml_physmem, - 1, 1, 0); - } - /* this will put all low memory onto the freelists */ totalram_pages = free_all_bootmem(); totalhigh_pages = highmem >> PAGE_SHIFT; diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index 166cb09cae4..abafa64b872 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -317,7 +317,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, } } -extern int __syscall_stub_start, __binary_start; +extern int __syscall_stub_start; void setup_physmem(unsigned long start, unsigned long reserve_end, unsigned long len, unsigned long long highmem) diff --git a/arch/um/kernel/sigio_kern.c b/arch/um/kernel/sigio.c index 51b67708394..0ad755ceb21 100644 --- a/arch/um/kernel/sigio_kern.c +++ b/arch/um/kernel/sigio.c @@ -31,7 +31,7 @@ int write_sigio_irq(int fd) int err; err = um_request_irq(SIGIO_WRITE_IRQ, fd, IRQ_READ, sigio_interrupt, - IRQF_DISABLED | IRQF_SAMPLE_RANDOM, "write sigio", + IRQF_DISABLED|IRQF_SAMPLE_RANDOM, "write sigio", NULL); if(err){ printk("write_sigio_irq : um_request_irq failed, err = %d\n", @@ -53,17 +53,3 @@ void sigio_unlock(void) { spin_unlock(&sigio_spinlock); } - -extern void sigio_cleanup(void); -__uml_exitcall(sigio_cleanup); - -/* - * 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/kernel/signal_kern.c b/arch/um/kernel/signal.c index da17b7541e0..4aa9808ba26 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -36,7 +36,7 @@ EXPORT_SYMBOL(unblock_signals); /* * OK, we're invoking a handler - */ + */ static int handle_signal(struct pt_regs *regs, unsigned long signr, struct k_sigaction *ka, siginfo_t *info, sigset_t *oldset) @@ -88,7 +88,7 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, force_sigsegv(signr, current); } else { spin_lock_irq(¤t->sighand->siglock); - sigorsets(¤t->blocked, ¤t->blocked, + sigorsets(¤t->blocked, ¤t->blocked, &ka->sa.sa_mask); if(!(ka->sa.sa_flags & SA_NODEFER)) sigaddset(¤t->blocked, signr); @@ -136,7 +136,7 @@ static int kern_do_signal(struct pt_regs *regs) PT_REGS_RESTART_SYSCALL(regs); break; case -ERESTART_RESTARTBLOCK: - PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; + PT_REGS_ORIG_SYSCALL(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); break; } @@ -146,7 +146,7 @@ static int kern_do_signal(struct pt_regs *regs) * you set a breakpoint on a system call instruction and singlestep * from it, the tracing thread used to PTRACE_SINGLESTEP the process * rather than PTRACE_SYSCALL it, allowing the system call to execute - * on the host. The tracing thread will check this flag and + * on the host. The tracing thread will check this flag and * PTRACE_SYSCALL if necessary. */ if(current->ptrace & PT_DTRACE) diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 88ab96c609c..27bbf54b1e5 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -9,31 +9,19 @@ #include "mem_user.h" #include "skas.h" -unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, - unsigned long *task_size_out) +unsigned long set_task_sizes_skas(unsigned long *task_size_out) { /* Round up to the nearest 4M */ - unsigned long top = ROUND_4M((unsigned long) &arg); + unsigned long host_task_size = ROUND_4M((unsigned long) + &host_task_size); #ifdef CONFIG_HOST_TASK_SIZE - *host_size_out = CONFIG_HOST_TASK_SIZE; + *host_size_out = ROUND_4M(CONFIG_HOST_TASK_SIZE); *task_size_out = CONFIG_HOST_TASK_SIZE; #else - *host_size_out = top; if (!skas_needs_stub) - *task_size_out = top; + *task_size_out = host_task_size; else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; #endif - return(((unsigned long) set_task_sizes_skas) & ~0xffffff); + return host_task_size; } - -/* - * 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/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 2135eaf98a9..55caeec8b25 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -177,7 +177,7 @@ int start_uml_skas(void) if(proc_mm) userspace_pid[0] = start_userspace(0); - init_new_thread_signals(1); + init_new_thread_signals(); init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; diff --git a/arch/um/kernel/skas/syscall.c b/arch/um/kernel/skas/syscall.c index 51fb94076fc..0ae4eea21be 100644 --- a/arch/um/kernel/skas/syscall.c +++ b/arch/um/kernel/skas/syscall.c @@ -18,11 +18,7 @@ void handle_syscall(union uml_pt_regs *r) struct pt_regs *regs = container_of(r, struct pt_regs, regs); long result; int syscall; -#ifdef UML_CONFIG_SYSCALL_DEBUG - int index; - index = record_syscall_start(UPT_SYSCALL_NR(r)); -#endif syscall_trace(r, 0); current->thread.nsyscalls++; @@ -44,7 +40,4 @@ void handle_syscall(union uml_pt_regs *r) REGS_SET_SYSCALL_RETURN(r->skas.regs, result); syscall_trace(r, 1); -#ifdef UML_CONFIG_SYSCALL_DEBUG - record_syscall_end(index, result); -#endif } diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 1731d90e685..48cf88dd02d 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -1,36 +1,166 @@ /* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) + * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) * Licensed under the GPL */ +#include "linux/sched.h" +#include "linux/file.h" +#include "linux/smp_lock.h" +#include "linux/mm.h" +#include "linux/utsname.h" +#include "linux/msg.h" +#include "linux/shm.h" +#include "linux/sys.h" +#include "linux/syscalls.h" +#include "linux/unistd.h" +#include "linux/slab.h" +#include "linux/utime.h" +#include "asm/mman.h" +#include "asm/uaccess.h" #include "kern_util.h" -#include "syscall.h" -#include "os.h" +#include "user_util.h" +#include "sysdep/syscalls.h" +#include "mode_kern.h" +#include "choose-mode.h" -struct { - int syscall; - int pid; - long result; - unsigned long long start; - unsigned long long end; -} syscall_record[1024]; +/* Unlocked, I don't care if this is a bit off */ +int nsyscalls = 0; -int record_syscall_start(int syscall) +long sys_fork(void) { - int max, index; + long ret; - max = sizeof(syscall_record)/sizeof(syscall_record[0]); - index = next_syscall_index(max); + current->thread.forking = 1; + ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), + ¤t->thread.regs, 0, NULL, NULL); + current->thread.forking = 0; + return(ret); +} + +long sys_vfork(void) +{ + long ret; + + current->thread.forking = 1; + ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, + UPT_SP(¤t->thread.regs.regs), + ¤t->thread.regs, 0, NULL, NULL); + current->thread.forking = 0; + return(ret); +} + +/* common code for old and new mmaps */ +long sys_mmap2(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long pgoff) +{ + long error = -EBADF; + struct file * file = NULL; + + flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); + if (!(flags & MAP_ANONYMOUS)) { + file = fget(fd); + if (!file) + goto out; + } + + down_write(¤t->mm->mmap_sem); + error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); + up_write(¤t->mm->mmap_sem); + + if (file) + fput(file); + out: + return error; +} + +long old_mmap(unsigned long addr, unsigned long len, + unsigned long prot, unsigned long flags, + unsigned long fd, unsigned long offset) +{ + long err = -EINVAL; + if (offset & ~PAGE_MASK) + goto out; + + err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); + out: + return err; +} +/* + * sys_pipe() is the normal C calling standard for creating + * a pipe. It's not the way unix traditionally does this, though. + */ +long sys_pipe(unsigned long __user * fildes) +{ + int fd[2]; + long error; + + error = do_pipe(fd); + if (!error) { + if (copy_to_user(fildes, fd, sizeof(fd))) + error = -EFAULT; + } + return error; +} - syscall_record[index].syscall = syscall; - syscall_record[index].pid = current_pid(); - syscall_record[index].result = 0xdeadbeef; - syscall_record[index].start = os_nsecs(); - return(index); + +long sys_uname(struct old_utsname __user * name) +{ + long err; + if (!name) + return -EFAULT; + down_read(&uts_sem); + err = copy_to_user(name, &system_utsname, sizeof (*name)); + up_read(&uts_sem); + return err?-EFAULT:0; } -void record_syscall_end(int index, long result) +long sys_olduname(struct oldold_utsname __user * name) { - syscall_record[index].result = result; - syscall_record[index].end = os_nsecs(); + long error; + + if (!name) + return -EFAULT; + if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) + return -EFAULT; + + down_read(&uts_sem); + + error = __copy_to_user(&name->sysname,&system_utsname.sysname, + __OLD_UTS_LEN); + error |= __put_user(0,name->sysname+__OLD_UTS_LEN); + error |= __copy_to_user(&name->nodename,&system_utsname.nodename, + __OLD_UTS_LEN); + error |= __put_user(0,name->nodename+__OLD_UTS_LEN); + error |= __copy_to_user(&name->release,&system_utsname.release, + __OLD_UTS_LEN); + error |= __put_user(0,name->release+__OLD_UTS_LEN); + error |= __copy_to_user(&name->version,&system_utsname.version, + __OLD_UTS_LEN); + error |= __put_user(0,name->version+__OLD_UTS_LEN); + error |= __copy_to_user(&name->machine,&system_utsname.machine, + __OLD_UTS_LEN); + error |= __put_user(0,name->machine+__OLD_UTS_LEN); + + up_read(&uts_sem); + + error = error ? -EFAULT : 0; + + return error; +} + +DEFINE_SPINLOCK(syscall_lock); + +static int syscall_index = 0; + +int next_syscall_index(int limit) +{ + int ret; + + spin_lock(&syscall_lock); + ret = syscall_index; + if(++syscall_index == limit) + syscall_index = 0; + spin_unlock(&syscall_lock); + return(ret); } diff --git a/arch/um/kernel/syscall_kern.c b/arch/um/kernel/syscall_kern.c deleted file mode 100644 index 37d3978337d..00000000000 --- a/arch/um/kernel/syscall_kern.c +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include "linux/sched.h" -#include "linux/file.h" -#include "linux/smp_lock.h" -#include "linux/mm.h" -#include "linux/utsname.h" -#include "linux/msg.h" -#include "linux/shm.h" -#include "linux/sys.h" -#include "linux/syscalls.h" -#include "linux/unistd.h" -#include "linux/slab.h" -#include "linux/utime.h" -#include "asm/mman.h" -#include "asm/uaccess.h" -#include "kern_util.h" -#include "user_util.h" -#include "sysdep/syscalls.h" -#include "mode_kern.h" -#include "choose-mode.h" - -/* Unlocked, I don't care if this is a bit off */ -int nsyscalls = 0; - -long sys_fork(void) -{ - long ret; - - current->thread.forking = 1; - ret = do_fork(SIGCHLD, UPT_SP(¤t->thread.regs.regs), - ¤t->thread.regs, 0, NULL, NULL); - current->thread.forking = 0; - return(ret); -} - -long sys_vfork(void) -{ - long ret; - - current->thread.forking = 1; - ret = do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, - UPT_SP(¤t->thread.regs.regs), - ¤t->thread.regs, 0, NULL, NULL); - current->thread.forking = 0; - return(ret); -} - -/* common code for old and new mmaps */ -long sys_mmap2(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long pgoff) -{ - long error = -EBADF; - struct file * file = NULL; - - flags &= ~(MAP_EXECUTABLE | MAP_DENYWRITE); - if (!(flags & MAP_ANONYMOUS)) { - file = fget(fd); - if (!file) - goto out; - } - - down_write(¤t->mm->mmap_sem); - error = do_mmap_pgoff(file, addr, len, prot, flags, pgoff); - up_write(¤t->mm->mmap_sem); - - if (file) - fput(file); - out: - return error; -} - -long old_mmap(unsigned long addr, unsigned long len, - unsigned long prot, unsigned long flags, - unsigned long fd, unsigned long offset) -{ - long err = -EINVAL; - if (offset & ~PAGE_MASK) - goto out; - - err = sys_mmap2(addr, len, prot, flags, fd, offset >> PAGE_SHIFT); - out: - return err; -} -/* - * sys_pipe() is the normal C calling standard for creating - * a pipe. It's not the way unix traditionally does this, though. - */ -long sys_pipe(unsigned long __user * fildes) -{ - int fd[2]; - long error; - - error = do_pipe(fd); - if (!error) { - if (copy_to_user(fildes, fd, sizeof(fd))) - error = -EFAULT; - } - return error; -} - - -long sys_uname(struct old_utsname __user * name) -{ - long err; - if (!name) - return -EFAULT; - down_read(&uts_sem); - err=copy_to_user(name, &system_utsname, sizeof (*name)); - up_read(&uts_sem); - return err?-EFAULT:0; -} - -long sys_olduname(struct oldold_utsname __user * name) -{ - long error; - - if (!name) - return -EFAULT; - if (!access_ok(VERIFY_WRITE,name,sizeof(struct oldold_utsname))) - return -EFAULT; - - down_read(&uts_sem); - - error = __copy_to_user(&name->sysname,&system_utsname.sysname, - __OLD_UTS_LEN); - error |= __put_user(0,name->sysname+__OLD_UTS_LEN); - error |= __copy_to_user(&name->nodename,&system_utsname.nodename, - __OLD_UTS_LEN); - error |= __put_user(0,name->nodename+__OLD_UTS_LEN); - error |= __copy_to_user(&name->release,&system_utsname.release, - __OLD_UTS_LEN); - error |= __put_user(0,name->release+__OLD_UTS_LEN); - error |= __copy_to_user(&name->version,&system_utsname.version, - __OLD_UTS_LEN); - error |= __put_user(0,name->version+__OLD_UTS_LEN); - error |= __copy_to_user(&name->machine,&system_utsname.machine, - __OLD_UTS_LEN); - error |= __put_user(0,name->machine+__OLD_UTS_LEN); - - up_read(&uts_sem); - - error = error ? -EFAULT : 0; - - return error; -} - -DEFINE_SPINLOCK(syscall_lock); - -static int syscall_index = 0; - -int next_syscall_index(int limit) -{ - int ret; - - spin_lock(&syscall_lock); - ret = syscall_index; - if(++syscall_index == limit) - syscall_index = 0; - spin_unlock(&syscall_lock); - return(ret); -} diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time.c index d7e044b5e5e..552ca1cb984 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time.c @@ -38,7 +38,6 @@ unsigned long long sched_clock(void) /* Changed at early boot */ int timer_irq_inited = 0; -static int first_tick; static unsigned long long prev_nsecs; #ifdef CONFIG_UML_REAL_TIME_CLOCK static long long delta; /* Deviation per interval */ @@ -48,15 +47,8 @@ void timer_irq(union uml_pt_regs *regs) { unsigned long long ticks = 0; - if(!timer_irq_inited){ - /* This is to ensure that ticks don't pile up when - * the timer handler is suspended */ - first_tick = 0; - return; - } - - if(first_tick){ #ifdef CONFIG_UML_REAL_TIME_CLOCK + if(prev_nsecs){ /* We've had 1 tick */ unsigned long long nsecs = os_nsecs(); @@ -69,44 +61,17 @@ void timer_irq(union uml_pt_regs *regs) ticks += (delta * HZ) / BILLION; delta -= (ticks * BILLION) / HZ; + } + else prev_nsecs = os_nsecs(); #else - ticks = 1; + ticks = 1; #endif - } - else { - prev_nsecs = os_nsecs(); - first_tick = 1; - } - while(ticks > 0){ do_IRQ(TIMER_IRQ, regs); ticks--; } } - -void time_init_kern(void) -{ - long long nsecs; - - nsecs = os_nsecs(); - set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, - -nsecs % BILLION); -} - -void do_boot_timer_handler(struct sigcontext * sc) -{ - unsigned long flags; - struct pt_regs regs; - - CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), - (void) (regs.regs.skas.is_user = 0)); - - write_seqlock_irqsave(&xtime_lock, flags); - do_timer(®s); - write_sequnlock_irqrestore(&xtime_lock, flags); -} - static DEFINE_SPINLOCK(timer_spinlock); static unsigned long long local_offset = 0; @@ -142,6 +107,32 @@ irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) return IRQ_HANDLED; } +static void register_timer(void) +{ + int err; + + err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); + if(err != 0) + printk(KERN_ERR "timer_init : request_irq failed - " + "errno = %d\n", -err); + + timer_irq_inited = 1; + + user_time_init(); +} + +extern void (*late_time_init)(void); + +void time_init(void) +{ + long long nsecs; + + nsecs = os_nsecs(); + set_normalized_timespec(&wall_to_monotonic, -nsecs / BILLION, + -nsecs % BILLION); + late_time_init = register_timer; +} + void do_gettimeofday(struct timeval *tv) { unsigned long long nsecs = get_time(); @@ -189,18 +180,3 @@ void timer_handler(int sig, union uml_pt_regs *regs) if(current_thread->cpu == 0) timer_irq(regs); } - -int __init timer_init(void) -{ - int err; - - user_time_init(); - err = request_irq(TIMER_IRQ, um_timer, IRQF_DISABLED, "timer", NULL); - if(err != 0) - printk(KERN_ERR "timer_init : request_irq failed - " - "errno = %d\n", -err); - timer_irq_inited = 1; - return(0); -} - -arch_initcall(timer_init); diff --git a/arch/um/kernel/trap_kern.c |