void syscall_handler_tt(int sig, struct pt_regs *regs) { void *sc; long result; int syscall; #ifdef CONFIG_SYSCALL_DEBUG int index; index = record_syscall_start(syscall); #endif sc = UPT_SC(®s->regs); SC_START_SYSCALL(sc); syscall_trace(®s->regs, 0); current->thread.nsyscalls++; nsyscalls++; syscall = UPT_SYSCALL_NR(®s->regs); if((syscall >= NR_syscalls) || (syscall < 0)) result = -ENOSYS; else result = EXECUTE_SYSCALL(syscall, regs); /* regs->sc may have changed while the system call ran (there may * have been an interrupt or segfault), so it needs to be refreshed. */ UPT_SC(®s->regs) = sc; SC_SET_SYSCALL_RETURN(sc, result); syscall_trace(®s->regs, 1); #ifdef CONFIG_SYSCALL_DEBUG record_syscall_end(index, result); #endif }
int copy_thread_tt(int nr, unsigned long clone_flags, unsigned long sp, unsigned long stack_top, struct task_struct * p, struct pt_regs *regs) { int (*tramp)(void *); int new_pid, err; unsigned long stack; if(current->thread.forking) tramp = fork_tramp; else { tramp = new_thread_proc; p->thread.request.u.thread = current->thread.request.u.thread; } err = os_pipe(p->thread.mode.tt.switch_pipe, 1, 1); if(err < 0){ printk("copy_thread : pipe failed, err = %d\n", -err); return(err); } stack = alloc_stack(0, 0); if(stack == 0){ printk(KERN_ERR "copy_thread : failed to allocate " "temporary stack\n"); return(-ENOMEM); } clone_flags &= CLONE_VM; p->thread.temp_stack = stack; 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); return(new_pid); } if(current->thread.forking){ sc_to_sc(UPT_SC(&p->thread.regs.regs), UPT_SC(®s->regs)); SC_SET_SYSCALL_RETURN(UPT_SC(&p->thread.regs.regs), 0); if(sp != 0) SC_SP(UPT_SC(&p->thread.regs.regs)) = sp; } p->thread.mode.tt.extern_pid = new_pid; current->thread.request.op = OP_FORK; current->thread.request.u.fork.pid = new_pid; os_usr1_process(os_getpid()); /* Enable the signal and then disable it to ensure that it is handled * here, and nowhere else. */ change_sig(SIGUSR1, 1); change_sig(SIGUSR1, 0); err = 0; return(err); }
static int copy_sc_to_user(struct sigcontext __user *to, struct _fpstate __user *fp, struct pt_regs *from, unsigned long sp) { return CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), sizeof(*fp), sp), copy_sc_to_user_skas(to, fp, from, sp)); }
static int copy_sc_to_user(struct sigcontext *to, struct _fpstate *fp, struct pt_regs *from) { return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), sizeof(*fp)), copy_sc_to_user_skas(to, fp, from))); }
void do_boot_timer_handler(struct sigcontext * sc) { struct pt_regs regs; CHOOSE_MODE((void) (UPT_SC(®s.regs) = sc), (void) (regs.regs.skas.is_user = 0)); do_timer(®s); }
static int copy_sc_from_user(struct pt_regs *to, void __user *from) { int ret; ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, sizeof(struct _fpstate)), copy_sc_from_user_skas(to, from)); return ret; }
static int copy_sc_from_user(struct pt_regs *to, void *from, struct arch_frame_data *arch) { int ret; ret = CHOOSE_MODE(copy_sc_from_user_tt(UPT_SC(&to->regs), from, arch), copy_sc_from_user_skas(&to->regs, from)); return(ret); }
static int copy_sc_to_user(void *to, void *fp, struct pt_regs *from, struct arch_frame_data *arch) { return(CHOOSE_MODE(copy_sc_to_user_tt(to, fp, UPT_SC(&from->regs), arch), copy_sc_to_user_skas(userspace_pid[0], to, fp, &from->regs, current->thread.cr2, current->thread.err))); }
void timer_handler(int sig, union uml_pt_regs *regs) { local_irq_disable(); irq_enter(); 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 void new_thread_handler(int sig) { unsigned long disable; int (*fn)(void *); void *arg; fn = current->thread.request.u.thread.proc; arg = current->thread.request.u.thread.arg; UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); disable = (1 << (SIGVTALRM - 1)) | (1 << (SIGALRM - 1)) | (1 << (SIGIO - 1)) | (1 << (SIGPROF - 1)); SC_SIGMASK(UPT_SC(¤t->thread.regs.regs)) &= ~disable; suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); force_flush_all(); if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; init_new_thread_signals(1); enable_timer(); free_page(current->thread.temp_stack); set_cmdline("(kernel thread)"); change_sig(SIGUSR1, 1); change_sig(SIGVTALRM, 1); change_sig(SIGPROF, 1); local_irq_enable(); if(!run_kernel_thread(fn, arg, ¤t->thread.exec_buf)) do_exit(0); /* XXX No set_user_mode here because a newly execed process will * immediately segfault on its non-existent IP, coming straight back * to the signal handler, which will call set_user_mode on its way * out. This should probably change since it's confusing. */ }
void finish_fork_handler(int sig) { UPT_SC(¤t->thread.regs.regs) = (void *) (&sig + 1); suspend_new_thread(current->thread.mode.tt.switch_pipe[0]); force_flush_all(); if(current->thread.prev_sched != NULL) schedule_tail(current->thread.prev_sched); current->thread.prev_sched = NULL; enable_timer(); change_sig(SIGVTALRM, 1); local_irq_enable(); if(current->mm != current->parent->mm) protect_memory(uml_reserved, high_physmem - uml_reserved, 1, 1, 0, 1); task_protections((unsigned long) current_thread); free_page(current->thread.temp_stack); local_irq_disable(); change_sig(SIGUSR1, 0); set_user_mode(current); }