X-Git-Url: http://git.onelab.eu/?a=blobdiff_plain;f=arch%2Fum%2Fkernel%2Fskas%2Fprocess_kern.c;h=2135eaf98a938122e87a269aee5f11f3cf0199de;hb=43bc926fffd92024b46cafaf7350d669ba9ca884;hp=5418f08628893ba3557e316091170e5d9e5a074a;hpb=c7b5ebbddf7bcd3651947760f423e3783bbe6573;p=linux-2.6.git diff --git a/arch/um/kernel/skas/process_kern.c b/arch/um/kernel/skas/process_kern.c index 5418f0862..2135eaf98 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,81 +13,15 @@ #include "asm/uaccess.h" #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" #include "tlb.h" -#include "frame.h" #include "kern.h" #include "mode.h" -#include "proc_mm.h" - -static atomic_t using_sysemu; -int sysemu_supported; - -void set_using_sysemu(int value) -{ - atomic_set(&using_sysemu, sysemu_supported && value); -} - -int get_using_sysemu(void) -{ - return atomic_read(&using_sysemu); -} +#include "registers.h" -int proc_read_sysemu(char *buf, char **start, off_t offset, int size,int *eof, void *data) -{ - if (snprintf(buf, size, "%d\n", get_using_sysemu()) < size) /*No overflow*/ - *eof = 1; - - return strlen(buf); -} - -int proc_write_sysemu(struct file *file,const char *buf, unsigned long count,void *data) -{ - char tmp[2]; - - if (copy_from_user(tmp, buf, 1)) - return -EFAULT; - - if (tmp[0] == '0' || tmp[0] == '1') - set_using_sysemu(tmp[0] - '0'); - return count; /*We use the first char, but pretend to write everything*/ -} - -int __init make_proc_sysemu(void) -{ - struct proc_dir_entry *ent; - if (mode_tt || !sysemu_supported) - return 0; - - ent = create_proc_entry("sysemu", 0600, &proc_root); - - if (ent == NULL) - { - printk("Failed to register /proc/sysemu\n"); - return(0); - } - - ent->read_proc = proc_read_sysemu; - ent->write_proc = proc_write_sysemu; - - return 0; -} - -late_initcall(make_proc_sysemu); - -int singlestepping_skas(void) -{ - int ret = current->ptrace & PT_DTRACE; - - current->ptrace &= ~PT_DTRACE; - return(ret); -} - -void *switch_to_skas(void *prev, void *next) +void switch_to_skas(void *prev, void *next) { struct task_struct *from, *to; @@ -98,16 +32,13 @@ void *switch_to_skas(void *prev, void *next) if(current->pid == 0) switch_timers(0); - to->thread.prev_sched = from; - set_current(to); - - switch_threads(&from->thread.mode.skas.switch_buf, + switch_threads(&from->thread.mode.skas.switch_buf, to->thread.mode.skas.switch_buf); + arch_switch_to_skas(current->thread.prev_sched, current); + if(current->pid == 0) switch_timers(1); - - return(current->thread.prev_sched); } extern void schedule_tail(struct task_struct *prev); @@ -119,8 +50,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) @@ -131,8 +62,11 @@ void new_thread_handler(int sig) * 0 if it just exits */ n = run_kernel_thread(fn, arg, ¤t->thread.exec_buf); - if(n == 1) + if(n == 1){ + /* Handle any immediate reschedules or signals */ + interrupt_end(); userspace(¤t->thread.regs.regs); + } else do_exit(0); } @@ -146,14 +80,10 @@ void release_thread_skas(struct task_struct *task) { } -void exit_thread_skas(void) -{ -} - 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(); @@ -161,60 +91,57 @@ void fork_handler(int sig) panic("blech"); schedule_tail(current->thread.prev_sched); + + /* XXX: if interrupt_end() calls schedule, this call to + * arch_switch_to_skas isn't needed. We could want to apply this to + * improve performance. -bb */ + arch_switch_to_skas(current->thread.prev_sched, current); + current->thread.prev_sched = NULL; +/* 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); if(current->thread.forking){ - memcpy(&p->thread.regs.regs.skas, - ¤t->thread.regs.regs.skas, + memcpy(&p->thread.regs.regs.skas, ®s->regs.skas, sizeof(p->thread.regs.regs.skas)); REGS_SET_SYSCALL_RETURN(p->thread.regs.regs.skas.regs, 0); if(sp != 0) REGS_SP(p->thread.regs.regs.skas.regs) = sp; handler = fork_handler; + + arch_copy_thread(¤t->thread.arch, &p->thread.arch); } else { - memcpy(p->thread.regs.regs.skas.regs, exec_regs, - sizeof(p->thread.regs.regs.skas.regs)); - memcpy(p->thread.regs.regs.skas.fp, exec_fp_regs, - sizeof(p->thread.regs.regs.skas.fp)); - memcpy(p->thread.regs.regs.skas.xfp, exec_fpx_regs, - sizeof(p->thread.regs.regs.skas.xfp)); + init_thread_registers(&p->thread.regs.regs); p->thread.request.u.thread = current->thread.request.u.thread; 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); } -int new_mm(int from) +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); return(fd); } @@ -243,17 +170,18 @@ static int start_kernel_proc(void *unused) return(0); } +extern int userspace_pid[]; + int start_uml_skas(void) { - start_userspace(0); - capture_signal_stack(); + if(proc_mm) + userspace_pid[0] = start_userspace(0); init_new_thread_signals(1); - uml_idle_timer(); 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)); } @@ -270,13 +198,30 @@ int thread_pid_skas(struct task_struct *task) return(userspace_pid[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: - */ +void kill_off_processes_skas(void) +{ + if(proc_mm) +#warning need to loop over userspace_pids in kill_off_processes_skas + os_kill_ptraced_process(userspace_pid[0], 1); + else { + struct task_struct *p; + int pid, me; + + me = os_getpid(); + for_each_process(p){ + if(p->mm == NULL) + continue; + + pid = p->mm->context.skas.id.u.pid; + os_kill_ptraced_process(pid, 1); + } + } +} + +unsigned long current_stub_stack(void) +{ + if(current->mm == NULL) + return(0); + + return(current->mm->context.skas.id.stack); +}