diff options
Diffstat (limited to 'arch/um/kernel')
-rw-r--r-- | arch/um/kernel/Makefile | 8 | ||||
-rw-r--r-- | arch/um/kernel/asm-offsets.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/irq_user.c | 49 | ||||
-rw-r--r-- | arch/um/kernel/process_kern.c | 7 | ||||
-rw-r--r-- | arch/um/kernel/reboot.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/sigio_user.c | 2 | ||||
-rw-r--r-- | arch/um/kernel/signal_kern.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/signal_user.c | 157 | ||||
-rw-r--r-- | arch/um/kernel/skas/Makefile | 2 | ||||
-rw-r--r-- | arch/um/kernel/skas/include/skas.h | 1 | ||||
-rw-r--r-- | arch/um/kernel/skas/process.c | 15 | ||||
-rw-r--r-- | arch/um/kernel/skas/process_kern.c | 5 | ||||
-rw-r--r-- | arch/um/kernel/skas/trap_user.c | 78 | ||||
-rw-r--r-- | arch/um/kernel/time.c | 9 | ||||
-rw-r--r-- | arch/um/kernel/trap_kern.c | 25 | ||||
-rw-r--r-- | arch/um/kernel/trap_user.c | 98 | ||||
-rw-r--r-- | arch/um/kernel/tt/exec_kern.c | 3 | ||||
-rw-r--r-- | arch/um/kernel/tt/process_kern.c | 9 | ||||
-rw-r--r-- | arch/um/kernel/tt/tracer.c | 1 | ||||
-rw-r--r-- | arch/um/kernel/tt/trap_user.c | 16 | ||||
-rw-r--r-- | arch/um/kernel/um_arch.c | 15 | ||||
-rw-r--r-- | arch/um/kernel/umid.c | 323 |
22 files changed, 89 insertions, 739 deletions
diff --git a/arch/um/kernel/Makefile b/arch/um/kernel/Makefile index 3de9d21e36b..193cc2b7448 100644 --- a/arch/um/kernel/Makefile +++ b/arch/um/kernel/Makefile @@ -9,9 +9,9 @@ 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 signal_user.o smp.o syscall_kern.o sysrq.o time.o \ - time_kern.o tlb.o trap_kern.o trap_user.o uaccess.o um_arch.o \ - umid.o user_util.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 obj-$(CONFIG_BLK_DEV_INITRD) += initrd.o obj-$(CONFIG_GPROF) += gprof_syms.o @@ -24,7 +24,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 umid.o user_util.o +USER_OBJS := $(user-objs-y) config.o time.o tty_log.o user_util.o include arch/um/scripts/Makefile.rules diff --git a/arch/um/kernel/asm-offsets.c b/arch/um/kernel/asm-offsets.c index c13a64a288f..91ea538e161 100644 --- a/arch/um/kernel/asm-offsets.c +++ b/arch/um/kernel/asm-offsets.c @@ -1 +1 @@ -/* Dummy file to make kbuild happy - unused! */ +#include "sysdep/kernel-offsets.h" diff --git a/arch/um/kernel/irq_user.c b/arch/um/kernel/irq_user.c index c3ccaf24f3e..0e32f5f4a88 100644 --- a/arch/um/kernel/irq_user.c +++ b/arch/um/kernel/irq_user.c @@ -15,7 +15,6 @@ #include "kern_util.h" #include "user.h" #include "process.h" -#include "signal_user.h" #include "sigio.h" #include "irq_user.h" #include "os.h" @@ -29,7 +28,6 @@ struct irq_fd { int pid; int events; int current_events; - int freed; }; static struct irq_fd *active_fds = NULL; @@ -41,9 +39,11 @@ static int pollfds_size = 0; extern int io_count, intr_count; +extern void free_irqs(void); + void sigio_handler(int sig, union uml_pt_regs *regs) { - struct irq_fd *irq_fd, *next; + struct irq_fd *irq_fd; int i, n; if(smp_sigio_handler()) return; @@ -66,29 +66,15 @@ void sigio_handler(int sig, union uml_pt_regs *regs) irq_fd = irq_fd->next; } - for(irq_fd = active_fds; irq_fd != NULL; irq_fd = next){ - next = irq_fd->next; + for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ if(irq_fd->current_events != 0){ irq_fd->current_events = 0; do_IRQ(irq_fd->irq, regs); - - /* This is here because the next irq may be - * freed in the handler. If a console goes - * away, both the read and write irqs will be - * freed. After do_IRQ, ->next will point to - * a good IRQ. - * Irqs can't be freed inside their handlers, - * so the next best thing is to have them - * marked as needing freeing, so that they - * can be freed here. - */ - next = irq_fd->next; - if(irq_fd->freed){ - free_irq(irq_fd->irq, irq_fd->id); - } } } } + + free_irqs(); } int activate_ipi(int fd, int pid) @@ -136,8 +122,7 @@ int activate_fd(int irq, int fd, int type, void *dev_id) .irq = irq, .pid = pid, .events = events, - .current_events = 0, - .freed = 0 } ); + .current_events = 0 } ); /* Critical section - locked by a spinlock because this stuff can * be changed from interrupt handlers. The stuff above is done @@ -313,26 +298,6 @@ static struct irq_fd *find_irq_by_fd(int fd, int irqnum, int *index_out) return(irq); } -void free_irq_later(int irq, void *dev_id) -{ - struct irq_fd *irq_fd; - unsigned long flags; - - flags = irq_lock(); - for(irq_fd = active_fds; irq_fd != NULL; irq_fd = irq_fd->next){ - if((irq_fd->irq == irq) && (irq_fd->id == dev_id)) - break; - } - if(irq_fd == NULL){ - printk("free_irq_later found no irq, irq = %d, " - "dev_id = 0x%p\n", irq, dev_id); - goto out; - } - irq_fd->freed = 1; - out: - irq_unlock(flags); -} - void reactivate_fd(int fd, int irqnum) { struct irq_fd *irq; diff --git a/arch/um/kernel/process_kern.c b/arch/um/kernel/process_kern.c index 34b54a3e213..7f13b85d265 100644 --- a/arch/um/kernel/process_kern.c +++ b/arch/um/kernel/process_kern.c @@ -36,7 +36,6 @@ #include "kern_util.h" #include "kern.h" #include "signal_kern.h" -#include "signal_user.h" #include "init.h" #include "irq_user.h" #include "mem_user.h" @@ -108,7 +107,7 @@ void set_current(void *t) { struct task_struct *task = t; - cpu_tasks[task->thread_info->cpu] = ((struct cpu_task) + cpu_tasks[task_thread_info(task)->cpu] = ((struct cpu_task) { external_pid(task), task }); } @@ -324,10 +323,6 @@ int user_context(unsigned long sp) return(stack != (unsigned long) current_thread); } -extern void remove_umid_dir(void); - -__uml_exitcall(remove_umid_dir); - extern exitcall_t __uml_exitcall_begin, __uml_exitcall_end; void do_uml_exitcalls(void) diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index a637e885c58..6f1a3a28811 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -12,6 +12,8 @@ #include "mode.h" #include "choose-mode.h" +void (*pm_power_off)(void); + #ifdef CONFIG_SMP static void kill_idlers(int me) { diff --git a/arch/um/kernel/sigio_user.c b/arch/um/kernel/sigio_user.c index 48b1f644b9a..62e5cfdf218 100644 --- a/arch/um/kernel/sigio_user.c +++ b/arch/um/kernel/sigio_user.c @@ -216,6 +216,8 @@ static int write_sigio_thread(void *unused) "err = %d\n", -n); } } + + return 0; } static int need_poll(int n) diff --git a/arch/um/kernel/signal_kern.c b/arch/um/kernel/signal_kern.c index 03618bd13d5..7b0e0e81c16 100644 --- a/arch/um/kernel/signal_kern.c +++ b/arch/um/kernel/signal_kern.c @@ -22,7 +22,6 @@ #include "asm/ucontext.h" #include "kern_util.h" #include "signal_kern.h" -#include "signal_user.h" #include "kern.h" #include "frame_kern.h" #include "sigcontext.h" diff --git a/arch/um/kernel/signal_user.c b/arch/um/kernel/signal_user.c deleted file mode 100644 index 62f457835fb..00000000000 --- a/arch/um/kernel/signal_user.c +++ /dev/null @@ -1,157 +0,0 @@ -/* - * Copyright (C) 2000 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdio.h> -#include <unistd.h> -#include <stdlib.h> -#include <signal.h> -#include <errno.h> -#include <stdarg.h> -#include <string.h> -#include <sys/mman.h> -#include "user_util.h" -#include "kern_util.h" -#include "user.h" -#include "signal_user.h" -#include "signal_kern.h" -#include "sysdep/sigcontext.h" -#include "sigcontext.h" - -void set_sigstack(void *sig_stack, int size) -{ - stack_t stack = ((stack_t) { .ss_flags = 0, - .ss_sp = (__ptr_t) sig_stack, - .ss_size = size - sizeof(void *) }); - - if(sigaltstack(&stack, NULL) != 0) - panic("enabling signal stack failed, errno = %d\n", errno); -} - -void set_handler(int sig, void (*handler)(int), int flags, ...) -{ - struct sigaction action; - va_list ap; - int mask; - - va_start(ap, flags); - action.sa_handler = handler; - sigemptyset(&action.sa_mask); - while((mask = va_arg(ap, int)) != -1){ - sigaddset(&action.sa_mask, mask); - } - va_end(ap); - action.sa_flags = flags; - action.sa_restorer = NULL; - if(sigaction(sig, &action, NULL) < 0) - panic("sigaction failed"); -} - -int change_sig(int signal, int on) -{ - sigset_t sigset, old; - - sigemptyset(&sigset); - sigaddset(&sigset, signal); - sigprocmask(on ? SIG_UNBLOCK : SIG_BLOCK, &sigset, &old); - return(!sigismember(&old, signal)); -} - -/* Both here and in set/get_signal we don't touch SIGPROF, because we must not - * disable profiling; it's safe because the profiling code does not interact - * with the kernel code at all.*/ - -static void change_signals(int type) -{ - sigset_t mask; - - sigemptyset(&mask); - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - sigaddset(&mask, SIGIO); - if(sigprocmask(type, &mask, NULL) < 0) - panic("Failed to change signal mask - errno = %d", errno); -} - -void block_signals(void) -{ - change_signals(SIG_BLOCK); -} - -void unblock_signals(void) -{ - change_signals(SIG_UNBLOCK); -} - -/* These are the asynchronous signals. SIGVTALRM and SIGARLM are handled - * together under SIGVTALRM_BIT. SIGPROF is excluded because we want to - * be able to profile all of UML, not just the non-critical sections. If - * profiling is not thread-safe, then that is not my problem. We can disable - * profiling when SMP is enabled in that case. - */ -#define SIGIO_BIT 0 -#define SIGVTALRM_BIT 1 - -static int enable_mask(sigset_t *mask) -{ - int sigs; - - sigs = sigismember(mask, SIGIO) ? 0 : 1 << SIGIO_BIT; - sigs |= sigismember(mask, SIGVTALRM) ? 0 : 1 << SIGVTALRM_BIT; - sigs |= sigismember(mask, SIGALRM) ? 0 : 1 << SIGVTALRM_BIT; - return(sigs); -} - -int get_signals(void) -{ - sigset_t mask; - - if(sigprocmask(SIG_SETMASK, NULL, &mask) < 0) - panic("Failed to get signal mask"); - return(enable_mask(&mask)); -} - -int set_signals(int enable) -{ - sigset_t mask; - int ret; - - sigemptyset(&mask); - if(enable & (1 << SIGIO_BIT)) - sigaddset(&mask, SIGIO); - if(enable & (1 << SIGVTALRM_BIT)){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } - - /* This is safe - sigprocmask is guaranteed to copy locally the - * value of new_set, do his work and then, at the end, write to - * old_set. - */ - if(sigprocmask(SIG_UNBLOCK, &mask, &mask) < 0) - panic("Failed to enable signals"); - ret = enable_mask(&mask); - sigemptyset(&mask); - if((enable & (1 << SIGIO_BIT)) == 0) - sigaddset(&mask, SIGIO); - if((enable & (1 << SIGVTALRM_BIT)) == 0){ - sigaddset(&mask, SIGVTALRM); - sigaddset(&mask, SIGALRM); - } - if(sigprocmask(SIG_BLOCK, &mask, NULL) < 0) - panic("Failed to block signals"); - - return(ret); -} - -/* - * 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 8de471b59c1..7a9fc16d71d 100644 --- a/arch/um/kernel/skas/Makefile +++ b/arch/um/kernel/skas/Makefile @@ -4,7 +4,7 @@ # 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 + syscall.o tlb.o uaccess.o USER_OBJS := process.o clone.o diff --git a/arch/um/kernel/skas/include/skas.h b/arch/um/kernel/skas/include/skas.h index daa2f85b684..01d489de398 100644 --- a/arch/um/kernel/skas/include/skas.h +++ b/arch/um/kernel/skas/include/skas.h @@ -22,7 +22,6 @@ extern int start_idle_thread(void *stack, void *switch_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 remove_sigstack(void); 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, diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 599d679bd4f..3b3955d8440 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -31,7 +31,6 @@ #include "proc_mm.h" #include "skas_ptrace.h" #include "chan_user.h" -#include "signal_user.h" #include "registers.h" #include "mem.h" #include "uml-config.h" @@ -69,7 +68,7 @@ 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]; + unsigned long regs[HOST_FRAME_SIZE]; if(ptrace(PTRACE_GETREGS, pid, 0, regs) < 0) printk("Failed to get registers from stub, " "errno = %d\n", errno); @@ -77,7 +76,7 @@ void wait_stub_done(int pid, int sig, char * fname) int i; printk("Stub registers -\n"); - for(i = 0; i < FRAME_SIZE; i++) + for(i = 0; i < HOST_FRAME_SIZE; i++) printk("\t%d - %lx\n", i, regs[i]); } panic("%s : failed to wait for SIGUSR1/SIGTRAP, " @@ -514,16 +513,6 @@ int start_idle_thread(void *stack, void *switch_buf_ptr, void **fork_buf_ptr) siglongjmp(**switch_buf, 1); } -void remove_sigstack(void) -{ - stack_t stack = ((stack_t) { .ss_flags = SS_DISABLE, - .ss_sp = NULL, - .ss_size = 0 }); - - if(sigaltstack(&stack, NULL) != 0) - panic("disabling signal stack failed, errno = %d\n", errno); -} - void initial_thread_cb_skas(void (*proc)(void *), void *arg) { sigjmp_buf here; diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 9c990253966..dc41c6dc2f3 100644 --- a/arch/um/kernel/skas/process_kern.c +++ b/arch/um/kernel/skas/process_kern.c @@ -14,7 +14,6 @@ #include "asm/atomic.h" #include "kern_util.h" #include "time_user.h" -#include "signal_user.h" #include "skas.h" #include "os.h" #include "user_util.h" @@ -119,7 +118,7 @@ int copy_thread_skas(int nr, unsigned long clone_flags, unsigned long sp, handler = new_thread_handler; } - new_thread(p->thread_info, &p->thread.mode.skas.switch_buf, + new_thread(task_stack_page(p), &p->thread.mode.skas.switch_buf, &p->thread.mode.skas.fork_buf, handler); return(0); } @@ -186,7 +185,7 @@ int start_uml_skas(void) init_task.thread.request.u.thread.proc = start_kernel_proc; init_task.thread.request.u.thread.arg = NULL; - return(start_idle_thread(init_task.thread_info, + return(start_idle_thread(task_stack_page(&init_task), &init_task.thread.mode.skas.switch_buf, &init_task.thread.mode.skas.fork_buf)); } diff --git a/arch/um/kernel/skas/trap_user.c b/arch/um/kernel/skas/trap_user.c deleted file mode 100644 index 9950a6716fe..00000000000 --- a/arch/um/kernel/skas/trap_user.c +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (C) 2002 - 2003 Jeff Dike (jdike@addtoit.com) - * Licensed under the GPL - */ - -#include <signal.h> -#include <errno.h> -#include "signal_user.h" -#include "user_util.h" -#include "kern_util.h" -#include "task.h" -#include "sigcontext.h" -#include "skas.h" -#include "ptrace_user.h" -#include "sysdep/ptrace.h" -#include "sysdep/ptrace_user.h" - -void sig_handler_common_skas(int sig, void *sc_ptr) -{ - struct sigcontext *sc = sc_ptr; - struct skas_regs *r; - struct signal_info *info; - int save_errno = errno; - int save_user; - - /* This is done because to allow SIGSEGV to be delivered inside a SEGV - * handler. This can happen in copy_user, and if SEGV is disabled, - * the process will die. - * XXX Figure out why this is better than SA_NODEFER - */ - if(sig == SIGSEGV) - change_sig(SIGSEGV, 1); - - r = &TASK_REGS(get_current())->skas; - save_user = r->is_user; - r->is_user = 0; - if ( sig == SIGFPE || sig == SIGSEGV || - sig == SIGBUS || sig == SIGILL || - sig == SIGTRAP ) { - GET_FAULTINFO_FROM_SC(r->faultinfo, sc); - } - - change_sig(SIGUSR1, 1); - info = &sig_info[sig]; - if(!info->is_irq) unblock_signals(); - - (*info->handler)(sig, (union uml_pt_regs *) r); - - errno = save_errno; - r->is_user = save_user; -} - -extern int ptrace_faultinfo; - -void user_signal(int sig, union uml_pt_regs *regs, int pid) -{ - struct signal_info *info; - int segv = ((sig == SIGFPE) || (sig == SIGSEGV) || (sig == SIGBUS) || - (sig == SIGILL) || (sig == SIGTRAP)); - - if (segv) - get_skas_faultinfo(pid, ®s->skas.faultinfo); - info = &sig_info[sig]; - (*info->handler)(sig, regs); - - unblock_signals(); -} - -/* - * 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/time.c b/arch/um/kernel/time.c index c40b611e3d9..8fa2ae7f302 100644 --- a/arch/um/kernel/time.c +++ b/arch/um/kernel/time.c @@ -14,9 +14,9 @@ #include "kern_util.h" #include "user.h" #include "process.h" -#include "signal_user.h" #include "time_user.h" #include "kern_constants.h" +#include "os.h" /* XXX This really needs to be declared and initialized in a kernel file since * it's in <linux/time.h> @@ -99,7 +99,8 @@ void uml_idle_timer(void) set_interval(ITIMER_REAL); } -extern int do_posix_clock_monotonic_gettime(struct timespec *tp); +extern void ktime_get_ts(struct timespec *ts); +#define do_posix_clock_monotonic_gettime(ts) ktime_get_ts(ts) void time_init(void) { @@ -114,8 +115,8 @@ void time_init(void) wall_to_monotonic.tv_nsec = -now.tv_nsec; } -/* Declared in linux/time.h, which can't be included here */ -extern void clock_was_set(void); +/* Defined in linux/ktimer.h, which can't be included here */ +#define clock_was_set() do { } while (0) void do_gettimeofday(struct timeval *tv) { diff --git a/arch/um/kernel/trap_kern.c b/arch/um/kernel/trap_kern.c index 0d4c10a7360..d56046c2aba 100644 --- a/arch/um/kernel/trap_kern.c +++ b/arch/um/kernel/trap_kern.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2001 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -26,9 +26,13 @@ #include "mconsole_kern.h" #include "mem.h" #include "mem_kern.h" +#include "sysdep/sigcontext.h" +#include "sysdep/ptrace.h" +#include "os.h" #ifdef CONFIG_MODE_SKAS #include "skas.h" #endif +#include "os.h" /* Note this is constrained to return 0, -EFAULT, -EACCESS, -ENOMEM by segv(). */ int handle_page_fault(unsigned long address, unsigned long ip, @@ -125,6 +129,25 @@ out_of_memory: goto out; } +void segv_handler(int sig, union uml_pt_regs *regs) +{ + struct faultinfo * fi = UPT_FAULTINFO(regs); + + if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ + bad_segv(*fi, UPT_IP(regs)); + return; + } + segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); +} + +struct kern_handlers handlinfo_kern = { + .relay_signal = relay_signal, + .winch = winch, + .bus_handler = relay_signal, + .page_fault = segv_handler, + .sigio_handler = sigio_handler, + .timer_handler = timer_handler +}; /* * We give a *copy* of the faultinfo in the regs to segv. * This must be done, since nesting SEGVs could overwrite diff --git a/arch/um/kernel/trap_user.c b/arch/um/kernel/trap_user.c deleted file mode 100644 index e9ccd6b8d3c..00000000000 --- a/arch/um/kernel/trap_user.c +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Copyright (C) 2000, 2001, 2002 Jeff Dike (jdike@karaya.com) - * Licensed under the GPL - */ - -#include <stdlib.h> -#include <errno.h> -#include <setjmp.h> -#include <signal.h> -#include <sys/time.h> -#include <sys/wait.h> -#include <asm/page.h> -#include <asm/unistd.h> -#include <asm/ptrace.h> -#include "init.h" -#include "sysdep/ptrace.h" -#include "sigcontext.h" -#include "sysdep/sigcontext.h" -#include "irq_user.h" -#include "signal_user.h" -#include "time_user.h" -#include "task.h" -#include "mode.h" -#include "choose-mode.h" -#include "kern_util.h" -#include "user_util.h" -#include "os.h" - -void kill_child_dead(int pid) -{ - kill(pid, SIGKILL); - kill(pid, SIGCONT); - do { - int n; - CATCH_EINTR(n = waitpid(pid, NULL, 0)); - if (n > 0) - kill(pid, SIGCONT); - else - break; - } while(1); -} - -void segv_handler(int sig, union uml_pt_regs *regs) -{ - struct faultinfo * fi = UPT_FAULTINFO(regs); - - if(UPT_IS_USER(regs) && !SEGV_IS_FIXABLE(fi)){ - bad_segv(*fi, UPT_IP(regs)); - return; - } - segv(*fi, UPT_IP(regs), UPT_IS_USER(regs), regs); -} - -void usr2_handler(int sig, union uml_pt_regs *regs) -{ - CHOOSE_MODE(syscall_handler_tt(sig, regs), (void) 0); -} - -struct signal_info sig_info[] = { - [ SIGTRAP ] { .handler = relay_signal, - .is_irq = 0 }, - [ SIGFPE ] { .handler = relay_signal, - .is_irq = 0 }, - [ SIGILL ] { .handler = relay_signal, - .is_irq = 0 }, - [ SIGWINCH ] { .handler = winch, - .is_irq = 1 }, - [ SIGBUS ] { .handler = bus_handler, - .is_irq = 0 }, - [ SIGSEGV] { .handler = segv_handler, - .is_irq = 0 }, - [ SIGIO ] { .handler = sigio_handler, - .is_irq = 1 }, - [ SIGVTALRM ] { .handler = timer_handler, - .is_irq = 1 }, - [ SIGALRM ] { .handler = timer_handler, - .is_irq = 1 }, - [ SIGUSR2 ] { .handler = usr2_handler, - .is_irq = 0 }, -}; - -void do_longjmp(void *b, int val) -{ - sigjmp_buf *buf = b; - - siglongjmp(*buf, val); -} - -/* - * 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 065b504a653..8f40e483873 100644 --- a/arch/um/kernel/tt/exec_kern.c +++ b/arch/um/kernel/tt/exec_kern.c @@ -14,7 +14,6 @@ #include "kern_util.h" #include "irq_user.h" #include "time_user.h" -#include "signal_user.h" #include "mem_user.h" #include "os.h" #include "tlb.h" @@ -40,7 +39,7 @@ void flush_thread_tt(void) do_exit(SIGKILL); } - new_pid = start_fork_tramp(current->thread_info, stack, 0, exec_tramp); + new_pid = start_fork_tramp(task_stack_page(current), stack, 0, exec_tramp); if(new_pid < 0){ printk(KERN_ERR "flush_thread : new thread failed, errno = %d\n", diff --git a/arch/um/kernel/tt/process_kern.c b/arch/um/kernel/tt/process_kern.c index cfaa373a6e7..62535303aa2 100644 --- a/arch/um/kernel/tt/process_kern.c +++ b/arch/um/kernel/tt/process_kern.c @@ -13,7 +13,6 @@ #include "asm/ptrace.h" #include "asm/tlbflush.h" #include "irq_user.h" -#include "signal_user.h" #include "kern_util.h" #include "user_util.h" #include "os.h" @@ -37,7 +36,7 @@ void switch_to_tt(void *prev, void *next) from = prev; to = next; - cpu = from->thread_info->cpu; + cpu = task_thread_info(from)->cpu; if(cpu == 0) forward_interrupts(to->thread.mode.tt.extern_pid); #ifdef CONFIG_SMP @@ -254,7 +253,7 @@ int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, clone_flags &= CLONE_VM; p->thread.temp_stack = stack; - new_pid = start_fork_tramp(p->thread_info, stack, clone_flags, tramp); + new_pid = start_fork_tramp(task_stack_page(p), stack, clone_flags, tramp); if(new_pid < 0){ printk(KERN_ERR "copy_thread : clone failed - errno = %d\n", -new_pid); @@ -344,7 +343,7 @@ int do_proc_op(void *t, int proc_id) pid = thread->request.u.exec.pid; do_exec(thread->mode.tt.extern_pid, pid); thread->mode.tt.extern_pid = pid; - cpu_tasks[task->thread_info->cpu].pid = pid; + cpu_tasks[task_thread_info(task)->cpu].pid = pid; break; case OP_FORK: attach_process(thread->request.u.fork.pid); @@ -426,7 +425,7 @@ int start_uml_tt(void) int pages; pages = (1 << CONFIG_KERNEL_STACK_ORDER); - sp = (void *) ((unsigned long) init_task.thread_info) + + sp = task_stack_page(&init_task) + pages * PAGE_SIZE - sizeof(unsigned long); return(tracer(start_kernel_proc, sp)); } diff --git a/arch/um/kernel/tt/tracer.c b/arch/um/kernel/tt/tracer.c index d11e7399d7a..71daae24e48 100644 --- a/arch/um/kernel/tt/tracer.c +++ b/arch/um/kernel/tt/tracer.c @@ -19,7 +19,6 @@ #include "sigcontext.h" #include "sysdep/sigcontext.h" #include "os.h" -#include "signal_user.h" #include "user_util.h" #include "mem_user.h" #include "process.h" diff --git a/arch/um/kernel/tt/trap_user.c b/arch/um/kernel/tt/trap_user.c index fc108615bea..a414c529fbc 100644 --- a/arch/um/kernel/tt/trap_user.c +++ b/arch/um/kernel/tt/trap_user.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -8,18 +8,18 @@ #include <signal.h> #include "sysdep/ptrace.h" #include "sysdep/sigcontext.h" -#include "signal_user.h" #include "user_util.h" #include "kern_util.h" #include "task.h" #include "tt.h" +#include "os.h" void sig_handler_common_tt(int sig, void *sc_ptr) { struct sigcontext *sc = sc_ptr; struct tt_regs save_regs, *r; - struct signal_info *info; int save_errno = errno, is_user; + void (*handler)(int, union uml_pt_regs *); /* This is done because to allow SIGSEGV to be delivered inside a SEGV * handler. This can happen in copy_user, and if SEGV is disabled, @@ -40,10 +40,14 @@ void sig_handler_common_tt(int sig, void *sc_ptr) if(sig != SIGUSR2) r->syscall = -1; - info = &sig_info[sig]; - if(!info->is_irq) unblock_signals(); + handler = sig_info[sig]; + + /* unblock SIGALRM, SIGVTALRM, SIGIO if sig isn't IRQ signal */ + if (sig != SIGIO && sig != SIGWINCH && + sig != SIGVTALRM && sig != SIGALRM) + unblock_signals(); - (*info->handler)(sig, (union uml_pt_regs *) r); + handler(sig, (union uml_pt_regs *) r); if(is_user){ interrupt_end(); diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index 142a9493912..e2d3ca445ef 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -1,4 +1,4 @@ -/* +/* * Copyright (C) 2000, 2002 Jeff Dike (jdike@karaya.com) * Licensed under the GPL */ @@ -146,8 +146,8 @@ void set_cmdline(char *cmd) if(CHOOSE_MODE(honeypot, 0)) return; - umid = get_umid(1); - if(umid != NULL){ + umid = get_umid(); + if(*umid != '\0'){ snprintf(argv1_begin, (argv1_end - argv1_begin) * sizeof(*ptr), "(%s) ", umid); @@ -243,10 +243,6 @@ static int __init mode_tt_setup(char *line, int *add) return(0); } -#else - -#error Either CONFIG_MODE_TT or CONFIG_MODE_SKAS must be enabled - #endif #endif #endif @@ -363,6 +359,11 @@ int linux_main(int argc, char **argv) uml_start = CHOOSE_MODE_PROC(set_task_sizes_tt, set_task_sizes_skas, 0, &host_task_size, &task_size); + /* + * Setting up handlers to 'sig_info' struct + */ + os_fill_handlinfo(handlinfo_kern); + brk_start = (unsigned long) sbrk(0); CHOOSE_MODE_PROC(before_mem_tt, before_mem_skas, brk_start); /* Increase physical memory size for exec-shield users diff --git a/arch/um/kernel/umid.c b/arch/um/kernel/umid.c index 0b21d59ba0c..4eaee823bfd 100644 --- a/arch/um/kernel/umid.c +++ b/arch/um/kernel/umid.c @@ -3,61 +3,30 @@ * Licensed under the GPL */ -#include <stdio.h> -#include <unistd.h> -#include <errno.h> -#include <string.h> -#include <stdlib.h> -#include <dirent.h> -#include <signal.h> -#include <sys/stat.h> -#include <sys/param.h> -#include "user.h" -#include "umid.h" +#include "asm/errno.h" #include "init.h" #include "os.h" -#include "user_util.h" -#include "choose-mode.h" +#include "kern.h" +#include "linux/kernel.h" -#define UMID_LEN 64 -#define UML_DIR "~/.uml/" - -/* Changed by set_umid and make_umid, which are run early in boot */ -static char umid[UMID_LEN] = { 0 }; - -/* Changed by set_uml_dir and make_uml_dir, which are run early in boot */ -static char *uml_dir = UML_DIR; - -/* Changed by set_umid */ -static int umid_is_random = 1; +/* Changed by set_umid_arg */ 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, ...)); - -static int __init set_umid(char *name, int is_random, - int (*printer)(const char *fmt, ...)) +static int __init set_umid_arg(char *name, int *add) { - if(umid_inited){ - (*printer)("Unique machine name can't be set twice\n"); - return(-1); - } + int err; - if(strlen(name) > UMID_LEN - 1) - (*printer)("Unique machine name is being truncated to %d " - "characters\n", UMID_LEN); - strlcpy(umid, name, sizeof(umid)); + if(umid_inited) + return 0; - umid_is_random = is_random; - umid_inited = 1; - return 0; -} - -static int __init set_umid_arg(char *name, int *add) -{ *add = 0; - return(set_umid(name, 0, printf)); + err = set_umid(name); + if(err == -EEXIST) + printf("umid '%s' already in use\n", name); + else if(!err) + umid_inited = 1; + + return 0; } __uml_setup("umid=", set_umid_arg, @@ -66,265 +35,3 @@ __uml_setup("umid=", set_umid_arg, " is used for naming the pid file and management console socket.\n\n" ); -int __init umid_file_name(char *name, char *buf, int len) -{ - int n; - - if(!umid_inited && make_umid(printk)) return(-1); - - n = strlen(uml_dir) + strlen(umid) + strlen(name) + 1; - if(n > len){ - printk("umid_file_name : buffer too short\n"); - return(-1); - } - - sprintf(buf, "%s%s/%s", uml_dir, umid, name); - return(0); -} - -extern int tracing_pid; - -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; - - 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; - } - - sprintf(pid, "%d\n", os_getpid()); - n = os_write_file(fd, pid, strlen(pid)); - if(n != strlen(pid)) - printf("Write of pid file failed - err = %d\n", -n); - os_close_file(fd); -} - -static int actually_do_remove(char *dir) -{ - DIR *directory; - struct dirent *ent; - int len; - char file[256]; - - directory = opendir(dir); - if(directory == NULL){ - printk("actually_do_remove : couldn't open directory '%s', " - "errno = %d\n", dir, errno); - return(1); - } - while((ent = readdir(directory)) != NULL){ - if(!strcmp(ent->d_name, ".") || !strcmp(ent->d_name, "..")) - continue; - len = strlen(dir) + sizeof("/") + strlen(ent->d_name) + 1; - if(len > sizeof(file)){ - printk("Not deleting '%s' from '%s' - name too long\n", - ent->d_name, dir); - continue; - } - sprintf(file, "%s/%s", dir, ent->d_name); - if(unlink(file) < 0){ - printk("actually_do_remove : couldn't remove '%s' " - "from '%s', errno = %d\n", ent->d_name, dir, - errno); - return(1); - } - } - if(rmdir(dir) < 0){ - printk("actually_do_remove : couldn't rmdir '%s', " - "errno = %d\n", dir, errno); - return(1); - } - return(0); -} - -void remove_umid_dir(void) -{ - char dir[strlen(uml_dir) + UMID_LEN + 1]; - if (!umid_owned) - return; - - sprintf(dir, "%s%s", uml_dir, umid); - actually_do_remove(dir); -} - -char *get_umid(int only_if_set) -{ - if(only_if_set && umid_is_random) - return NULL; - return umid; -} - -static int not_dead_yet(char *dir) -{ - char file[strlen(uml_dir) + UMID_LEN + sizeof("/pid\0")]; - char pid[sizeof("nnnnn\0")], *end; - int dead, fd, p, n; - - sprintf(file, "%s/pid", dir); - dead = 0; - fd = os_open_file(file, of_read(OPENFLAGS()), 0); - if(fd < 0){ - if(fd != -ENOENT){ - printk("not_dead_yet : couldn't open pid file '%s', " - "err = %d\n", file, -fd); - return(1); - } - dead = 1; - } - if(fd > 0){ - n = os_read_file(fd, pid, sizeof(pid)); - if(n < 0){ - printk("not_dead_yet : couldn't read pid file '%s', " - "err = %d\n", file, -n); - return(1); - } - p = strtoul(pid, &end, 0); - if(end == pid){ - printk("not_dead_yet : couldn't parse pid file '%s', " - "errno = %d\n", file, errno); - dead = 1; - } - if(((kill(p, 0) < 0) && (errno == ESRCH)) || - (p == CHOOSE_MODE(tracing_pid, os_getpid()))) - dead = 1; - } - if(!dead) - return(1); - return(actually_do_remove(dir)); -} - -static int __init set_uml_dir(char *name, int *add) -{ - if((strlen(name) > 0) && (name[strlen(name) - 1] != '/')){ - uml_dir = malloc(strlen(name) + 2); - if(uml_dir == NULL){ - printf("Failed to malloc uml_dir - error = %d\n", - errno); - uml_dir = name; - /* Return 0 here because do_initcalls doesn't look at - * the return value. - */ - return(0); - } - sprintf(uml_dir, "%s/", name); - } - else uml_dir = name; - return(0); -} - -static int __init make_uml_dir(void) -{ - char dir[MAXPATHLEN + 1] = { '\0' }; - int len; - - if(*uml_dir == '~'){ - char *home = getenv("HOME"); - - if(home == NULL){ - printf("make_uml_dir : no value in environment for " - "$HOME\n"); - exit(1); - } - strlcpy(dir, home, sizeof(dir)); - uml_dir++; - } - strlcat(dir, uml_dir, sizeof(dir)); - len = strlen(dir); - if (len > 0 && dir[len - 1] != '/') - strlcat(dir, "/", sizeof(dir)); - - uml_dir = malloc(strlen(dir) + 1); - if (uml_dir == NULL) { - printf("make_uml_dir : malloc failed, errno = %d\n", errno); - exit(1); - } - strcpy(uml_dir, dir); - - if((mkdir(uml_dir, 0777) < 0) && (errno != EEXIST)){ - printf("Failed to mkdir %s: %s\n", uml_dir, strerror(errno)); - return(-1); - } - return 0; -} - -static int __init make_umid(int (*printer)(const char *fmt, ...)) -{ - int fd, err; - char tmp[strlen(uml_dir) + UMID_LEN + 1]; - - strlcpy(tmp, uml_dir, sizeof(tmp)); - - if(!umid_inited){ - strcat(tmp, "XXXXXX"); - fd = mkstemp(tmp); - if(fd < 0){ - (*printer)("make_umid - mkstemp(%s) failed: %s\n", - tmp,strerror(errno)); - return(1); - } - - os_close_file(fd); - /* There's a nice tiny little race between this unlink and - * the mkdir below. It'd be nice if there were a mkstemp - * for directories. - */ - unlink(tmp); - set_umid(&tmp[strlen(uml_dir)], 1, printer); - } - - sprintf(tmp, "%s%s", uml_dir, umid); - - err = mkdir(tmp, 0777); - if(err < 0){ - 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); - } - } - if(err < 0){ - (*printer)("Failed to create %s - errno = %d\n", umid, errno); - return(-1); - } - - umid_owned = 1; - return 0; -} - -__uml_setup("uml_dir=", set_uml_dir, -"uml_dir=<directory>\n" -" The location to place the pid and umid files.\n\n" -); - -static int __init make_umid_setup(void) -{ - /* one function with the ordering we need ... */ - make_uml_dir(); - make_umid(printf); - create_pid_file(); - return 0; -} -__uml_postsetup(make_umid_setup); - -/* - * 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: - */ |