diff options
Diffstat (limited to 'arch/um/kernel')
36 files changed, 199 insertions, 824 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 1a0001b3850..3de9d21e36b 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -7,10 +7,10 @@ extra-y := vmlinux.lds clean-files := obj-y = config.o exec_kern.o exitcode.o \ - helper.o init_task.o irq.o irq_user.o ksyms.o main.o mem.o physmem.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 signal_user.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess_user.o um_arch.o \ + time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ umid.o user_util.o obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o @@ -24,8 +24,7 @@ obj-$(CONFIG_MODE_SKAS) += skas/ user-objs-$(CONFIG_TTY_LOG) += tty_log.o -USER_OBJS := $(user-objs-y) config.o helper.o main.o time.o tty_log.o umid.o \ - user_util.o +USER_OBJS := $(user-objs-y) config.o time.o tty_log.o umid.o user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/helper.c b/arch/um/kernel/helper.c deleted file mode 100644 index 33fb0bd3b11..00000000000 --- a/arch/um/kernel/helper.c +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <stdlib.h> -#include <unistd.h> -#include <errno.h> -#include <sched.h> -#include <sys/signal.h> -#include <sys/wait.h> -#include "user.h" -#include "kern_util.h" -#include "user_util.h" -#include "helper.h" -#include "os.h" - -struct helper_data { - void (*pre_exec)(void*); - void *pre_data; - char **argv; - int fd; -}; - -/* Debugging aid, changed only from gdb */ -int helper_pause = 0; - -static void helper_hup(int sig) -{ -} - -static int helper_child(void *arg) -{ - struct helper_data *data = arg; - char **argv = data->argv; - int errval; - - if(helper_pause){ - signal(SIGHUP, helper_hup); - pause(); - } - if(data->pre_exec != NULL) - (*data->pre_exec)(data->pre_data); - execvp(argv[0], argv); - errval = errno; - printk("execvp of '%s' failed - errno = %d\n", argv[0], errno); - os_write_file(data->fd, &errval, sizeof(errval)); - os_kill_process(os_getpid(), 0); - return(0); -} - -/* Returns either the pid of the child process we run or -E* on failure. - * XXX The alloc_stack here breaks if this is called in the tracing thread */ -int run_helper(void (*pre_exec)(void *), void *pre_data, char **argv, - unsigned long *stack_out) -{ - struct helper_data data; - unsigned long stack, sp; - int pid, fds[2], ret, n; - - if((stack_out != NULL) && (*stack_out != 0)) - stack = *stack_out; - else stack = alloc_stack(0, um_in_interrupt()); - if(stack == 0) - return(-ENOMEM); - - ret = os_pipe(fds, 1, 0); - if(ret < 0){ - printk("run_helper : pipe failed, ret = %d\n", -ret); - goto out_free; - } - - ret = os_set_exec_close(fds[1], 1); - if(ret < 0){ - printk("run_helper : setting FD_CLOEXEC failed, ret = %d\n", - -ret); - goto out_close; - } - - sp = stack + page_size() - sizeof(void *); - data.pre_exec = pre_exec; - data.pre_data = pre_data; - data.argv = argv; - data.fd = fds[1]; - pid = clone(helper_child, (void *) sp, CLONE_VM | SIGCHLD, &data); - if(pid < 0){ - ret = -errno; - printk("run_helper : clone failed, errno = %d\n", errno); - goto out_close; - } - - os_close_file(fds[1]); - fds[1] = -1; - - /*Read the errno value from the child.*/ - n = os_read_file(fds[0], &ret, sizeof(ret)); - if(n < 0){ - printk("run_helper : read on pipe failed, ret = %d\n", -n); - ret = n; - os_kill_process(pid, 1); - } - else if(n != 0){ - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - ret = -errno; - } else { - ret = pid; - } - -out_close: - if (fds[1] != -1) - os_close_file(fds[1]); - os_close_file(fds[0]); -out_free: - if(stack_out == NULL) - free_stack(stack, 0); - else *stack_out = stack; - return(ret); -} - -int run_helper_thread(int (*proc)(void *), void *arg, unsigned int flags, - unsigned long *stack_out, int stack_order) -{ - unsigned long stack, sp; - int pid, status, err; - - stack = alloc_stack(stack_order, um_in_interrupt()); - if(stack == 0) return(-ENOMEM); - - sp = stack + (page_size() << stack_order) - sizeof(void *); - pid = clone(proc, (void *) sp, flags | SIGCHLD, arg); - if(pid < 0){ - err = -errno; - printk("run_helper_thread : clone failed, errno = %d\n", - errno); - return err; - } - if(stack_out == NULL){ - CATCH_EINTR(pid = waitpid(pid, &status, 0)); - if(pid < 0){ - err = -errno; - printk("run_helper_thread - wait failed, errno = %d\n", - errno); - pid = err; - } - if(!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) - printk("run_helper_thread - thread returned status " - "0x%x\n", status); - free_stack(stack, stack_order); - } - else *stack_out = stack; - return(pid); -} - -int helper_wait(int pid) -{ - int ret; - - CATCH_EINTR(ret = waitpid(pid, NULL, WNOHANG)); - if(ret < 0){ - ret = -errno; - printk("helper_wait : waitpid failed, errno = %d\n", errno); - } - return(ret); -} diff --git a/arch/um/kernel/irq.c b/arch/um/kernel/irq.c index dcd81497199..bbf94bf2921 100644 --- a/arch/um/kernel/irq.c +++ b/arch/um/kernel/irq.c @@ -9,7 +9,6 @@ #include "linux/kernel.h" #include "linux/module.h" #include "linux/smp.h" -#include "linux/irq.h" #include "linux/kernel_stat.h" #include "linux/interrupt.h" #include "linux/random.h" diff --git a/arch/um/kernel/ksyms.c b/arch/um/kernel/ksyms.c index a97a72e516a..7713e7a6f47 100644 --- a/arch/um/kernel/ksyms.c +++ b/arch/um/kernel/ksyms.c @@ -20,7 +20,6 @@ #include "user_util.h" #include "mem_user.h" #include "os.h" -#include "helper.h" EXPORT_SYMBOL(stop); EXPORT_SYMBOL(uml_physmem); diff --git a/arch/um/kernel/main.c b/arch/um/kernel/main.c deleted file mode 100644 index d31027f0fe3..00000000000 --- a/arch/um/kernel/main.c +++ /dev/null @@ -1,270 +0,0 @@ -/* - * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <unistd.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <signal.h> -#include <errno.h> -#include <sys/resource.h> -#include <sys/mman.h> -#include <sys/user.h> -#include <asm/page.h> -#include "user_util.h" -#include "kern_util.h" -#include "mem_user.h" -#include "signal_user.h" -#include "time_user.h" -#include "irq_user.h" -#include "user.h" -#include "init.h" -#include "mode.h" -#include "choose-mode.h" -#include "uml-config.h" -#include "os.h" - -/* Set in set_stklim, which is called from main and __wrap_malloc. - * __wrap_malloc only calls it if main hasn't started. - */ -unsigned long stacksizelim; - -/* Set in main */ -char *linux_prog; - -#define PGD_BOUND (4 * 1024 * 1024) -#define STACKSIZE (8 * 1024 * 1024) -#define THREAD_NAME_LEN (256) - -static void set_stklim(void) -{ - struct rlimit lim; - - if(getrlimit(RLIMIT_STACK, &lim) < 0){ - perror("getrlimit"); - exit(1); - } - if((lim.rlim_cur == RLIM_INFINITY) || (lim.rlim_cur > STACKSIZE)){ - lim.rlim_cur = STACKSIZE; - if(setrlimit(RLIMIT_STACK, &lim) < 0){ - perror("setrlimit"); - exit(1); - } - } - stacksizelim = (lim.rlim_cur + PGD_BOUND - 1) & ~(PGD_BOUND - 1); -} - -static __init void do_uml_initcalls(void) -{ - initcall_t *call; - - call = &__uml_initcall_start; - while (call < &__uml_initcall_end){; - (*call)(); - call++; - } -} - -static void last_ditch_exit(int sig) -{ - signal(SIGINT, SIG_DFL); - signal(SIGTERM, SIG_DFL); - signal(SIGHUP, SIG_DFL); - uml_cleanup(); - exit(1); -} - -extern int uml_exitcode; - -extern void scan_elf_aux( char **envp); - -int main(int argc, char **argv, char **envp) -{ - char **new_argv; - sigset_t mask; - int ret, i, err; - - /* Enable all signals except SIGIO - in some environments, we can - * enter with some signals blocked - */ - - sigemptyset(&mask); - sigaddset(&mask, SIGIO); - if(sigprocmask(SIG_SETMASK, &mask, NULL) < 0){ - perror("sigprocmask"); - exit(1); - } - -#ifdef UML_CONFIG_CMDLINE_ON_HOST - /* Allocate memory for thread command lines */ - if(argc < 2 || strlen(argv[1]) < THREAD_NAME_LEN - 1){ - - char padding[THREAD_NAME_LEN] = { - [ 0 ... THREAD_NAME_LEN - 2] = ' ', '\0' - }; - - new_argv = malloc((argc + 2) * sizeof(char*)); - if(!new_argv) { - perror("Allocating extended argv"); - exit(1); - } - - new_argv[0] = argv[0]; - new_argv[1] = padding; - - for(i = 2; i <= argc; i++) - new_argv[i] = argv[i - 1]; - new_argv[argc + 1] = NULL; - - execvp(new_argv[0], new_argv); - perror("execing with extended args"); - exit(1); - } -#endif - - linux_prog = argv[0]; - - set_stklim(); - - new_argv = malloc((argc + 1) * sizeof(char *)); - if(new_argv == NULL){ - perror("Mallocing argv"); - exit(1); - } - for(i=0;i<argc;i++){ - new_argv[i] = strdup(argv[i]); - if(new_argv[i] == NULL){ - perror("Mallocing an arg"); - exit(1); - } - } - new_argv[argc] = NULL; - - set_handler(SIGINT, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); - set_handler(SIGTERM, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); - set_handler(SIGHUP, last_ditch_exit, SA_ONESHOT | SA_NODEFER, -1); - - scan_elf_aux( envp); - - do_uml_initcalls(); - ret = linux_main(argc, argv); - - /* Disable SIGPROF - I have no idea why libc doesn't do this or turn - * off the profiling time, but UML dies with a SIGPROF just before - * exiting when profiling is active. - */ - change_sig(SIGPROF, 0); - - /* This signal stuff used to be in the reboot case. However, - * sometimes a SIGVTALRM can come in when we're halting (reproducably - * when writing out gcov information, presumably because that takes - * some time) and cause a segfault. - */ - - /* stop timers and set SIG*ALRM to be ignored */ - disable_timer(); - - /* disable SIGIO for the fds and set SIGIO to be ignored */ - err = deactivate_all_fds(); - if(err) - printf("deactivate_all_fds failed, errno = %d\n", -err); - - /* Let any pending signals fire now. This ensures - * that they won't be delivered after the exec, when - * they are definitely not expected. - */ - unblock_signals(); - - /* Reboot */ - if(ret){ - printf("\n"); - execvp(new_argv[0], new_argv); - perror("Failed to exec kernel"); - ret = 1; - } - printf("\n"); - return(uml_exitcode); -} - -#define CAN_KMALLOC() \ - (kmalloc_ok && CHOOSE_MODE((os_getpid() != tracing_pid), 1)) - -extern void *__real_malloc(int); - -void *__wrap_malloc(int size) -{ - void *ret; - - if(!CAN_KMALLOC()) - return(__real_malloc(size)); - else if(size <= PAGE_SIZE) /* finding contiguos pages can be hard*/ - ret = um_kmalloc(size); - else ret = um_vmalloc(size); - - /* glibc people insist that if malloc fails, errno should be - * set by malloc as well. So we do. - */ - if(ret == NULL) - errno = ENOMEM; - - return(ret); -} - -void *__wrap_calloc(int n, int size) -{ - void *ptr = __wrap_malloc(n * size); - - if(ptr == NULL) return(NULL); - memset(ptr, 0, n * size); - return(ptr); -} - -extern void __real_free(void *); - -extern unsigned long high_physmem; - -void __wrap_free(void *ptr) -{ - unsigned long addr = (unsigned long) ptr; - - /* We need to know how the allocation happened, so it can be correctly - * freed. This is done by seeing what region of memory the pointer is - * in - - * physical memory - kmalloc/kfree - * kernel virtual memory - vmalloc/vfree - * anywhere else - malloc/free - * If kmalloc is not yet possible, then either high_physmem and/or - * end_vm are still 0 (as at startup), in which case we call free, or - * we have set them, but anyway addr has not been allocated from those - * areas. So, in both cases __real_free is called. - * - * CAN_KMALLOC is checked because it would be bad to free a buffer - * with kmalloc/vmalloc after they have been turned off during - * shutdown. - * XXX: However, we sometimes shutdown CAN_KMALLOC temporarily, so - * there is a possibility for memory leaks. - */ - - if((addr >= uml_physmem) && (addr < high_physmem)){ - if(CAN_KMALLOC()) - kfree(ptr); - } - else if((addr >= start_vm) && (addr < end_vm)){ - if(CAN_KMALLOC()) - vfree(ptr); - } - else __real_free(ptr); -} - -/* - * 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/mem.c b/arch/um/kernel/mem.c index ea008b031a8..fa4f915be5c 100644 --- a/arch/um/kernel/mem.c +++ b/arch/um/kernel/mem.c @@ -234,8 +234,8 @@ void paging_init(void) empty_bad_page = (unsigned long *) alloc_bootmem_low_pages(PAGE_SIZE); for(i=0;i<sizeof(zones_size)/sizeof(zones_size[0]);i++) zones_size[i] = 0; - zones_size[0] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); - zones_size[2] = highmem >> PAGE_SHIFT; + zones_size[ZONE_DMA] = (end_iomem >> PAGE_SHIFT) - (uml_physmem >> PAGE_SHIFT); + zones_size[ZONE_HIGHMEM] = highmem >> PAGE_SHIFT; free_area_init(zones_size); /* @@ -252,7 +252,7 @@ void paging_init(void) #endif } -struct page *arch_validate(struct page *page, int mask, int order) +struct page *arch_validate(struct page *page, gfp_t mask, int order) { unsigned long addr, zero = 0; int i; diff --git a/arch/um/kernel/physmem.c b/arch/um/kernel/physmem.c index ea670fcc8af..f3b583a878a 100644 --- a/arch/um/kernel/physmem.c +++ b/arch/um/kernel/physmem.c @@ -246,7 +246,7 @@ int is_remapped(void *virt) /* Changed during early boot */ unsigned long high_physmem; -extern unsigned long physmem_size; +extern unsigned long long physmem_size; int init_maps(unsigned long physmem, unsigned long iomem, unsigned long highmem) { @@ -321,7 +321,7 @@ void map_memory(unsigned long virt, unsigned long phys, unsigned long len, extern int __syscall_stub_start, __binary_start; void setup_physmem(unsigned long start, unsigned long reserve_end, - unsigned long len, unsigned long highmem) + unsigned long len, unsigned long long highmem) { unsigned long reserve = reserve_end - start; int pfn = PFN_UP(__pa(reserve_end)); diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 39cf568ccfa..34b54a3e213 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -80,9 +80,10 @@ void free_stack(unsigned long stack, int order) unsigned long alloc_stack(int order, int atomic) { unsigned long page; - int flags = GFP_KERNEL; + gfp_t flags = GFP_KERNEL; - if(atomic) flags |= GFP_ATOMIC; + if (atomic) + flags = GFP_ATOMIC; page = __get_free_pages(flags, order); if(page == 0) return(0); @@ -221,6 +222,7 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, pud_t *pud; pmd_t *pmd; pte_t *pte; + pte_t ptent; if(task->mm == NULL) return(ERR_PTR(-EINVAL)); @@ -237,12 +239,13 @@ void *um_virt_to_phys(struct task_struct *task, unsigned long addr, return(ERR_PTR(-EINVAL)); pte = pte_offset_kernel(pmd, addr); - if(!pte_present(*pte)) + ptent = *pte; + if(!pte_present(ptent)) return(ERR_PTR(-EINVAL)); if(pte_out != NULL) - *pte_out = *pte; - return((void *) (pte_val(*pte) & PAGE_MASK) + (addr & ~PAGE_MASK)); + *pte_out = ptent; + return((void *) (pte_val(ptent) & PAGE_MASK) + (addr & ~PAGE_MASK)); } char *current_cmd(void) diff --git a/arch/um/kernel/ptrace.c b/arch/um/kernel/ptrace.c index 71af4d50389..98e09395c09 100644 --- a/arch/um/kernel/ptrace.c +++ b/arch/um/kernel/ptrace.c @@ -43,53 +43,10 @@ void ptrace_disable(struct task_struct *child) extern int peek_user(struct task_struct * child, long addr, long data); extern int poke_user(struct task_struct * child, long addr, long data); -long sys_ptrace(long request, long pid, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, long addr, long data) { - struct task_struct *child; int i, ret; - lock_kernel(); - ret = -EPERM; - if (request == PTRACE_TRACEME) { - /* are we already being traced? */ - if (current->ptrace & PT_PTRACED) - goto out; - - ret = security_ptrace(current->parent, current); - if (ret) - goto out; - - /* set the ptrace bit in the process flags. */ - current->ptrace |= PT_PTRACED; - ret = 0; - goto out; - } - ret = -ESRCH; - read_lock(&tasklist_lock); - child = find_task_by_pid(pid); - if (child) - get_task_struct(child); - read_unlock(&tasklist_lock); - if (!child) - goto out; - - ret = -EPERM; - if (pid == 1) /* you may not mess with init */ - goto out_tsk; - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - goto out_tsk; - } - -#ifdef SUBACH_PTRACE_SPECIAL - SUBARCH_PTRACE_SPECIAL(child,request,addr,data); -#endif - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_tsk; - switch (request) { /* when I and D space are separate, these will need to be fixed. */ case PTRACE_PEEKTEXT: /* read word at location addr. */ @@ -282,10 +239,7 @@ long sys_ptrace(long request, long pid, long addr, long data) ret = ptrace_request(child, request, addr, data); break; } - out_tsk: - put_task_struct(child); - out: - unlock_kernel(); + return ret; } diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index e89218958f3..48b1f644b9a 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -18,7 +18,6 @@ #include "kern_util.h" #include "user_util.h" #include "sigio.h" -#include "helper.h" #include "os.h" /* Changed during early boot */ @@ -225,7 +224,7 @@ static int need_poll(int n) next_poll.used = n; return(0); } - if(next_poll.poll != NULL) kfree(next_poll.poll); + kfree(next_poll.poll); next_poll.poll = um_kmalloc_atomic(n * sizeof(struct pollfd)); if(next_poll.poll == NULL){ printk("need_poll : failed to allocate new pollfds\n"); @@ -340,7 +339,7 @@ static int setup_initial_poll(int fd) { struct pollfd *p; - p = um_kmalloc(sizeof(struct pollfd)); + p = um_kmalloc_atomic(sizeof(struct pollfd)); if(p == NULL){ printk("setup_initial_poll : failed to allocate poll\n"); return(-1); diff --git a/arch/um/kernel/skas/Makefile b/arch/um/kernel/skas/Makefile index db36c7c9594..8de471b59c1 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -6,8 +6,6 @@ obj-y := clone.o exec_kern.o mem.o mem_user.o mmu.o process.o process_kern.o \ syscall.o tlb.o trap_user.o uaccess.o -subdir- := util - USER_OBJS := process.o clone.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/skas/clone.c b/arch/um/kernel/skas/clone.c index 4dc55f10cd1..cb37ce9124a 100644 --- a/arch/um/kernel/skas/clone.c +++ b/arch/um/kernel/skas/clone.c @@ -9,18 +9,24 @@ #include "stub-data.h" #include "uml-config.h" #include "sysdep/stub.h" +#include "kern_constants.h" /* This is in a separate file because it needs to be compiled with any * extraneous gcc flags (-pg, -fprofile-arcs, -ftest-coverage) disabled + * + * Use UM_KERN_PAGE_SIZE instead of PAGE_SIZE because that calls getpagesize + * on some systems. */ + +#define STUB_DATA(field) (((struct stub_data *) UML_CONFIG_STUB_DATA)->field) + void __attribute__ ((__section__ (".__syscall_stub"))) stub_clone_handler(void) { long err; - struct stub_data *from = (struct stub_data *) UML_CONFIG_STUB_DATA; err = stub_syscall2(__NR_clone, CLONE_PARENT | CLONE_FILES | SIGCHLD, - UML_CONFIG_STUB_DATA + PAGE_SIZE / 2 - + UML_CONFIG_STUB_DATA + UM_KERN_PAGE_SIZE / 2 - sizeof(void *)); if(err != 0) goto out; @@ -30,15 +36,16 @@ stub_clone_handler(void) goto out; err = stub_syscall3(__NR_setitimer, ITIMER_VIRTUAL, - (long) &from->timer, 0); + (long) &STUB_DATA(timer), 0); if(err) goto out; - err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, PAGE_SIZE, - PROT_READ | PROT_WRITE, MAP_FIXED | MAP_SHARED, - from->fd, from->offset); + err = stub_syscall6(STUB_MMAP_NR, UML_CONFIG_STUB_DATA, + UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_FIXED | MAP_SHARED, STUB_DATA(fd), + STUB_DATA(offset)); out: /* save current result. Parent: pid; child: retcode of mmap */ - from->err = err; + STUB_DATA(err) = err; trap_myself(); } diff --git a/arch/um/kernel/skas/include/mmu-skas.h b/arch/um/kernel/skas/include/mmu-skas.h index 09536f81ee4..44110c521e4 100644 --- a/arch/um/kernel/skas/include/mmu-skas.h +++ b/arch/um/kernel/skas/include/mmu-skas.h @@ -8,6 +8,7 @@ #include "linux/config.h" #include "mm_id.h" +#include "asm/ldt.h" struct mmu_context_skas { struct mm_id id; @@ -15,6 +16,7 @@ struct mmu_context_skas { #ifdef CONFIG_3_LEVEL_PGTABLES unsigned long last_pmd; #endif + uml_ldt_t ldt; }; extern void switch_mm_skas(struct mm_id * mm_idp); diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index 060934740f9..daa2f85b684 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -10,7 +10,8 @@ #include "sysdep/ptrace.h" extern int userspace_pid[]; -extern int proc_mm, ptrace_faultinfo; +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); diff --git a/arch/um/kernel/skas/include/uaccess-skas.h b/arch/um/kernel/skas/include/uaccess-skas.h index 7da0c2def0e..f611f83ad4f 100644 --- a/arch/um/kernel/skas/include/uaccess-skas.h +++ b/arch/um/kernel/skas/include/uaccess-skas.h @@ -9,14 +9,8 @@ #include "asm/errno.h" #include "asm/fixmap.h" -#define access_ok_skas(type, addr, size) \ - ((segment_eq(get_fs(), KERNEL_DS)) || \ - (((unsigned long) (addr) < TASK_SIZE) && \ - ((unsigned long) (addr) + (size) <= TASK_SIZE)) || \ - ((type == VERIFY_READ ) && \ - ((unsigned long) (addr) >= FIXADDR_USER_START) && \ - ((unsigned long) (addr) + (size) <= FIXADDR_USER_END) && \ - ((unsigned long) (addr) + (size) >= (unsigned long)(addr)))) +/* 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); diff --git a/arch/um/kernel/skas/mem.c b/arch/um/kernel/skas/mem.c index 147466d7ff4..88ab96c609c 100644 --- a/arch/um/kernel/skas/mem.c +++ b/arch/um/kernel/skas/mem.c @@ -20,7 +20,7 @@ unsigned long set_task_sizes_skas(int arg, unsigned long *host_size_out, *task_size_out = CONFIG_HOST_TASK_SIZE; #else *host_size_out = top; - if (proc_mm && ptrace_faultinfo) + if (!skas_needs_stub) *task_size_out = top; else *task_size_out = CONFIG_STUB_START & PGDIR_MASK; #endif diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 240143b616a..677871f1b37 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -15,6 +15,7 @@ #include "asm/mmu.h" #include "asm/pgalloc.h" #include "asm/pgtable.h" +#include "asm/ldt.h" #include "os.h" #include "skas.h" @@ -28,7 +29,6 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, pmd_t *pmd; pte_t *pte; - spin_lock(&mm->page_table_lock); pgd = pgd_offset(mm, proc); pud = pud_alloc(mm, pgd, proc); if (!pud) @@ -63,7 +63,6 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, *pte = mk_pte(virt_to_page(kernel), __pgprot(_PAGE_PRESENT)); *pte = pte_mkexec(*pte); *pte = pte_wrprotect(*pte); - spin_unlock(&mm->page_table_lock); return(0); out_pmd: @@ -71,19 +70,17 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, out_pte: pmd_free(pmd); out: - spin_unlock(&mm->page_table_lock); return(-ENOMEM); } int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) { - struct mm_struct *cur_mm = current->mm; - struct mm_id *cur_mm_id = &cur_mm->context.skas.id; - struct mm_id *mm_id = &mm->context.skas.id; + struct mmu_context_skas *from_mm = NULL; + struct mmu_context_skas *to_mm = &mm->context.skas; unsigned long stack = 0; - int from, ret = -ENOMEM; + int from_fd, ret = -ENOMEM; - if(!proc_mm || !ptrace_faultinfo){ + if(skas_needs_stub){ stack = get_zeroed_page(GFP_KERNEL); if(stack == 0) goto out; @@ -105,33 +102,43 @@ int init_new_context_skas(struct task_struct *task, struct mm_struct *mm) mm->nr_ptes--; } - mm_id->stack = stack; + + to_mm->id.stack = stack; + if(current->mm != NULL && current->mm != &init_mm) + from_mm = ¤t->mm->context.skas; if(proc_mm){ - if((cur_mm != NULL) && (cur_mm != &init_mm)) - from = cur_mm_id->u.mm_fd; - else from = -1; + if(from_mm) + from_fd = from_mm->id.u.mm_fd; + else from_fd = -1; - ret = new_mm(from, stack); + ret = new_mm(from_fd, stack); if(ret < 0){ printk("init_new_context_skas - new_mm failed, " "errno = %d\n", ret); goto out_free; } - mm_id->u.mm_fd = ret; + to_mm->id.u.mm_fd = ret; } else { - if((cur_mm != NULL) && (cur_mm != &init_mm)) - mm_id->u.pid = copy_context_skas0(stack, - cur_mm_id->u.pid); - else mm_id->u.pid = start_userspace(stack); + if(from_mm) + to_mm->id.u.pid = copy_context_skas0(stack, + from_mm->id.u.pid); + else to_mm->id.u.pid = start_userspace(stack); + } + + ret = init_new_ldt(to_mm, from_mm); + if(ret < 0){ + printk("init_new_context_skas - init_ldt" + " failed, errno = %d\n", ret); + goto out_free; } return 0; out_free: - if(mm_id->stack != 0) - free_page(mm_id->stack); + if(to_mm->id.stack != 0) + free_page(to_mm->id.stack); out: return ret; } @@ -147,6 +154,7 @@ void destroy_context_skas(struct mm_struct *mm) if(!proc_mm || !ptrace_faultinfo){ free_page(mmu->id.stack); + pte_lock_deinit(virt_to_page(mmu->last_page_table)); pte_free_kernel((pte_t *) mmu->last_page_table); dec_page_state(nr_page_table_pages); #ifdef CONFIG_3_LEVEL_PGTABLES diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 5cd0e992978..599d679bd4f 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -69,6 +69,17 @@ void wait_stub_done(int pid, int sig, char * fname) if((n < 0) || !WIFSTOPPED(status) || (WSTOPSIG(status) != SIGUSR1 && WSTOPSIG(status) != SIGTRAP)){ + unsigned long regs[FRAME_SIZE]; + if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) + printk("Failed to get registers from stub, " + "errno = %d\n", errno); + else { + int i; + + printk("Stub registers -\n"); + for(i = 0; i < FRAME_SIZE; i++) + printk("\t%d - %lx\n", i, regs[i]); + } panic("%s : failed to wait for SIGUSR1/SIGTRAP, " "pid = %d, n = %d, errno = %d, status = 0x%x\n", fname, pid, n, errno, status); @@ -370,9 +381,9 @@ int copy_context_skas0(unsigned long new_stack, int pid) } /* - * This is used only, if proc_mm is available, while PTRACE_FAULTINFO - * isn't. Opening /proc/mm creates a new mm_context, which lacks the stub-pages - * Thus, we map them using /proc/mm-fd + * This is used only, if stub pages are needed, while proc_mm is + * availabl. Opening /proc/mm creates a new mm_context, which lacks + * the stub-pages. Thus, we map them using /proc/mm-fd */ void map_stub_pages(int fd, unsigned long code, unsigned long data, unsigned long stack) diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index efe92e8aa2a..9c990253966 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -145,7 +145,7 @@ int new_mm(int from, unsigned long stack) "err = %d\n", -n); } - if(!ptrace_faultinfo) + if(skas_needs_stub) map_stub_pages(fd, CONFIG_STUB_CODE, CONFIG_STUB_DATA, stack); return(fd); diff --git a/arch/um/kernel/skas/uaccess.c b/arch/um/kernel/skas/uaccess.c index 75195281081..a5a47528dec 100644 --- a/arch/um/kernel/skas/uaccess.c +++ b/arch/um/kernel/skas/uaccess.c @@ -143,7 +143,7 @@ int copy_from_user_skas(void *to, const void __user *from, int n) return(0); } - return(access_ok_skas(VERIFY_READ, from, n) ? + return(access_ok(VERIFY_READ, from, n) ? buffer_op((unsigned long) from, n, 0, copy_chunk_from_user, &to): n); } @@ -164,7 +164,7 @@ int copy_to_user_skas(void __user *to, const void *from, int n) return(0); } - return(access_ok_skas(VERIFY_WRITE, to, n) ? + return(access_ok(VERIFY_WRITE, to, n) ? buffer_op((unsigned long) to, n, 1, copy_chunk_to_user, &from) : n); } @@ -193,7 +193,7 @@ int strncpy_from_user_skas(char *dst, const char __user *src, int count) return(strnlen(dst, count)); } - if(!access_ok_skas(VERIFY_READ, src, 1)) + if(!access_ok(VERIFY_READ, src, 1)) return(-EFAULT); n = buffer_op((unsigned long) src, count, 0, strncpy_chunk_from_user, @@ -221,7 +221,7 @@ int clear_user_skas(void __user *mem, int len) return(0); } - return(access_ok_skas(VERIFY_WRITE, mem, len) ? + return(access_ok(VERIFY_WRITE, mem, len) ? buffer_op((unsigned long) mem, len, 1, clear_chunk, NULL) : len); } diff --git a/arch/um/kernel/skas/util/Makefile b/arch/um/kernel/skas/util/Makefile deleted file mode 100644 index f7b7eba8334..00000000000 --- a/arch/um/kernel/skas/util/Makefile +++ /dev/null @@ -1,5 +0,0 @@ -hostprogs-y := mk_ptregs -always := $(hostprogs-y) - -mk_ptregs-objs := mk_ptregs-$(SUBARCH).o -HOSTCFLAGS_mk_ptregs-$(SUBARCH).o := -I$(objtree)/arch/um diff --git a/arch/um/kernel/skas/util/mk_ptregs-i386.c b/arch/um/kernel/skas/util/mk_ptregs-i386.c deleted file mode 100644 index 1f96e1eeb8a..00000000000 --- a/arch/um/kernel/skas/util/mk_ptregs-i386.c +++ /dev/null @@ -1,49 +0,0 @@ -#include <stdio.h> -#include <user-offsets.h> - -#define SHOW(name) printf("#define %s %d\n", #name, name) - -int main(int argc, char **argv) -{ - printf("/* Automatically generated by " - "arch/um/kernel/skas/util/mk_ptregs */\n"); - printf("\n"); - printf("#ifndef __SKAS_PT_REGS_\n"); - printf("#define __SKAS_PT_REGS_\n"); - printf("\n"); - SHOW(HOST_FRAME_SIZE); - SHOW(HOST_FP_SIZE); - SHOW(HOST_XFP_SIZE); - - SHOW(HOST_IP); - SHOW(HOST_SP); - SHOW(HOST_EFLAGS); - SHOW(HOST_EAX); - SHOW(HOST_EBX); - SHOW(HOST_ECX); - SHOW(HOST_EDX); - SHOW(HOST_ESI); - SHOW(HOST_EDI); - SHOW(HOST_EBP); - SHOW(HOST_CS); - SHOW(HOST_SS); - SHOW(HOST_DS); - SHOW(HOST_FS); - SHOW(HOST_ES); - SHOW(HOST_GS); - - printf("\n"); - printf("#endif\n"); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c b/arch/um/kernel/skas/util/mk_ptregs-x86_64.c deleted file mode 100644 index 5fccbfe35f7..00000000000 --- a/arch/um/kernel/skas/util/mk_ptregs-x86_64.c +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2003 PathScale, Inc. - * - * Licensed under the GPL - */ - -#include <stdio.h> -#include <user-offsets.h> - -#define SHOW(name) \ - printf("#define %s (%d / sizeof(unsigned long))\n", #name, name) - -int main(int argc, char **argv) -{ - printf("/* Automatically generated by " - "arch/um/kernel/skas/util/mk_ptregs */\n"); - printf("\n"); - printf("#ifndef __SKAS_PT_REGS_\n"); - printf("#define __SKAS_PT_REGS_\n"); - SHOW(HOST_FRAME_SIZE); - SHOW(HOST_RBX); - SHOW(HOST_RCX); - SHOW(HOST_RDI); - SHOW(HOST_RSI); - SHOW(HOST_RDX); - SHOW(HOST_RBP); - SHOW(HOST_RAX); - SHOW(HOST_R8); - SHOW(HOST_R9); - SHOW(HOST_R10); - SHOW(HOST_R11); - SHOW(HOST_R12); - SHOW(HOST_R13); - SHOW(HOST_R14); - SHOW(HOST_R15); - SHOW(HOST_ORIG_RAX); - SHOW(HOST_CS); - SHOW(HOST_SS); - SHOW(HOST_EFLAGS); -#if 0 - SHOW(HOST_FS); - SHOW(HOST_GS); - SHOW(HOST_DS); - SHOW(HOST_ES); -#endif - - SHOW(HOST_IP); - SHOW(HOST_SP); - printf("#define HOST_FP_SIZE 0\n"); - printf("#define HOST_XFP_SIZE 0\n"); - printf("\n"); - printf("\n"); - printf("#endif\n"); - return(0); -} - -/* - * Overrides for Emacs so that we follow Linus's tabbing style. - * Emacs will notice this stuff at the end of the file and automatically - * adjust the settings for this buffer only. This must remain at the end - * of the file. - * --------------------------------------------------------------------------- - * Local variables: - * c-file-style: "linux" - * End: - */ diff --git a/arch/um/kernel/sysrq.c b/arch/um/kernel/sysrq.c index f80850091e7..b331e970002 100644 --- a/arch/um/kernel/sysrq.c +++ b/arch/um/kernel/sysrq.c @@ -62,13 +62,7 @@ void show_stack(struct task_struct *task, unsigned long *esp) if (esp == NULL) { if (task != current && task != NULL) { - /* XXX: Isn't this bogus? I.e. isn't this the - * *userspace* stack of this task? If not so, use this - * even when task == current (as in i386). - */ esp = (unsigned long *) KSTK_ESP(task); - /* Which one? No actual difference - just coding style.*/ - //esp = (unsigned long *) PT_REGS_IP(&task->thread.regs); } else { esp = (unsigned long *) &esp; } @@ -84,5 +78,5 @@ void show_stack(struct task_struct *task, unsigned long *esp) } printk("Call Trace: \n"); - show_trace(current, esp); + show_trace(task, esp); } diff --git a/arch/um/kernel/time_kern.c b/arch/um/kernel/time_kern.c index 4e08f7545d6..020ca79b8d3 100644 --- a/arch/um/kernel/time_kern.c +++ b/arch/um/kernel/time_kern.c @@ -22,10 +22,6 @@ #include "mode.h" #include "os.h" -u64 jiffies_64 = INITIAL_JIFFIES; - -EXPORT_SYMBOL(jiffies_64); - int hz(void) { return(HZ); diff --git a/arch/um/kernel/tlb.c b/arch/um/kernel/tlb.c index 0a562c3c0fd..f5b0636f9ad 100644 --- a/arch/um/kernel/tlb.c +++ b/arch/um/kernel/tlb.c @@ -193,12 +193,12 @@ void fix_range_common(struct mm_struct *mm, unsigned long start_addr, r = pte_read(*npte); w = pte_write(*npte); x = pte_exec(*npte); - if(!pte_dirty(*npte)) - w = 0; - if(!pte_young(*npte)){ - r = 0; - w = 0; - } + if (!pte_young(*npte)) { + r = 0; + w = 0; + } else if (!pte_dirty(*npte)) { + w = 0; + } if(force || pte_newpage(*npte)){ if(pte_present(*npte)) ret = add_mmap(addr, diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 87cc6fd76ce..0d4c10a7360 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -18,6 +18,7 @@ #include "asm/a.out.h" #include "asm/current.h" #include "asm/irq.h" +#include "sysdep/sigcontext.h" #include "user_util.h" #include "kern_util.h" #include "kern.h" @@ -25,6 +26,9 @@ #include "mconsole_kern.h" #include "mem.h" #include "mem_kern.h" +#ifdef CONFIG_MODE_SKAS +#include "skas.h" +#endif /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ int handle_page_fault(unsigned long address, unsigned long ip, @@ -39,6 +43,12 @@ int handle_page_fault(unsigned long address, unsigned long ip, int err = -EFAULT; *code_out = SEGV_MAPERR; + + /* If the fault was during atomic operation, don't take the fault, just + * fail. */ + if (in_atomic()) + goto out_nosemaphore; + down_read(&mm->mmap_sem); vma = find_vma(mm, address); if(!vma) @@ -85,10 +95,20 @@ survive: pte = pte_offset_kernel(pmd, address); } while(!pte_present(*pte)); err = 0; + /* The below warning was added in place of + * pte_mkyoung(); if (is_write) pte_mkdirty(); + * If it's triggered, we'd see normally a hang here (a clean pte is + * marked read-only to emulate the dirty bit). + * However, the generic code can mark a PTE writable but clean on a + * concurrent read fault, triggering this harmlessly. So comment it out. + */ +#if 0 WARN_ON(!pte_young(*pte) || (is_write && !pte_dirty(*pte))); +#endif flush_tlb_page(vma, address); out: up_read(&mm->mmap_sem); +out_nosemaphore: return(err); /* @@ -125,7 +145,15 @@ unsigned long segv(struct faultinfo fi, unsigned long ip, int is_user, void *sc) } else if(current->mm == NULL) panic("Segfault with no mm"); - err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + + if (SEGV_IS_FIXABLE(&fi) || SEGV_MAYBE_FIXABLE(&fi)) + err = handle_page_fault(address, ip, is_write, is_user, &si.si_code); + else { + err = -EFAULT; + /* A thread accessed NULL, we get a fault, but CR2 is invalid. + * This code is used in __do_copy_from_user() of TT mode. */ + address = 0; + } catcher = current->thread.fault_catcher; if(!err) diff --git a/arch/um/kernel/tt/include/uaccess-tt.h b/arch/um/kernel/tt/include/uaccess-tt.h index dc2ebfa8c54..b9bfe9c481c 100644 --- a/arch/um/kernel/tt/include/uaccess-tt.h +++ b/arch/um/kernel/tt/include/uaccess-tt.h @@ -19,19 +19,13 @@ extern unsigned long end_vm; extern unsigned long uml_physmem; -#define under_task_size(addr, size) \ - (((unsigned long) (addr) < TASK_SIZE) && \ - (((unsigned long) (addr) + (size)) < TASK_SIZE)) - #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) \ - ((type == VERIFY_READ) || (segment_eq(get_fs(), KERNEL_DS)) || \ - (((unsigned long) (addr) <= ((unsigned long) (addr) + (size))) && \ - (under_task_size(addr, size) || is_stack(addr, size)))) + (is_stack(addr, size)) extern unsigned long get_fault_addr(void); diff --git a/arch/um/kernel/tt/tlb.c b/arch/um/kernel/tt/tlb.c index f1d85dbb45b..ae6217c8613 100644 --- a/arch/um/kernel/tt/tlb.c +++ b/arch/um/kernel/tt/tlb.c @@ -74,42 +74,6 @@ void flush_tlb_kernel_range_tt(unsigned long start, unsigned long end) atomic_inc(&vmchange_seq); } -static void protect_vm_page(unsigned long addr, int w, int must_succeed) -{ - int err; - - err = protect_memory(addr, PAGE_SIZE, 1, w, 1, must_succeed); - if(err == 0) return; - else if((err == -EFAULT) || (err == -ENOMEM)){ - flush_tlb_kernel_range(addr, addr + PAGE_SIZE); - protect_vm_page(addr, w, 1); - } - else panic("protect_vm_page : protect failed, errno = %d\n", err); -} - -void mprotect_kernel_vm(int w) -{ - struct mm_struct *mm; - pgd_t *pgd; - pud_t *pud; - pmd_t *pmd; - pte_t *pte; - unsigned long addr; - - mm = &init_mm; - for(addr = start_vm; addr < end_vm;){ - pgd = pgd_offset(mm, addr); - pud = pud_offset(pgd, addr); - pmd = pmd_offset(pud, addr); - if(pmd_present(*pmd)){ - pte = pte_offset_kernel(pmd, addr); - if(pte_present(*pte)) protect_vm_page(addr, w, 0); - addr += PAGE_SIZE; - } - else addr += PMD_SIZE; - } -} - void flush_tlb_kernel_vm_tt(void) { flush_tlb_kernel_range(start_vm, end_vm); diff --git a/arch/um/kernel/tt/uaccess.c b/arch/um/kernel/tt/uaccess.c index a72aa632972..1cb60726567 100644 --- a/arch/um/kernel/tt/uaccess.c +++ b/arch/um/kernel/tt/uaccess.c @@ -8,7 +8,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) { - if(!access_ok_tt(VERIFY_READ, from, n)) + if(!access_ok(VERIFY_READ, from, n)) return(n); return(__do_copy_from_user(to, from, n, ¤t->thread.fault_addr, @@ -17,7 +17,7 @@ int copy_from_user_tt(void *to, const void __user *from, int n) int copy_to_user_tt(void __user *to, const void *from, int n) { - if(!access_ok_tt(VERIFY_WRITE, to, n)) + if(!access_ok(VERIFY_WRITE, to, n)) return(n); return(__do_copy_to_user(to, from, n, ¤t->thread.fault_addr, @@ -28,7 +28,7 @@ int strncpy_from_user_tt(char *dst, const char __user *src, int count) { int n; - if(!access_ok_tt(VERIFY_READ, src, 1)) + if(!access_ok(VERIFY_READ, src, 1)) return(-EFAULT); n = __do_strncpy_from_user(dst, src, count, @@ -47,7 +47,7 @@ int __clear_user_tt(void __user *mem, int len) int clear_user_tt(void __user *mem, int len) { - if(!access_ok_tt(VERIFY_WRITE, mem, len)) + if(!access_ok(VERIFY_WRITE, mem, len)) return(len); return(__do_clear_user(mem, len, ¤t->thread.fault_addr, diff --git a/arch/um/kernel/tt/uaccess_user.c b/arch/um/kernel/tt/uaccess_user.c index f01475512ec..6c92bbccb49 100644 --- a/arch/um/kernel/tt/uaccess_user.c +++ b/arch/um/kernel/tt/uaccess_user.c @@ -10,6 +10,7 @@ #include "uml_uaccess.h" #include "task.h" #include "kern_util.h" +#include "os.h" int __do_copy_from_user(void *to, const void *from, int n, void **fault_addr, void **fault_catcher) @@ -22,8 +23,15 @@ int __do_copy_from_user(void *to, const void *from, int n, __do_copy, &faulted); TASK_REGS(get_current())->tt = save; - if(!faulted) return(0); - else return(n - (fault - (unsigned long) from)); + if(!faulted) + return 0; + else if (fault) + return n - (fault - (unsigned long) from); + else + /* In case of a general protection fault, we don't have the + * fault address, so NULL is used instead. Pretend we didn't + * copy anything. */ + return n; } static void __do_strncpy(void *dst, const void *src, int count) diff --git a/arch/um/kernel/uaccess.c b/arch/um/kernel/uaccess.c new file mode 100644 index 00000000000..054e3de0784 --- /dev/null +++ b/arch/um/kernel/uaccess.c @@ -0,0 +1,30 @@ +/* + * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) + * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) + * Licensed under the GPL + */ + +/* These are here rather than tt/uaccess.c because skas mode needs them in + * order to do SIGBUS recovery when a tmpfs mount runs out of room. + */ + +#include <linux/string.h> +#include "os.h" + +void __do_copy(void *to, const void *from, int n) +{ + memcpy(to, from, n); +} + + +int __do_copy_to_user(void *to, const void *from, int n, + void **fault_addr, void **fault_catcher) +{ + unsigned long fault; + int faulted; + + fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, + __do_copy, &faulted); + if(!faulted) return(0); + else return(n - (fault - (unsigned long) to)); +} diff --git a/arch/um/kernel/uaccess_user.c b/arch/um/kernel/uaccess_user.c deleted file mode 100644 index d035257ed0a..00000000000 --- a/arch/um/kernel/uaccess_user.c +++ /dev/null @@ -1,64 +0,0 @@ -/* - * Copyright (C) 2001 Chris Emerson (cemerson@chiark.greenend.org.uk) - * Copyright (C) 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <setjmp.h> -#include <string.h> - -/* These are here rather than tt/uaccess.c because skas mode needs them in - * order to do SIGBUS recovery when a tmpfs mount runs out of room. - */ - -unsigned long __do_user_copy(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher, - void (*op)(void *to, const void *from, - int n), int *faulted_out) -{ - unsigned long *faddrp = (unsigned long *) fault_addr, ret; - - sigjmp_buf jbuf; - *fault_catcher = &jbuf; - if(sigsetjmp(jbuf, 1) == 0){ - (*op)(to, from, n); - ret = 0; - *faulted_out = 0; - } - else { - ret = *faddrp; - *faulted_out = 1; - } - *fault_addr = NULL; - *fault_catcher = NULL; - return ret; -} - -void __do_copy(void *to, const void *from, int n) -{ - memcpy(to, from, n); -} - - -int __do_copy_to_user(void *to, const void *from, int n, - void **fault_addr, void **fault_catcher) -{ - unsigned long fault; - int faulted; - - fault = __do_user_copy(to, from, n, fault_addr, fault_catcher, - __do_copy, &faulted); - if(!faulted) return(0); - else return(n - (fault - (unsigned long) to)); -} - -/* - * 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/um_arch.c b/arch/um/kernel/um_arch.c index f0a275947d3..142a9493912 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -137,7 +137,7 @@ static char *argv1_end = NULL; /* Set in early boot */ static int have_root __initdata = 0; -long physmem_size = 32 * 1024 * 1024; +long long physmem_size = 32 * 1024 * 1024; void set_cmdline(char *cmd) { @@ -334,6 +334,8 @@ int linux_main(int argc, char **argv) add_arg(DEFAULT_COMMAND_LINE); os_early_checks(); + if (force_tt) + clear_can_do_skas(); mode_tt = force_tt ? 1 : !can_do_skas(); #ifndef CONFIG_MODE_TT if (mode_tt) { @@ -400,7 +402,7 @@ int linux_main(int argc, char **argv) #ifndef CONFIG_HIGHMEM highmem = 0; printf("CONFIG_HIGHMEM not enabled - physical memory shrunk " - "to %ld bytes\n", physmem_size); + "to %lu bytes\n", physmem_size); #endif } @@ -412,8 +414,8 @@ int linux_main(int argc, char **argv) setup_physmem(uml_physmem, uml_reserved, physmem_size, highmem); if(init_maps(physmem_size, iomem_size, highmem)){ - printf("Failed to allocate mem_map for %ld bytes of physical " - "memory and %ld bytes of highmem\n", physmem_size, + printf("Failed to allocate mem_map for %lu bytes of physical " + "memory and %lu bytes of highmem\n", physmem_size, highmem); exit(1); } @@ -424,7 +426,7 @@ int linux_main(int argc, char **argv) end_vm = start_vm + virtmem_size; if(virtmem_size < physmem_size) - printf("Kernel virtual memory size shrunk to %ld bytes\n", + printf("Kernel virtual memory size shrunk to %lu bytes\n", virtmem_size); uml_postsetup(); diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 186c2888501..0b21d59ba0c 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -31,6 +31,8 @@ static char *uml_dir = UML_DIR; /* Changed by set_umid */ static int umid_is_random = 1; static int umid_inited = 0; +/* Have we created the files? Should we remove them? */ +static int umid_owned = 0; static int make_umid(int (*printer)(const char *fmt, ...)); @@ -82,20 +84,21 @@ int __init umid_file_name(char *name, char *buf, int len) extern int tracing_pid; -static int __init create_pid_file(void) +static void __init create_pid_file(void) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")]; int fd, n; - if(umid_file_name("pid", file, sizeof(file))) return 0; + if(umid_file_name("pid", file, sizeof(file))) + return; fd = os_open_file(file, of_create(of_excl(of_rdwr(OPENFLAGS()))), 0644); if(fd < 0){ printf("Open of machine pid file \"%s\" failed: %s\n", file, strerror(-fd)); - return 0; + return; } sprintf(pid, "%d\n", os_getpid()); @@ -103,7 +106,6 @@ static int __init create_pid_file(void) if(n != strlen(pid)) printf("Write of pid file failed - err = %d\n", -n); os_close_file(fd); - return 0; } static int actually_do_remove(char *dir) @@ -147,7 +149,8 @@ static int actually_do_remove(char *dir) void remove_umid_dir(void) { char dir[strlen(uml_dir) + UMID_LEN + 1]; - if(!umid_inited) return; + if (!umid_owned) + return; sprintf(dir, "%s%s", uml_dir, umid); actually_do_remove(dir); @@ -155,11 +158,12 @@ void remove_umid_dir(void) char *get_umid(int only_if_set) { - if(only_if_set && umid_is_random) return(NULL); - return(umid); + if(only_if_set && umid_is_random) + return NULL; + return umid; } -int not_dead_yet(char *dir) +static int not_dead_yet(char *dir) { char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; char pid[sizeof("nnnnn\0")], *end; @@ -193,7 +197,8 @@ int not_dead_yet(char *dir) (p == CHOOSE_MODE(tracing_pid, os_getpid()))) dead = 1; } - if(!dead) return(1); + if(!dead) + return(1); return(actually_do_remove(dir)); } @@ -232,16 +237,13 @@ static int __init make_uml_dir(void) strlcpy(dir, home, sizeof(dir)); uml_dir++; } + strlcat(dir, uml_dir, sizeof(dir)); len = strlen(dir); - strncat(dir, uml_dir, sizeof(dir) - len); - len = strlen(dir); - if((len > 0) && (len < sizeof(dir) - 1) && (dir[len - 1] != '/')){ - dir[len] = '/'; - dir[len + 1] = '\0'; - } + if (len > 0 && dir[len - 1] != '/') + strlcat(dir, "/", sizeof(dir)); uml_dir = malloc(strlen(dir) + 1); - if(uml_dir == NULL){ + if (uml_dir == NULL) { printf("make_uml_dir : malloc failed, errno = %d\n", errno); exit(1); } @@ -286,6 +288,7 @@ static int __init make_umid(int (*printer)(const char *fmt, ...)) if(errno == EEXIST){ if(not_dead_yet(tmp)){ (*printer)("umid '%s' is in use\n", umid); + umid_owned = 0; return(-1); } err = mkdir(tmp, 0777); @@ -296,7 +299,8 @@ static int __init make_umid(int (*printer)(const char *fmt, ...)) return(-1); } - return(0); + umid_owned = 1; + return 0; } __uml_setup("uml_dir=", set_uml_dir, @@ -309,7 +313,8 @@ static int __init make_umid_setup(void) /* one function with the ordering we need ... */ make_uml_dir(); make_umid(printf); - return create_pid_file(); + create_pid_file(); + return 0; } __uml_postsetup(make_umid_setup); diff --git a/arch/um/kernel/user_util.c b/arch/um/kernel/user_util.c index 41d17c71511..4c231161f25 100644 --- a/arch/um/kernel/user_util.c +++ b/arch/um/kernel/user_util.c @@ -27,7 +27,6 @@ #include "user.h" #include "mem_user.h" #include "init.h" -#include "helper.h" #include "ptrace_user.h" #include "uml-config.h" |