diff options
Diffstat (limited to 'arch/um/kernel')
32 files changed, 213 insertions, 1081 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 193cc2b7448..693018ba80f 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -9,9 +9,8 @@ clean-files := obj-y = config.o exec_kern.o exitcode.o \ init_task.o irq.o irq_user.o ksyms.o mem.o physmem.o \ process_kern.o ptrace.o reboot.o resource.o sigio_user.o sigio_kern.o \ - signal_kern.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o uaccess.o um_arch.o umid.o \ - user_util.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-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,7 +23,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o +USER_OBJS := $(user-objs-y) config.o tty_log.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/exec_kern.c b/arch/um/kernel/exec_kern.c index efd222ffe20..569fe8b9b05 100644 --- a/arch/um/kernel/exec_kern.c +++ b/arch/um/kernel/exec_kern.c @@ -17,7 +17,6 @@ #include "irq_user.h" #include "tlb.h" #include "os.h" -#include "time_user.h" #include "choose-mode.h" #include "mode_kern.h" diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 7f13b85d265..3113cab8675 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -39,7 +39,6 @@ #include "init.h" #include "irq_user.h" #include "mem_user.h" -#include "time_user.h" #include "tlb.h" #include "frame_kern.h" #include "sigcontext.h" @@ -288,17 +287,27 @@ EXPORT_SYMBOL(disable_hlt); void *um_kmalloc(int size) { - return(kmalloc(size, GFP_KERNEL)); + return kmalloc(size, GFP_KERNEL); } void *um_kmalloc_atomic(int size) { - return(kmalloc(size, GFP_ATOMIC)); + return kmalloc(size, GFP_ATOMIC); } void *um_vmalloc(int size) { - return(vmalloc(size)); + return vmalloc(size); +} + +void *um_vmalloc_atomic(int size) +{ + return __vmalloc(size, GFP_ATOMIC | __GFP_HIGHMEM, PAGE_KERNEL); +} + +int __cant_sleep(void) { + return in_atomic() || irqs_disabled() || in_interrupt(); + /* Is in_interrupt() really needed? */ } unsigned long get_fault_addr(void) @@ -370,11 +379,6 @@ int smp_sigio_handler(void) return(0); } -int um_in_interrupt(void) -{ - return(in_interrupt()); -} - int cpu(void) { return(current_thread->cpu); diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 62e5cfdf218..f7b18e157d3 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -337,70 +337,103 @@ int ignore_sigio_fd(int fd) return(err); } -static int setup_initial_poll(int fd) +static struct pollfd* setup_initial_poll(int fd) { struct pollfd *p; - p = um_kmalloc_atomic(sizeof(struct pollfd)); - if(p == NULL){ + p = um_kmalloc(sizeof(struct pollfd)); + if (p == NULL) { printk("setup_initial_poll : failed to allocate poll\n"); - return(-1); + return NULL; } *p = ((struct pollfd) { .fd = fd, .events = POLLIN, .revents = 0 }); - current_poll = ((struct pollfds) { .poll = p, - .used = 1, - .size = 1 }); - return(0); + return p; } void write_sigio_workaround(void) { unsigned long stack; + struct pollfd *p; int err; + int l_write_sigio_fds[2]; + int l_sigio_private[2]; + int l_write_sigio_pid; + /* We call this *tons* of times - and most ones we must just fail. */ sigio_lock(); - if(write_sigio_pid != -1) - goto out; + l_write_sigio_pid = write_sigio_pid; + sigio_unlock(); - err = os_pipe(write_sigio_fds, 1, 1); + if (l_write_sigio_pid != -1) + return; + + err = os_pipe(l_write_sigio_fds, 1, 1); if(err < 0){ printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); - goto out; + return; } - err = os_pipe(sigio_private, 1, 1); + err = os_pipe(l_sigio_private, 1, 1); if(err < 0){ - printk("write_sigio_workaround - os_pipe 2 failed, " + printk("write_sigio_workaround - os_pipe 1 failed, " "err = %d\n", -err); goto out_close1; } - if(setup_initial_poll(sigio_private[1])) + + p = setup_initial_poll(l_sigio_private[1]); + if(!p) goto out_close2; - write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, + sigio_lock(); + + /* Did we race? Don't try to optimize this, please, it's not so likely + * to happen, and no more than once at the boot. */ + if(write_sigio_pid != -1) + goto out_unlock; + + write_sigio_pid = run_helper_thread(write_sigio_thread, NULL, CLONE_FILES | CLONE_VM, &stack, 0); - if(write_sigio_pid < 0) goto out_close2; + if (write_sigio_pid < 0) + goto out_clear; - if(write_sigio_irq(write_sigio_fds[0])) + if (write_sigio_irq(l_write_sigio_fds[0])) goto out_kill; - out: + /* Success, finally. */ + memcpy(write_sigio_fds, l_write_sigio_fds, sizeof(l_write_sigio_fds)); + memcpy(sigio_private, l_sigio_private, sizeof(l_sigio_private)); + + current_poll = ((struct pollfds) { .poll = p, + .used = 1, + .size = 1 }); + sigio_unlock(); return; out_kill: - os_kill_process(write_sigio_pid, 1); + l_write_sigio_pid = write_sigio_pid; write_sigio_pid = -1; + sigio_unlock(); + /* Going to call waitpid, avoid holding the lock. */ + os_kill_process(l_write_sigio_pid, 1); + goto out_free; + + out_clear: + write_sigio_pid = -1; + out_unlock: + sigio_unlock(); + out_free: + kfree(p); out_close2: - os_close_file(sigio_private[0]); - os_close_file(sigio_private[1]); + os_close_file(l_sigio_private[0]); + os_close_file(l_sigio_private[1]); out_close1: - os_close_file(write_sigio_fds[0]); - os_close_file(write_sigio_fds[1]); - sigio_unlock(); + os_close_file(l_write_sigio_fds[0]); + os_close_file(l_write_sigio_fds[1]); + return; } int read_sigio_fd(int fd) diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 7b0e0e81c16..da17b7541e0 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -99,31 +99,46 @@ static int handle_signal(struct pt_regs *regs, unsigned long signr, return err; } -static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) +static int kern_do_signal(struct pt_regs *regs) { struct k_sigaction ka_copy; siginfo_t info; + sigset_t *oldset; int sig, handled_sig = 0; + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + oldset = ¤t->saved_sigmask; + else + oldset = ¤t->blocked; + while((sig = get_signal_to_deliver(&info, &ka_copy, regs, NULL)) > 0){ handled_sig = 1; /* Whee! Actually deliver the signal. */ - if(!handle_signal(regs, sig, &ka_copy, &info, oldset)) + if(!handle_signal(regs, sig, &ka_copy, &info, oldset)){ + /* a signal was successfully delivered; the saved + * sigmask will have been stored in the signal frame, + * and will be restored by sigreturn, so we can simply + * clear the TIF_RESTORE_SIGMASK flag */ + if (test_thread_flag(TIF_RESTORE_SIGMASK)) + clear_thread_flag(TIF_RESTORE_SIGMASK); break; + } } /* Did we come from a system call? */ if(!handled_sig && (PT_REGS_SYSCALL_NR(regs) >= 0)){ /* Restart the system call - no handlers present */ - if(PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOHAND || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTSYS || - PT_REGS_SYSCALL_RET(regs) == -ERESTARTNOINTR){ + switch(PT_REGS_SYSCALL_RET(regs)){ + case -ERESTARTNOHAND: + case -ERESTARTSYS: + case -ERESTARTNOINTR: PT_REGS_ORIG_SYSCALL(regs) = PT_REGS_SYSCALL_NR(regs); PT_REGS_RESTART_SYSCALL(regs); - } - else if(PT_REGS_SYSCALL_RET(regs) == -ERESTART_RESTARTBLOCK){ + break; + case -ERESTART_RESTARTBLOCK: PT_REGS_SYSCALL_RET(regs) = __NR_restart_syscall; PT_REGS_RESTART_SYSCALL(regs); + break; } } @@ -137,12 +152,19 @@ static int kern_do_signal(struct pt_regs *regs, sigset_t *oldset) if(current->ptrace & PT_DTRACE) current->thread.singlestep_syscall = is_syscall(PT_REGS_IP(¤t->thread.regs)); + + /* if there's no signal to deliver, we just put the saved sigmask + * back */ + if (!handled_sig && test_thread_flag(TIF_RESTORE_SIGMASK)) { + clear_thread_flag(TIF_RESTORE_SIGMASK); + sigprocmask(SIG_SETMASK, ¤t->saved_sigmask, NULL); + } return(handled_sig); } int do_signal(void) { - return(kern_do_signal(¤t->thread.regs, ¤t->blocked)); + return(kern_do_signal(¤t->thread.regs)); } /* @@ -150,63 +172,20 @@ int do_signal(void) */ long sys_sigsuspend(int history0, int history1, old_sigset_t mask) { - sigset_t saveset; - mask &= _BLOCKABLE; spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; + current->saved_sigmask = current->blocked; siginitset(¤t->blocked, mask); recalc_sigpending(); spin_unlock_irq(¤t->sighand->siglock); - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if(kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } -} - -long sys_rt_sigsuspend(sigset_t __user *unewset, size_t sigsetsize) -{ - sigset_t saveset, newset; - - /* XXX: Don't preclude handling different sized sigset_t's. */ - if (sigsetsize != sizeof(sigset_t)) - return -EINVAL; - - if (copy_from_user(&newset, unewset, sizeof(newset))) - return -EFAULT; - sigdelsetmask(&newset, ~_BLOCKABLE); - - spin_lock_irq(¤t->sighand->siglock); - saveset = current->blocked; - current->blocked = newset; - recalc_sigpending(); - spin_unlock_irq(¤t->sighand->siglock); - - PT_REGS_SYSCALL_RET(¤t->thread.regs) = -EINTR; - while (1) { - current->state = TASK_INTERRUPTIBLE; - schedule(); - if (kern_do_signal(¤t->thread.regs, &saveset)) - return(-EINTR); - } + current->state = TASK_INTERRUPTIBLE; + schedule(); + set_thread_flag(TIF_RESTORE_SIGMASK); + return -ERESTARTNOHAND; } long sys_sigaltstack(const stack_t __user *uss, stack_t __user *uoss) { return(do_sigaltstack(uss, uoss, PT_REGS_SP(¤t->thread.regs))); } - -/* - * 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/Makefile b/arch/um/kernel/skas/Makefile index 7a9fc16d71d..57181a920d4 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -1,12 +1,12 @@ -# +# # Copyright (C) 2002 - 2004 Jeff Dike (jdike@addtoit.com) # Licensed under the GPL # -obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ +obj-y := clone.o exec_kern.o mem.o mmu.o process_kern.o \ syscall.o tlb.o uaccess.o -USER_OBJS := process.o clone.o +USER_OBJS := clone.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/include/mm_id.h b/arch/um/kernel/skas/include/mm_id.h deleted file mode 100644 index 48dd0989dda..00000000000 --- a/arch/um/kernel/skas/include/mm_id.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (C) 2005 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MM_ID_H -#define __MM_ID_H - -struct mm_id { - union { - int mm_fd; - int pid; - } u; - unsigned long stack; -}; - -#endif diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h deleted file mode 100644 index 44110c521e4..00000000000 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MMU_H -#define __SKAS_MMU_H - -#include "linux/config.h" -#include "mm_id.h" -#include "asm/ldt.h" - -struct mmu_context_skas { - struct mm_id id; - unsigned long last_page_table; -#ifdef CONFIG_3_LEVEL_PGTABLES - unsigned long last_pmd; -#endif - uml_ldt_t ldt; -}; - -extern void switch_mm_skas(struct mm_id * mm_idp); - -#endif - -/* - * 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/include/mode-skas.h b/arch/um/kernel/skas/include/mode-skas.h deleted file mode 100644 index bcd26a6a388..00000000000 --- a/arch/um/kernel/skas/include/mode-skas.h +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __MODE_SKAS_H__ -#define __MODE_SKAS_H__ - -#include <sysdep/ptrace.h> - -extern unsigned long exec_regs[]; -extern unsigned long exec_fp_regs[]; -extern unsigned long exec_fpx_regs[]; -extern int have_fpx_regs; - -extern void sig_handler_common_skas(int sig, void *sc_ptr); -extern void halt_skas(void); -extern void reboot_skas(void); -extern void kill_off_processes_skas(void); -extern int is_skas_winch(int pid, int fd, void *data); - -#endif - -/* - * 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/include/mode_kern-skas.h b/arch/um/kernel/skas/include/mode_kern-skas.h deleted file mode 100644 index c97a80dfe37..00000000000 --- a/arch/um/kernel/skas/include/mode_kern-skas.h +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_MODE_KERN_H__ -#define __SKAS_MODE_KERN_H__ - -#include "linux/sched.h" -#include "asm/page.h" -#include "asm/ptrace.h" - -extern void flush_thread_skas(void); -extern void switch_to_skas(void *prev, void *next); -extern void start_thread_skas(struct pt_regs *regs, unsigned long eip, - unsigned long esp); -extern int copy_thread_skas(int nr, unsigned long clone_flags, - unsigned long sp, unsigned long stack_top, - struct task_struct *p, struct pt_regs *regs); -extern void release_thread_skas(struct task_struct *task); -extern void initial_thread_cb_skas(void (*proc)(void *), void *arg); -extern void init_idle_skas(void); -extern void flush_tlb_kernel_range_skas(unsigned long start, - unsigned long end); -extern void flush_tlb_kernel_vm_skas(void); -extern void __flush_tlb_one_skas(unsigned long addr); -extern void flush_tlb_range_skas(struct vm_area_struct *vma, - unsigned long start, unsigned long end); -extern void flush_tlb_mm_skas(struct mm_struct *mm); -extern void force_flush_all_skas(void); -extern long execute_syscall_skas(void *r); -extern void before_mem_skas(unsigned long unused); -extern unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, - unsigned long *task_size_out); -extern int start_uml_skas(void); -extern int external_pid_skas(struct task_struct *task); -extern int thread_pid_skas(struct task_struct *task); - -#define kmem_end_skas (host_task_size - 1024 * 1024) - -#endif - -/* - * 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/include/proc_mm.h b/arch/um/kernel/skas/include/proc_mm.h deleted file mode 100644 index cce61a67905..00000000000 --- a/arch/um/kernel/skas/include/proc_mm.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_PROC_MM_H -#define __SKAS_PROC_MM_H - -#define MM_MMAP 54 -#define MM_MUNMAP 55 -#define MM_MPROTECT 56 -#define MM_COPY_SEGMENTS 57 - -struct mm_mmap { - unsigned long addr; - unsigned long len; - unsigned long prot; - unsigned long flags; - unsigned long fd; - unsigned long offset; -}; - -struct mm_munmap { - unsigned long addr; - unsigned long len; -}; - -struct mm_mprotect { - unsigned long addr; - unsigned long len; - unsigned int prot; -}; - -struct proc_mm_op { - int op; - union { - struct mm_mmap mmap; - struct mm_munmap munmap; - struct mm_mprotect mprotect; - int copy_segments; - } u; -}; - -#endif - -/* - * 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/include/skas.h b/arch/um/kernel/skas/include/skas.h deleted file mode 100644 index 01d489de398..00000000000 --- a/arch/um/kernel/skas/include/skas.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_H -#define __SKAS_H - -#include "mm_id.h" -#include "sysdep/ptrace.h" - -extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo, ptrace_ldt; -extern int skas_needs_stub; - -extern void switch_threads(void *me, void *next); -extern void thread_wait(void *sw, void *fb); -extern void new_thread(void *stack, void **switch_buf_ptr, void **fork_buf_ptr, - void (*handler)(int)); -extern int start_idle_thread(void *stack, void *switch_buf_ptr, - void **fork_buf_ptr); -extern int user_thread(unsigned long stack, int flags); -extern void userspace(union uml_pt_regs *regs); -extern void new_thread_proc(void *stack, void (*handler)(int sig)); -extern void new_thread_handler(int sig); -extern void handle_syscall(union uml_pt_regs *regs); -extern int map(struct mm_id * mm_idp, unsigned long virt, - unsigned long len, int r, int w, int x, int phys_fd, - unsigned long long offset, int done, void **data); -extern int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, - int done, void **data); -extern int protect(struct mm_id * mm_idp, unsigned long addr, - unsigned long len, int r, int w, int x, int done, - void **data); -extern void user_signal(int sig, union uml_pt_regs *regs, int pid); -extern int new_mm(int from, unsigned long stack); -extern int start_userspace(unsigned long stub_stack); -extern int copy_context_skas0(unsigned long stack, int pid); -extern void get_skas_faultinfo(int pid, struct faultinfo * fi); -extern long execute_syscall_skas(void *r); -extern unsigned long current_stub_stack(void); -extern long run_syscall_stub(struct mm_id * mm_idp, - int syscall, unsigned long *args, long expected, - void **addr, int done); -extern long syscall_stub_data(struct mm_id * mm_idp, - unsigned long *data, int data_count, - void **addr, void **stub_addr); - -#endif diff --git a/arch/um/kernel/skas/include/stub-data.h b/arch/um/kernel/skas/include/stub-data.h deleted file mode 100644 index f6ed92c3727..00000000000 --- a/arch/um/kernel/skas/include/stub-data.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2005 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __STUB_DATA_H -#define __STUB_DATA_H - -#include <sys/time.h> - -struct stub_data { - long offset; - int fd; - struct itimerval timer; - long err; -}; - -#endif diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h deleted file mode 100644 index 64516c556cd..00000000000 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __SKAS_UACCESS_H -#define __SKAS_UACCESS_H - -#include "asm/errno.h" - -/* No SKAS-specific checking. */ -#define access_ok_skas(type, addr, size) 0 - -extern int copy_from_user_skas(void *to, const void __user *from, int n); -extern int copy_to_user_skas(void __user *to, const void *from, int n); -extern int strncpy_from_user_skas(char *dst, const char __user *src, int count); -extern int __clear_user_skas(void __user *mem, int len); -extern int clear_user_skas(void __user *mem, int len); -extern int strnlen_user_skas(const void __user *str, int len); - -#endif - -/* - * 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/mem_user.c b/arch/um/kernel/skas/mem_user.c deleted file mode 100644 index 1d89640bd50..00000000000 --- a/arch/um/kernel/skas/mem_user.c +++ /dev/null @@ -1,281 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <signal.h> -#include <errno.h> -#include <string.h> -#include <sys/mman.h> -#include <sys/wait.h> -#include <asm/page.h> -#include <asm/unistd.h> -#include "mem_user.h" -#include "mem.h" -#include "skas.h" -#include "user.h" -#include "os.h" -#include "proc_mm.h" -#include "ptrace_user.h" -#include "user_util.h" -#include "kern_util.h" -#include "task.h" -#include "registers.h" -#include "uml-config.h" -#include "sysdep/ptrace.h" -#include "sysdep/stub.h" - -extern unsigned long batch_syscall_stub, __syscall_stub_start; - -extern void wait_stub_done(int pid, int sig, char * fname); - -static inline unsigned long *check_init_stack(struct mm_id * mm_idp, - unsigned long *stack) -{ - if(stack == NULL){ - stack = (unsigned long *) mm_idp->stack + 2; - *stack = 0; - } - return stack; -} - -extern int proc_mm; - -int single_count = 0; -int multi_count = 0; -int multi_op_count = 0; - -static long do_syscall_stub(struct mm_id *mm_idp, void **addr) -{ - unsigned long regs[MAX_REG_NR]; - unsigned long *data; - unsigned long *syscall; - long ret, offset; - int n, pid = mm_idp->u.pid; - - if(proc_mm) -#warning Need to look up userspace_pid by cpu - pid = userspace_pid[0]; - - multi_count++; - - get_safe_registers(regs); - regs[REGS_IP_INDEX] = UML_CONFIG_STUB_CODE + - ((unsigned long) &batch_syscall_stub - - (unsigned long) &__syscall_stub_start); - n = ptrace_setregs(pid, regs); - if(n < 0) - panic("do_syscall_stub : PTRACE_SETREGS failed, errno = %d\n", - n); - - wait_stub_done(pid, 0, "do_syscall_stub"); - - /* When the stub stops, we find the following values on the - * beginning of the stack: - * (long )return_value - * (long )offset to failed sycall-data (0, if no error) - */ - ret = *((unsigned long *) mm_idp->stack); - offset = *((unsigned long *) mm_idp->stack + 1); - if (offset) { - data = (unsigned long *)(mm_idp->stack + - offset - UML_CONFIG_STUB_DATA); - syscall = (unsigned long *)((unsigned long)data + data[0]); - printk("do_syscall_stub: syscall %ld failed, return value = " - "0x%lx, expected return value = 0x%lx\n", - syscall[0], ret, syscall[7]); - printk(" syscall parameters: " - "0x%lx 0x%lx 0x%lx 0x%lx 0x%lx 0x%lx\n", - syscall[1], syscall[2], syscall[3], - syscall[4], syscall[5], syscall[6]); - for(n = 1; n < data[0]/sizeof(long); n++) { - if(n == 1) - printk(" additional syscall data:"); - if(n % 4 == 1) - printk("\n "); - printk(" 0x%lx", data[n]); - } - if(n > 1) - printk("\n"); - } - else ret = 0; - - *addr = check_init_stack(mm_idp, NULL); - - return ret; -} - -long run_syscall_stub(struct mm_id * mm_idp, int syscall, - unsigned long *args, long expected, void **addr, - int done) -{ - unsigned long *stack = check_init_stack(mm_idp, *addr); - - if(done && *addr == NULL) - single_count++; - - *stack += sizeof(long); - stack += *stack / sizeof(long); - - *stack++ = syscall; - *stack++ = args[0]; - *stack++ = args[1]; - *stack++ = args[2]; - *stack++ = args[3]; - *stack++ = args[4]; - *stack++ = args[5]; - *stack++ = expected; - *stack = 0; - multi_op_count++; - - if(!done && ((((unsigned long) stack) & ~PAGE_MASK) < - PAGE_SIZE - 10 * sizeof(long))){ - *addr = stack; - return 0; - } - - return do_syscall_stub(mm_idp, addr); -} - -long syscall_stub_data(struct mm_id * mm_idp, - unsigned long *data, int data_count, - void **addr, void **stub_addr) -{ - unsigned long *stack; - int ret = 0; - - /* If *addr still is uninitialized, it *must* contain NULL. - * Thus in this case do_syscall_stub correctly won't be called. - */ - if((((unsigned long) *addr) & ~PAGE_MASK) >= - PAGE_SIZE - (10 + data_count) * sizeof(long)) { - ret = do_syscall_stub(mm_idp, addr); - /* in case of error, don't overwrite data on stack */ - if(ret) - return ret; - } - - stack = check_init_stack(mm_idp, *addr); - *addr = stack; - - *stack = data_count * sizeof(long); - - memcpy(stack + 1, data, data_count * sizeof(long)); - - *stub_addr = (void *)(((unsigned long)(stack + 1) & ~PAGE_MASK) + - UML_CONFIG_STUB_DATA); - - return 0; -} - -int map(struct mm_id * mm_idp, unsigned long virt, unsigned long len, - int r, int w, int x, int phys_fd, unsigned long long offset, - int done, void **data) -{ - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - struct proc_mm_op map; - int fd = mm_idp->u.mm_fd; - - map = ((struct proc_mm_op) { .op = MM_MMAP, - .u = - { .mmap = - { .addr = virt, - .len = len, - .prot = prot, - .flags = MAP_SHARED | - MAP_FIXED, - .fd = phys_fd, - .offset= offset - } } } ); - ret = os_write_file(fd, &map, sizeof(map)); - if(ret != sizeof(map)) - printk("map : /proc/mm map failed, err = %d\n", -ret); - else ret = 0; - } - else { - unsigned long args[] = { virt, len, prot, - MAP_SHARED | MAP_FIXED, phys_fd, - MMAP_OFFSET(offset) }; - - ret = run_syscall_stub(mm_idp, STUB_MMAP_NR, args, virt, - data, done); - } - - return ret; -} - -int unmap(struct mm_id * mm_idp, void *addr, unsigned long len, int done, - void **data) -{ - int ret; - - if(proc_mm){ - struct proc_mm_op unmap; - int fd = mm_idp->u.mm_fd; - - unmap = ((struct proc_mm_op) { .op = MM_MUNMAP, - .u = - { .munmap = - { .addr = - (unsigned long) addr, - .len = len } } } ); - ret = os_write_file(fd, &unmap, sizeof(unmap)); - if(ret != sizeof(unmap)) - printk("unmap - proc_mm write returned %d\n", ret); - else ret = 0; - } - else { - unsigned long args[] = { (unsigned long) addr, len, 0, 0, 0, - 0 }; - - ret = run_syscall_stub(mm_idp, __NR_munmap, args, 0, - data, done); - if(ret < 0) - printk("munmap stub failed, errno = %d\n", ret); - } - - return ret; -} - -int protect(struct mm_id * mm_idp, unsigned long addr, unsigned long len, - int r, int w, int x, int done, void **data) -{ - struct proc_mm_op protect; - int prot, ret; - - prot = (r ? PROT_READ : 0) | (w ? PROT_WRITE : 0) | - (x ? PROT_EXEC : 0); - - if(proc_mm){ - int fd = mm_idp->u.mm_fd; - protect = ((struct proc_mm_op) { .op = MM_MPROTECT, - .u = - { .mprotect = - { .addr = - (unsigned long) addr, - .len = len, - .prot = prot } } } ); - - ret = os_write_file(fd, &protect, sizeof(protect)); - if(ret != sizeof(protect)) - printk("protect failed, err = %d", -ret); - else ret = 0; - } - else { - unsigned long args[] = { addr, len, prot, 0, 0, 0 }; - - ret = run_syscall_stub(mm_idp, __NR_mprotect, args, 0, - data, done); - } - - return ret; -} - -void before_mem_skas(unsigned long unused) -{ -} diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 677871f1b37..c5c9885a829 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -78,7 +78,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) struct mmu_context_skas *from_mm = NULL; struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from_fd, ret = -ENOMEM; + int ret = -ENOMEM; if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); @@ -108,11 +108,7 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) from_mm = ¤t->mm->context.skas; if(proc_mm){ - if(from_mm) - from_fd = from_mm->id.u.mm_fd; - else from_fd = -1; - - ret = new_mm(from_fd, stack); + ret = new_mm(stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 3b3955d8440..eea1c9c4bb0 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -18,7 +18,6 @@ #include <asm/types.h> #include "user.h" #include "ptrace_user.h" -#include "time_user.h" #include "sysdep/ptrace.h" #include "user_util.h" #include "kern_util.h" diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index dc41c6dc2f3..3f70a2e12f0 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,14 +13,12 @@ #include "asm/uaccess.h" #include "asm/atomic.h" #include "kern_util.h" -#include "time_user.h" #include "skas.h" #include "os.h" #include "user_util.h" #include "tlb.h" #include "kern.h" #include "mode.h" -#include "proc_mm.h" #include "registers.h" void switch_to_skas(void *prev, void *next) @@ -34,7 +32,7 @@ void switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - switch_threads(&from->thread.mode.skas.switch_buf, + switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); if(current->pid == 0) @@ -50,8 +48,8 @@ void new_thread_handler(int sig) fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); if(current->thread.prev_sched != NULL) @@ -82,8 +80,8 @@ void release_thread_skas(struct task_struct *task) void fork_handler(int sig) { - change_sig(SIGUSR1, 1); - thread_wait(¤t->thread.mode.skas.switch_buf, + os_usr1_signal(1); + thread_wait(¤t->thread.mode.skas.switch_buf, current->thread.mode.skas.fork_buf); force_flush_all(); @@ -93,13 +91,13 @@ void fork_handler(int sig) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; - /* Handle any immediate reschedules or signals */ +/* Handle any immediate reschedules or signals */ interrupt_end(); userspace(¤t->thread.regs.regs); } int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, - unsigned long stack_top, struct task_struct * p, + unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { void (*handler)(int); @@ -123,27 +121,14 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, return(0); } -extern void map_stub_pages(int fd, unsigned long code, - unsigned long data, unsigned long stack); -int new_mm(int from, unsigned long stack) +int new_mm(unsigned long stack) { - struct proc_mm_op copy; - int n, fd; + int fd; fd = os_open_file("/proc/mm", of_cloexec(of_write(OPENFLAGS())), 0); if(fd < 0) return(fd); - if(from != -1){ - copy = ((struct proc_mm_op) { .op = MM_COPY_SEGMENTS, - .u = - { .copy_segments = from } } ); - n = os_write_file(fd, ©, sizeof(copy)); - if(n != sizeof(copy)) - printk("new_mm : /proc/mm copy_segments failed, " - "err = %d\n", -n); - } - if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index a5a47528dec..5992c325716 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -13,7 +13,7 @@ #include "asm/pgtable.h" #include "asm/uaccess.h" #include "kern_util.h" -#include "user_util.h" +#include "os.h" extern void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pte_t *pte_out); diff --git a/arch/um/kernel/syscall.c b/arch/um/kernel/syscall.c index 1429c131879..1731d90e685 100644 --- a/arch/um/kernel/syscall.c +++ b/arch/um/kernel/syscall.c @@ -25,12 +25,12 @@ int record_syscall_start(int syscall) syscall_record[index].syscall = syscall; syscall_record[index].pid = current_pid(); syscall_record[index].result = 0xdeadbeef; - syscall_record[index].start = os_usecs(); + syscall_record[index].start = os_nsecs(); return(index); } void record_syscall_end(int index, long result) { syscall_record[index].result = result; - syscall_record[index].end = os_usecs(); + syscall_record[index].end = os_nsecs(); } diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 020ca79b8d3..3c7626cdba4 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -13,12 +13,12 @@ #include "linux/interrupt.h" #include "linux/init.h" #include "linux/delay.h" +#include "linux/hrtimer.h" #include "asm/irq.h" #include "asm/param.h" #include "asm/current.h" #include "kern_util.h" #include "user_util.h" -#include "time_user.h" #include "mode.h" #include "os.h" @@ -39,7 +39,7 @@ unsigned long long sched_clock(void) int timer_irq_inited = 0; static int first_tick; -static unsigned long long prev_usecs; +static unsigned long long prev_nsecs; #ifdef CONFIG_UML_REAL_TIME_CLOCK static long long delta; /* Deviation per interval */ #endif @@ -58,23 +58,23 @@ void timer_irq(union uml_pt_regs *regs) if(first_tick){ #ifdef CONFIG_UML_REAL_TIME_CLOCK /* We've had 1 tick */ - unsigned long long usecs = os_usecs(); + unsigned long long nsecs = os_nsecs(); - delta += usecs - prev_usecs; - prev_usecs = usecs; + delta += nsecs - prev_nsecs; + prev_nsecs = nsecs; /* Protect against the host clock being set backwards */ if(delta < 0) delta = 0; - ticks += (delta * HZ) / MILLION; - delta -= (ticks * MILLION) / HZ; + ticks += (delta * HZ) / BILLION; + delta -= (ticks * BILLION) / HZ; #else ticks = 1; #endif } else { - prev_usecs = os_usecs(); + prev_nsecs = os_nsecs(); first_tick = 1; } @@ -84,49 +84,102 @@ void timer_irq(union uml_pt_regs *regs) } } -void boot_timer_handler(int sig) +void do_boot_timer_handler(struct sigcontext * sc) { struct pt_regs regs; - CHOOSE_MODE((void) - (UPT_SC(®s.regs) = (struct sigcontext *) (&sig + 1)), + CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), (void) (regs.regs.skas.is_user = 0)); do_timer(®s); } +static DEFINE_SPINLOCK(timer_spinlock); + +static unsigned long long local_offset = 0; + +static inline unsigned long long get_time(void) +{ + unsigned long long nsecs; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + nsecs = os_nsecs(); + nsecs += local_offset; + spin_unlock_irqrestore(&timer_spinlock, flags); + + return nsecs; +} + irqreturn_t um_timer(int irq, void *dev, struct pt_regs *regs) { + unsigned long long nsecs; unsigned long flags; do_timer(regs); + write_seqlock_irqsave(&xtime_lock, flags); - timer(); + nsecs = get_time() + local_offset; + xtime.tv_sec = nsecs / NSEC_PER_SEC; + xtime.tv_nsec = nsecs - xtime.tv_sec * NSEC_PER_SEC; write_sequnlock_irqrestore(&xtime_lock, flags); + return(IRQ_HANDLED); } long um_time(int __user *tloc) { - struct timeval now; + long ret = get_time() / NSEC_PER_SEC; - do_gettimeofday(&now); - if (tloc) { - if (put_user(now.tv_sec, tloc)) - now.tv_sec = -EFAULT; - } - return now.tv_sec; + if((tloc != NULL) && put_user(ret, tloc)) + return -EFAULT; + + return ret; +} + +void do_gettimeofday(struct timeval *tv) +{ + unsigned long long nsecs = get_time(); + + tv->tv_sec = nsecs / NSEC_PER_SEC; + /* Careful about calculations here - this was originally done as + * (nsecs - tv->tv_sec * NSEC_PER_SEC) / NSEC_PER_USEC + * which gave bogus (> 1000000) values. Dunno why, suspect gcc + * (4.0.0) miscompiled it, or there's a subtle 64/32-bit conversion + * problem that I missed. + */ + nsecs -= tv->tv_sec * NSEC_PER_SEC; + tv->tv_usec = (unsigned long) nsecs / NSEC_PER_USEC; +} + +static inline void set_time(unsigned long long nsecs) +{ + unsigned long long now; + unsigned long flags; + + spin_lock_irqsave(&timer_spinlock, flags); + now = os_nsecs(); + local_offset = nsecs - now; + spin_unlock_irqrestore(&timer_spinlock, flags); + + clock_was_set(); } long um_stime(int __user *tptr) { int value; - struct timespec new; if (get_user(value, tptr)) return -EFAULT; - new.tv_sec = value; - new.tv_nsec = 0; - do_settimeofday(&new); + + set_time((unsigned long long) value * NSEC_PER_SEC); + + return 0; +} + +int do_settimeofday(struct timespec *tv) +{ + set_time((unsigned long long) tv->tv_sec * NSEC_PER_SEC + tv->tv_nsec); + return 0; } @@ -134,29 +187,15 @@ void timer_handler(int sig, union uml_pt_regs *regs) { local_irq_disable(); irq_enter(); - update_process_times(CHOOSE_MODE(user_context(UPT_SP(regs)), - (regs)->skas.is_user)); + update_process_times(CHOOSE_MODE( + (UPT_SC(regs) && user_context(UPT_SP(regs))), + (regs)->skas.is_user)); irq_exit(); local_irq_enable(); if(current_thread->cpu == 0) timer_irq(regs); } -static DEFINE_SPINLOCK(timer_spinlock); - -unsigned long time_lock(void) -{ - unsigned long flags; - - spin_lock_irqsave(&timer_spinlock, flags); - return(flags); -} - -void time_unlock(unsigned long flags) -{ - spin_unlock_irqrestore(&timer_spinlock, flags); -} - int __init timer_init(void) { int err; @@ -171,14 +210,3 @@ int __init timer_init(void) } __initcall(timer_init); - -/* - * 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/tt/exec_kern.c b/arch/um/kernel/tt/exec_kern.c index 8f40e483873..5c1e4cc1c04 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -13,7 +13,6 @@ #include "user_util.h" #include "kern_util.h" #include "irq_user.h" -#include "time_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" diff --git a/arch/um/kernel/tt/gdb.c b/arch/um/kernel/tt/gdb.c index 37e22d71a0d..786e4edd86c 100644 --- a/arch/um/kernel/tt/gdb.c +++ b/arch/um/kernel/tt/gdb.c @@ -20,6 +20,7 @@ #include "user_util.h" #include "tt.h" #include "sysdep/thread.h" +#include "os.h" extern int debugger_pid; extern int debugger_fd; diff --git a/arch/um/kernel/tt/include/debug.h b/arch/um/kernel/tt/include/debug.h deleted file mode 100644 index 738435461e1..00000000000 --- a/arch/um/kernel/tt/include/debug.h +++ /dev/null @@ -1,18 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) and - * Lars Brinkhoff. - * Licensed under the GPL - */ - -#ifndef __UML_TT_DEBUG_H -#define __UML_TT_DEBUG_H - -extern int debugger_proxy(int status, pid_t pid); -extern void child_proxy(pid_t pid, int status); -extern void init_proxy (pid_t pid, int waiting, int status); -extern int start_debugger(char *prog, int startup, int stop, int *debugger_fd); -extern void fake_child_exit(void); -extern int gdb_config(char *str); -extern int gdb_remove(int unused); - -#endif diff --git a/arch/um/kernel/tt/include/mmu-tt.h b/arch/um/kernel/tt/include/mmu-tt.h deleted file mode 100644 index 0440510ab3f..00000000000 --- a/arch/um/kernel/tt/include/mmu-tt.h +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_MMU_H -#define __TT_MMU_H - -struct mmu_context_tt { -}; - -#endif - -/* - * 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/tt/include/tt.h b/arch/um/kernel/tt/include/tt.h deleted file mode 100644 index c667b67af40..00000000000 --- a/arch/um/kernel/tt/include/tt.h +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#ifndef __TT_H__ -#define __TT_H__ - -#include "sysdep/ptrace.h" - -extern int gdb_pid; -extern int debug; -extern int debug_stop; -extern int debug_trace; - -extern int honeypot; - -extern int fork_tramp(void *sig_stack); -extern int do_proc_op(void *t, int proc_id); -extern int tracer(int (*init_proc)(void *), void *sp); -extern void attach_process(int pid); -extern void tracer_panic(char *format, ...); -extern void set_init_pid(int pid); -extern int set_user_mode(void *task); -extern void set_tracing(void *t, int tracing); -extern int is_tracing(void *task); -extern void syscall_handler(int sig, union uml_pt_regs *regs); -extern void exit_kernel(int pid, void *task); -extern void do_syscall(void *task, int pid, int local_using_sysemu); -extern void do_sigtrap(void *task); -extern int is_valid_pid(int pid); -extern void remap_data(void *segment_start, void *segment_end, int w); -extern long execute_syscall_tt(void *r); - -#endif - -/* - * 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/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h deleted file mode 100644 index b9bfe9c481c..00000000000 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * Copyright (C) 2000 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#ifndef __TT_UACCESS_H -#define __TT_UACCESS_H - -#include "linux/string.h" -#include "linux/sched.h" -#include "asm/processor.h" -#include "asm/errno.h" -#include "asm/current.h" -#include "asm/a.out.h" -#include "uml_uaccess.h" - -#define ABOVE_KMEM (16 * 1024 * 1024) - -extern unsigned long end_vm; -extern unsigned long uml_physmem; - -#define is_stack(addr, size) \ - (((unsigned long) (addr) < STACK_TOP) && \ - ((unsigned long) (addr) >= STACK_TOP - ABOVE_KMEM) && \ - (((unsigned long) (addr) + (size)) <= STACK_TOP)) - -#define access_ok_tt(type, addr, size) \ - (is_stack(addr, size)) - -extern unsigned long get_fault_addr(void); - -extern int __do_copy_from_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher); -extern int __do_strncpy_from_user(char *dst, const char *src, size_t n, - void **fault_addr, void **fault_catcher); -extern int __do_clear_user(void *mem, size_t len, void **fault_addr, - void **fault_catcher); -extern int __do_strnlen_user(const char *str, unsigned long n, - void **fault_addr, void **fault_catcher); - -extern int copy_from_user_tt(void *to, const void __user *from, int n); -extern int copy_to_user_tt(void __user *to, const void *from, int n); -extern int strncpy_from_user_tt(char *dst, const char __user *src, int count); -extern int __clear_user_tt(void __user *mem, int len); -extern int clear_user_tt(void __user *mem, int len); -extern int strnlen_user_tt(const void __user *str, int len); - -#endif - -/* - * 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/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index 62535303aa2..295c1ac817b 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -18,7 +18,6 @@ #include "os.h" #include "kern.h" #include "sigcontext.h" -#include "time_user.h" #include "mem_user.h" #include "tlb.h" #include "mode.h" diff --git a/arch/um/kernel/tt/ptproxy/ptrace.c b/arch/um/kernel/tt/ptproxy/ptrace.c index 528a5fc8d88..03774427d46 100644 --- a/arch/um/kernel/tt/ptproxy/ptrace.c +++ b/arch/um/kernel/tt/ptproxy/ptrace.c @@ -20,6 +20,7 @@ Jeff Dike (jdike@karaya.com) : Modified for integration into uml #include "kern_util.h" #include "ptrace_user.h" #include "tt.h" +#include "os.h" long proxy_ptrace(struct debugger *debugger, int arg1, pid_t arg2, long arg3, long arg4, pid_t child, int *ret) diff --git a/arch/um/kernel/tt/ptproxy/sysdep.c b/arch/um/kernel/tt/ptproxy/sysdep.c index a5f0e01e214..99f178319d0 100644 --- a/arch/um/kernel/tt/ptproxy/sysdep.c +++ b/arch/um/kernel/tt/ptproxy/sysdep.c @@ -15,6 +15,7 @@ terms and conditions. #include "ptrace_user.h" #include "user_util.h" #include "user.h" +#include "os.h" int get_syscall(pid_t pid, long *arg1, long *arg2, long *arg3, long *arg4, long *arg5) diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index a414c529fbc..b5d9d64d91e 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -18,7 +18,7 @@ void sig_handler_common_tt(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct tt_regs save_regs, *r; - int save_errno = errno, is_user; + int save_errno = errno, is_user = 0; void (*handler)(int, union uml_pt_regs *); /* This is done because to allow SIGSEGV to be delivered inside a SEGV @@ -35,7 +35,8 @@ void sig_handler_common_tt(int sig, void *sc_ptr) GET_FAULTINFO_FROM_SC(r->faultinfo, sc); } save_regs = *r; - is_user = user_context(SC_SP(sc)); + if (sc) + is_user = user_context(SC_SP(sc)); r->sc = sc; if(sig != SIGUSR2) r->syscall = -1; diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c deleted file mode 100644 index 4c231161f25..00000000000 --- a/arch/um/kernel/user_util.c +++ /dev/null @@ -1,174 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <limits.h> -#include <setjmp.h> -#include <sys/mman.h> -#include <sys/stat.h> -#include <sys/utsname.h> -#include <sys/param.h> -#include <sys/time.h> -#include "asm/types.h" -#include <ctype.h> -#include <signal.h> -#include <wait.h> -#include <errno.h> -#include <stdarg.h> -#include <sched.h> -#include <termios.h> -#include <string.h> -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "mem_user.h" -#include "init.h" -#include "ptrace_user.h" -#include "uml-config.h" - -void stop(void) -{ - while(1) sleep(1000000); -} - -void stack_protections(unsigned long address) -{ - int prot = PROT_READ | PROT_WRITE | PROT_EXEC; - - if(mprotect((void *) address, page_size(), prot) < 0) - panic("protecting stack failed, errno = %d", errno); -} - -void task_protections(unsigned long address) -{ - unsigned long guard = address + page_size(); - unsigned long stack = guard + page_size(); - int prot = 0, pages; - -#ifdef notdef - if(mprotect((void *) stack, page_size(), prot) < 0) - panic("protecting guard page failed, errno = %d", errno); -#endif - pages = (1 << UML_CONFIG_KERNEL_STACK_ORDER) - 2; - prot = PROT_READ | PROT_WRITE | PROT_EXEC; - if(mprotect((void *) stack, pages * page_size(), prot) < 0) - panic("protecting stack failed, errno = %d", errno); -} - -int wait_for_stop(int pid, int sig, int cont_type, void *relay) -{ - sigset_t *relay_signals = relay; - int status, ret; - - while(1){ - CATCH_EINTR(ret = waitpid(pid, &status, WUNTRACED)); - if((ret < 0) || - !WIFSTOPPED(status) || (WSTOPSIG(status) != sig)){ - if(ret < 0){ - printk("wait failed, errno = %d\n", - errno); - } - else if(WIFEXITED(status)) - printk("process %d exited with status %d\n", - pid, WEXITSTATUS(status)); - else if(WIFSIGNALED(status)) - printk("process %d exited with signal %d\n", - pid, WTERMSIG(status)); - else if((WSTOPSIG(status) == SIGVTALRM) || - (WSTOPSIG(status) == SIGALRM) || - (WSTOPSIG(status) == SIGIO) || - (WSTOPSIG(status) == SIGPROF) || - (WSTOPSIG(status) == SIGCHLD) || - (WSTOPSIG(status) == SIGWINCH) || - (WSTOPSIG(status) == SIGINT)){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else if((relay_signals != NULL) && - sigismember(relay_signals, WSTOPSIG(status))){ - ptrace(cont_type, pid, 0, WSTOPSIG(status)); - continue; - } - else printk("process %d stopped with signal %d\n", - pid, WSTOPSIG(status)); - panic("wait_for_stop failed to wait for %d to stop " - "with %d\n", pid, sig); - } - return(status); - } -} - -int raw(int fd) -{ - struct termios tt; - int err; - - CATCH_EINTR(err = tcgetattr(fd, &tt)); - if(err < 0) - return -errno; - - cfmakeraw(&tt); - - CATCH_EINTR(err = tcsetattr(fd, TCSADRAIN, &tt)); - if(err < 0) - return -errno; - - /* XXX tcsetattr could have applied only some changes - * (and cfmakeraw() is a set of changes) */ - return(0); -} - -void setup_machinename(char *machine_out) -{ - struct utsname host; - - uname(&host); -#if defined(UML_CONFIG_UML_X86) && !defined(UML_CONFIG_64BIT) - if (!strcmp(host.machine, "x86_64")) { - strcpy(machine_out, "i686"); - return; - } -#endif - strcpy(machine_out, host.machine); -} - -char host_info[(_UTSNAME_LENGTH + 1) * 4 + _UTSNAME_NODENAME_LENGTH + 1]; - -void setup_hostinfo(void) -{ - struct utsname host; - - uname(&host); - sprintf(host_info, "%s %s %s %s %s", host.sysname, host.nodename, - host.release, host.version, host.machine); -} - -int setjmp_wrapper(void (*proc)(void *, void *), ...) -{ - va_list args; - sigjmp_buf buf; - int n; - - n = sigsetjmp(buf, 1); - if(n == 0){ - va_start(args, proc); - (*proc)(&buf, &args); - } - va_end(args); - return(n); -} - -/* - * 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: - */ |